Windows Installer : Python3 + 64bit
authorEdouard Tisserant <edouard.tisserant@gmail.com>
Thu, 28 Sep 2023 22:29:30 +0200
changeset 120 02e37d9e96a9
parent 119 6be785b8cc85
child 121 9dd76a5bbc2a
Windows Installer : Python3 + 64bit

Upgrade of windows installer build system:
- revisions.txt supports "local" to point to local working directories
- msys2 ucrt64 64b runtine
- use requirements.txt
- most python packages from msys2 repo
- still use pip/wine for other python packages
- some cleanup in Makfile code, removing dead code
- CANopen, Modbus and OPC-UA not included... to be continued.
.dockerignore
.gitignore
Dockerfile
Makefile
README.md
create_docker_container.sh
distfiles/msys2-base-x86_64-20230718.tar.xz.md5
install.nsi
pacman-6.0.0-nogpg-relative_conf.patch
provision_focal64.sh
provision_jammy64.sh
revisions.txt
win32.mk
windows_installer.mk
winpaths.py
--- a/.dockerignore	Fri Mar 03 19:26:38 2023 +0100
+++ b/.dockerignore	Thu Sep 28 22:29:30 2023 +0200
@@ -1,2 +1,2 @@
 *
-!provision_focal64.sh
+!provision_jammy64.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Thu Sep 28 22:29:30 2023 +0200
@@ -0,0 +1,2 @@
+distfiles/*
+!distfiles/*.md5
\ No newline at end of file
--- a/Dockerfile	Fri Mar 03 19:26:38 2023 +0100
+++ b/Dockerfile	Thu Sep 28 22:29:30 2023 +0200
@@ -1,24 +1,26 @@
 # Dockerfile to setup beremiz_public_dist build container
 
-FROM ubuntu:focal
+FROM ubuntu:jammy
 
 ENV TERM xterm-256color
 
-COPY provision_focal64.sh .
-
-RUN ./provision_focal64.sh
-
 ENV LANG en_US.UTF-8
 ENV LANGUAGE en_US:en
 ENV LC_ALL en_US.UTF-8
 
-ARG UNAME=devel
+ARG UNAME=runner
 ENV UNAME ${UNAME}
 ARG UID=1000
 ARG GID=1000
 RUN groupadd -g $GID $UNAME
 RUN useradd -m -u $UID -g $GID -s /bin/bash $UNAME
 
+USER root
+
+COPY ./provision_jammy64.sh .
+
+RUN ./provision_jammy64.sh
+
 # easy to remember 'build' alias to invoke main makefile
 ARG OWNDIRBASENAME=beremiz_public_dist
 ENV OWNDIRBASENAME ${OWNDIRBASENAME}
--- a/Makefile	Fri Mar 03 19:26:38 2023 +0100
+++ b/Makefile	Thu Sep 28 22:29:30 2023 +0200
@@ -11,9 +11,7 @@
 DIST ?= win32
 
 src := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
-HGREMOTE ?= REMOTE_HG_DISABLED
-HGROOT ?= $(abspath $(src)/..)
-GITROOT := $(HGROOT)
+WORKSPACE ?= $(abspath $(src)/..)
 CPUS := `cat /proc/cpuinfo | grep -e 'processor\W*:\W*[[:digit:]]*' | nl -n ln | tail -n1 | cut -f1`
 
 distfiles = $(src)/distfiles
@@ -21,9 +19,8 @@
 tmp := $(shell rm -rf $${TMPDIR:-/tmp}/beremiz_dist_build_tmp.* ; mktemp -d -t beremiz_dist_build_tmp.XXXXXXXXXX)
 
 define hg_get_archive
-	test -d $(HGROOT)/`basename $(1)` || hg --cwd $(HGROOT) clone $(HGREMOTE)`basename $(1)`;\
-	hg -R $(HGROOT)/`basename $(1)` archive $(2) $(1);\
-	hg -R $(HGROOT)/`basename $(1)` id -i | sed 's/\+//' > $(1)/revision;
+	hg -R $(WORKSPACE)/`basename $(1)` archive $(2) $(1);\
+	hg -R $(WORKSPACE)/`basename $(1)` id -i | sed 's/\+//' > $(1)/revision;
 endef
 
 define get_src_hg
@@ -32,37 +29,32 @@
 endef
 
 define get_src_git
-	rm -rf $(1)
-	test -d $(GITROOT)/`basename $(1)` || git clone $(3) $(GITROOT)/`basename $(1)`
-	mkdir $(1)
-	(cd $(GITROOT)/`basename $(1)`; git archive --format=tar $(2)) | tar -C $(1) -x
 endef
 
 define get_src_http
 	dld=$(distfiles)/`echo $(2) | tr ' ()' '___'`;( ( [ -f $$dld ] || wget $(1)/$(2) -O $$dld ) && ( [ ! -f $$dld.md5 ] && (cd $(distfiles);md5sum `basename $$dld`) > $$dld.md5 || (cd $(distfiles);md5sum -c `basename $$dld.md5`) ) ) &&
 endef
 
-get_src_pypi=$(call get_src_http,https://pypi.python.org/packages/$(1),$(2))
-
-get_src_sf=$(call get_src_http,https://$(sfmirror).sourceforge.net/project/$(1),$(2))
-
 ifneq ("$(DIST)","")
 include $(src)/$(DIST).mk
 endif
 
-OWN_PROJECTS=beremiz matiec canfestival Modbus
+FROM_SOURCE_PROJECTS=beremiz matiec $(DIST_FROM_SOURCE_PROJECTS)
 
 define get_revision
 $(1)_revision?=$(lastword $(shell grep $(1) $(src)/revisions.txt))
 endef
-$(foreach project,$(OWN_PROJECTS),$(eval $(call get_revision,$(project))))
+$(foreach project,$(FROM_SOURCE_PROJECTS),$(eval $(call get_revision,$(project))))
+
+tar_opts=--absolute-names --exclude=.hg --exclude=.git --exclude=.*.pyc --exclude=.*.swp --exclude=__pycache__
 
 define get_revisionid
-ifeq ($(origin $(1)_revisionid), undefined)
-$(1)_revisionid?=$(shell hg -R $(HGROOT)/$(1) id -i -r $($(1)_revision))
-endif
+$(1)_revisionid ?=\
+	$(if $(filter local, $($(1)_revision)),\
+		$(shell tar $(tar_opts) -P -c $(WORKSPACE)/$(1) | sha1sum | cut -d ' ' -f 1),\
+		$(1)_revisionid?=$$(shell hg -R $(WORKSPACE)/$(1) id -i -r $($(1)_revision)))
 endef
-$(foreach project,$(OWN_PROJECTS),$(eval $(call get_revisionid,$(project))))
+$(foreach project,$(FROM_SOURCE_PROJECTS),$(eval $(call get_revisionid,$(project))))
 
 sources:
 	mkdir -p sources
@@ -72,14 +64,19 @@
 	touch $$@
 
 sources/$(1)_$($(1)_revisionid): | sources
+	rm -rf sources/$(1)*
+ifeq ($($(1)_revision),local)
+	echo "Copy local source code for $(1)_$($(1)_revisionid)"
+	tar -C $(WORKSPACE) $(tar_opts) -P -c $(1) | tar -C sources -x
+else
 	echo "Checkout HG source $(1)_$($(1)_revisionid)"
-	rm -rf sources/$(1)*
 	$(call get_src_hg,sources/$(1),-r $($(1)_revisionid))
+endif
 	touch $$@
 endef
-$(foreach project,$(OWN_PROJECTS),$(eval $(call make_src_rule,$(project))))
+$(foreach project,$(FROM_SOURCE_PROJECTS),$(eval $(call make_src_rule,$(project))))
 
-own_sources: $(foreach project,$(OWN_PROJECTS), sources/$(project)_src)
+own_sources: $(foreach project,$(FROM_SOURCE_PROJECTS), sources/$(project)_src)
 	touch $@
 
 all_sources: own_sources sources/open62541_src
@@ -93,15 +90,18 @@
 	
 
 define show_revision_details
-echo -n $(1) "revision is: "; hg -R $(HGROOT)/$(1) id -r $($(1)_revisionid);
+	$(if $(filter local, $($(1)_revision)),\
+		echo -n $(1) "state is: "; test -d .hg \
+			&& (hg -R $(WORKSPACE)/$(1) id; echo; hg -R $(WORKSPACE)/$(1) st) \
+			|| (git -C $(WORKSPACE)/$(1) show --pretty=format:'%P' -s; echo; git -C $(WORKSPACE)/$(1) status --porcelain);,\
+		echo -n $(1) "revision is: "; hg -R $(WORKSPACE)/$(1) id -r $($(1)_revisionid); )
 endef
 
 revisions.txt: $(src)/revisions.txt own_sources
 	echo "Generate revisions.txt"
 	echo "\n******* PACKAGE REVISIONS ********\n" > revisions.txt
-	(echo -n "beremiz_public_dist revision is: "; hg -R $(src) id;) >> revisions.txt
-	($(foreach project,$(OWN_PROJECTS),$(call show_revision_details,$(project)))) >> revisions.txt
-	bash -c 'hg -R $(src) st | ( if read ; then echo -e "\n******* beremiz_public_dist IS MODIFIED ********\n" ; hg -R $(src) st ; fi ) >> revisions.txt'
+	(echo -n "beremiz_public_dist revision is: "; test -d .hg && (hg -R $(src) id ; echo; hg -R $(src) st) || (git -C $(src) show --pretty=format:'%P' -s; echo; git -C $(src) status --porcelain)) >> revisions.txt
+	($(foreach project,$(FROM_SOURCE_PROJECTS),$(call show_revision_details,$(project)))) >> revisions.txt
 
 
 
--- a/README.md	Fri Mar 03 19:26:38 2023 +0100
+++ b/README.md	Thu Sep 28 22:29:30 2023 +0200
@@ -82,8 +82,8 @@
  
  Role             | Docker Volume     | Host path in example | Rationale
 ------------------|-------------------|----------------------|------------------------------------------------
- source directory | /home/devel/src   | ~/src                | Always relative to CWD : "../"
- build directory  | /home/devel/build | ~/build              | First argument to rebuild_docker.sh or ~/build
+ source directory | /home/runner/src   | ~/src                | Always relative to CWD : "../"
+ build directory  | /home/runner/build | ~/build              | First argument to rebuild_docker.sh or ~/build
 
 'build directory' can be specified as absolute path argument of rebuild_docker.sh.
 If not specified it defaults to ~/build
--- a/create_docker_container.sh	Fri Mar 03 19:26:38 2023 +0100
+++ b/create_docker_container.sh	Thu Sep 28 22:29:30 2023 +0200
@@ -12,7 +12,7 @@
 mkdir -p $BUILDDIR
 echo "BUILD direcory : $BUILDDIR"
 
-UNAME=devel
+UNAME=runner
 UHOME=/home/$UNAME
 
 echo "Creating docker container"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/distfiles/msys2-base-x86_64-20230718.tar.xz.md5	Thu Sep 28 22:29:30 2023 +0200
@@ -0,0 +1,1 @@
+27ecf0d49d5fe293e4372e7d7f6d5e8b  msys2-base-x86_64-20230718.tar.xz
--- a/install.nsi	Fri Mar 03 19:26:38 2023 +0100
+++ b/install.nsi	Thu Sep 28 22:29:30 2023 +0200
@@ -4,6 +4,9 @@
 SetDatablockOptimize off
 
 !include MUI2.nsh
+;!include LogicLib.nsh
+!include x64.nsh
+
 
 ; MUI Settings
 !define MUI_ICON "installer\beremiz\images\brz.ico"
@@ -25,17 +28,22 @@
 !insertmacro MUI_LANGUAGE "English"
 
 Name "Beremiz $BVERSION"
-OutFile "Beremiz-$BVERSION.exe"
-InstallDir "$PROGRAMFILES\Beremiz"
-!define PYTHONW_EXE "$INSTDIR\python\pythonw.exe"
+OutFile "Beremiz-nsis-installer.exe"
+InstallDir "$PROGRAMFILES64\Beremiz"
+!define PYTHONW_EXE "$INSTDIR\$MSYS_DIR\$MSYS_ENV_DIR\bin\pythonw.exe"
 !define BEREMIZ_EXE '"$INSTDIR\beremiz\Beremiz.py" -e "$INSTDIR\winpaths.py"'
 
 Section "Beremiz" 
   SetOutPath $INSTDIR
-  File /r /x debian /x *.pyc "installer/*"
+  ${If} ${IsNativeAMD64}
+    File /r /x debian /x *.pyc "installer/*"
+  ${Else}
+    Abort "Unsupported CPU architecture!"
+  ${EndIf}
 SectionEnd
 
 Section "Install"
+  SetRegView 64
   ;Store installation folder
   WriteRegStr HKCU "Software\Beremiz" "" $INSTDIR
   ;Create uninstaller
@@ -57,6 +65,7 @@
 SectionEnd
 
 Section "Uninstall"
+  SetRegView 64
   SetShellVarContext all
   Delete "$INSTDIR\Uninstall.exe"
 ;  Delete "$SMPROGRAMS\Beremiz\PlcopenEditor.lnk"
--- a/pacman-6.0.0-nogpg-relative_conf.patch	Fri Mar 03 19:26:38 2023 +0100
+++ b/pacman-6.0.0-nogpg-relative_conf.patch	Thu Sep 28 22:29:30 2023 +0200
@@ -40,3 +40,30 @@
  				if(ret) {
  					goto cleanup;
  				}
+diff -ruN pacman-6.0.0.orig/lib/libalpm/be_local.c pacman-6.0.0/lib/libalpm/be_local.c
+--- pacman-6.0.0.orig/lib/libalpm/be_local.c    2023-09-05 15:52:38.385979363 +0200
++++ pacman-6.0.0/lib/libalpm/be_local.c    2023-09-05 16:04:41.553345845 +0200
+@@ -423,7 +423,7 @@
+ 
+ static int local_db_create(alpm_db_t *db, const char *dbpath)
+ {
+-	if(mkdir(dbpath, 0755) != 0) {
++	if(mkdir(dbpath, 0755) != 0 && errno != EEXIST) {
+		_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not create directory %s: %s\n"),
+				dbpath, strerror(errno));
+		RET_ERR(db->handle, ALPM_ERR_DB_CREATE, -1);
+@@ -905,10 +905,12 @@
+	oldmask = umask(0000);
+	pkgpath = _alpm_local_db_pkgpath(db, info, NULL);
+ 
+-	if((retval = mkdir(pkgpath, 0755)) != 0) {
++	if((retval = mkdir(pkgpath, 0755)) != 0 && errno != EEXIST) {
+		_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not create directory %s: %s\n"),
+				pkgpath, strerror(errno));
+-	}
++	} else {
++		retval = 0;
++	}
+ 
+	free(pkgpath);
+	umask(oldmask);
--- a/provision_focal64.sh	Fri Mar 03 19:26:38 2023 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-#!/usr/bin/env bash
-
-# This script is to be executed as root to provision necessary stuff
-# to run distribution build on a blank Ubuntu Focal 64 image
-
-set -xe
-dpkg --add-architecture i386
-
-apt-get update
-
-apt-get install -y locales
-
-locale-gen en_US.UTF-8
-
-TZ="America/Paris" \
-DEBIAN_FRONTEND="noninteractive" \
-apt-get install -y --no-install-recommends \
-     autoconf                   \
-     automake                   \
-     bc                         \
-     bison                      \
-     build-essential            \
-     ca-certificates            \
-     cpio                       \
-     cmake                      \
-     fakeroot                   \
-     file                       \
-     flex                       \
-     gettext                    \
-     gawk                       \
-     git                        \
-     gperf                      \
-     gcc-multilib               \
-     g++-multilib               \
-     help2man                   \
-     less                       \
-     libarchive-dev             \
-     libcurl4-openssl-dev       \
-     libssl-dev                 \
-     libtool                    \
-     libtool-bin                \
-     lzma                       \
-     make                       \
-     mercurial                  \
-     meson                      \
-     mingw-w64                  \
-     ncurses-dev                \
-     nsis                       \
-     rsync                      \
-     pkg-config                 \
-     python                     \
-     python-dev                 \
-     python3-distutils          \
-     subversion                 \
-     swig                       \
-     texinfo                    \
-     unrar                      \
-     unzip                      \
-     wget                       \
-     xvfb                       \
-     zip
-
-
-## for winehq-staging
-#     gnupg                      \
-#     libgpgme-dev               \
-#     software-properties-common \
-# wget -nc https://dl.winehq.org/wine-builds/winehq.key
-# apt-key add winehq.key
-# add-apt-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ focal main'
-# apt-get update
-
-echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections
-echo ttf-mscorefonts-installer msttcorefonts/present-mscorefonts-eula note | debconf-set-selections
-
-apt-get install -y --install-recommends \
-     wine-stable winbind
-
-apt-get clean -y
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/provision_jammy64.sh	Thu Sep 28 22:29:30 2023 +0200
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+
+# This script is to be executed as root to provision necessary stuff
+# to run distribution build on a blank Ubuntu Focal 64 image
+
+set -xe
+dpkg --add-architecture i386
+
+apt-get update
+
+apt-get install -y locales
+
+locale-gen en_US.UTF-8
+
+TZ="America/Paris" \
+DEBIAN_FRONTEND="noninteractive" \
+apt-get install -y --no-install-recommends \
+     automake                   \
+     bc                         \
+     bison                      \
+     build-essential            \
+     ca-certificates            \
+     cpio                       \
+     cmake                      \
+     fakeroot                   \
+     flex                       \
+     gettext                    \
+     gawk                       \
+     git                        \
+     gperf                      \
+     g++-multilib               \
+     help2man                   \
+     less                       \
+     libarchive-dev             \
+     libcurl4-openssl-dev       \
+     libssl-dev                 \
+     libtool-bin                \
+     lzma                       \
+     mercurial                  \
+     meson                      \
+     mingw-w64                  \
+     ncurses-dev                \
+     nsis                       \
+     rsync                      \
+     pkg-config                 \
+     python3-pip                \
+     subversion                 \
+     swig                       \
+     texinfo                    \
+     unrar                      \
+     unzip                      \
+     wget                       \
+     xvfb                       \
+     zip
+
+echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections
+echo ttf-mscorefonts-installer msttcorefonts/present-mscorefonts-eula note | debconf-set-selections
+
+apt-get install -y --install-recommends \
+     wine-stable winbind
+
+apt-get clean -y
--- a/revisions.txt	Fri Mar 03 19:26:38 2023 +0100
+++ b/revisions.txt	Thu Sep 28 22:29:30 2023 +0200
@@ -1,4 +1,4 @@
-beremiz tip
-canfestival tip
-Modbus tip
-matiec tip
+beremiz local
+canfestival local
+Modbus local
+matiec local
--- a/win32.mk	Fri Mar 03 19:26:38 2023 +0100
+++ b/win32.mk	Thu Sep 28 22:29:30 2023 +0200
@@ -1,25 +1,35 @@
 # Win32 only distribution
 
-main_target: Beremiz-installer
+main_target: Beremiz-windows-build
 
 include $(src)/windows_installer.mk
 
-ide_targets_from_dist: canfestival
+ide_targets_from_dist:
 	touch $@
 
-canfestival_dir = installer/canfestival
-canfestival: $(canfestival_dir)/.stamp
-$(canfestival_dir)/.stamp: sources/canfestival_src | installer
-canfestival: $(canfestival_dir)/.stamp
-	rm -rf $(canfestival_dir)
-	cp -a sources/canfestival $(canfestival_dir)
-	cd $(canfestival_dir); \
-	./configure --can=tcp_win32 \
-				--cc=$(CC) \
-				--cxx=$(CXX) \
-				--target=win32 \
-				--wx=0
-	$(MAKE) -C $(canfestival_dir)
-	cd $(canfestival_dir); find . -name "*.o" -exec rm {} ';' #remove object files only
-	touch $@
+# TODO CANFESTIVAL
+# TODO MODBUS
+# TODO OPCUA
 
+# DIST_FROM_SOURCE_PROJECTS=canfestival Modbus open62541
+
+# ide_targets_from_dist: canfestival Modbus open62541
+# 	touch $@
+
+
+# canfestival_dir = installer/canfestival
+# canfestival: $(canfestival_dir)/.stamp
+# $(canfestival_dir)/.stamp: sources/canfestival_src | installer
+# canfestival: $(canfestival_dir)/.stamp
+# 	rm -rf $(canfestival_dir)
+# 	cp -a sources/canfestival $(canfestival_dir)
+# 	cd $(canfestival_dir); \
+# 	./configure --can=tcp_win32 \
+# 				--cc=$(CC) \
+# 				--cxx=$(CXX) \
+# 				--target=win32 \
+# 				--wx=0
+# 	$(MAKE) -C $(canfestival_dir)
+# 	cd $(canfestival_dir); find . -name "*.o" -exec rm {} ';' #remove object files only
+# 	touch $@
+
--- a/windows_installer.mk	Fri Mar 03 19:26:38 2023 +0100
+++ b/windows_installer.mk	Thu Sep 28 22:29:30 2023 +0200
@@ -1,11 +1,3 @@
-
-VERSIONPY=sources/beremiz/version.py
-BVERSION?=$(if $(file <$(VERSIONPY)), $(shell python2 $(VERSIONPY)), $(shell date '+%x_%R' | tr '/: ' '---'))
-
-CROSS_COMPILE=i686-w64-mingw32
-CROSS_COMPILE_LIBS_DIR=$(shell dirname $(shell $(CROSS_COMPILE)-gcc -print-libgcc-file-name))
-CC=$(CROSS_COMPILE)-gcc
-CXX=$(CROSS_COMPILE)-g++
 
 installer:
 	mkdir -p installer
@@ -14,106 +6,134 @@
 
 CURDIR:=$(shell pwd)
 PACMANPFX=$(CURDIR)/pacman
-msysdir=msys32
-MSYS_ROOT=$(CURDIR)/$(msysdir)
+MSYS_DIR=msys64
+MSYS_ENV_DIR=ucrt64
+MSYS_ENV=mingw-w64-ucrt-x86_64
+MSYS_ROOT=$(CURDIR)/$(MSYS_DIR)
 
 XVFBRUN ?= xvfb-run -a
 
-msysfinaldir=installer/msys2
+msysfinaldir=installer/$(MSYS_DIR)
 
-pacman/.stamp:
+pacman-6.0.0/src.stamp:
 	rm -rf pacman pacman-6.0.0
 	$(call get_src_http,https://sources.archlinux.org/other/pacman,pacman-6.0.0.tar.xz)\
 	tar -xJf $$dld
+	touch $@
+
+pacman-6.0.0/patched.stamp: pacman-6.0.0/src.stamp
 	cd pacman-6.0.0 ;\
-	patch -p1 < $(src)/pacman-6.0.0-nogpg-relative_conf.patch ;\
+	patch -p1 < $(src)/pacman-6.0.0-nogpg-relative_conf.patch ;
+	touch $@
+
+pacman/.stamp: pacman-6.0.0/patched.stamp
+	cd pacman-6.0.0 ;\
 	meson -Droot-dir=$(MSYS_ROOT) -Dsysconfdir=$(MSYS_ROOT)/etc -Dlocalstatedir=$(MSYS_ROOT)/var build ;\
 	DESTDIR=$(PACMANPFX) ninja -C build install
 	touch $@
 
-define pacman_install
-LD_LIBRARY_PATH=$(PACMANPFX)/usr/lib/x86_64-linux-gnu/ fakeroot pacman/usr/bin/pacman -S $(1) --arch i686 --noconfirm --cachedir $(distfiles)
+define pacman_call
+LD_LIBRARY_PATH=$(PACMANPFX)/usr/lib/x86_64-linux-gnu/ fakeroot pacman/usr/bin/pacman $(1)
 endef
 
-$(msysdir)/.stamp: pacman/.stamp 
-	rm -rf $(msysdir)
-	$(call get_src_http,http://repo.msys2.org/distrib/i686,msys2-base-i686-20210705.tar.xz)\
+pacman_update=$(call pacman_call, -Sy --noconfirm --cachedir $(distfiles));
+pacman_install_ming=$(call pacman_call, -S $(1) --arch x86_64 --noconfirm --cachedir $(distfiles));
+pacman_install_msys=$(call pacman_call, -S $(1) --noconfirm --cachedir $(distfiles));
+
+# First part are python packages requested by our app and available in msys
+# Second part are dependencies of packages to be later installed with pip
+# Third part : neede for cross-install operation
+#    -> all those packages are installed with pacman, ignoring version given in requirements.txt
+define MSYS_PY_PACKAGES
+	brotli
+	click
+	fonttools
+	lxml
+	matplotlib
+	msgpack
+	pycountry
+	u-msgpack
+	zeroconf
+	twisted
+	
+	cryptography
+	aiosqlite
+	pytz
+	sortedcontainers
+
+	pip
+endef
+
+define MSYS_PACKAGES_NAMES
+	gcc
+	make
+	wxPython
+	$(foreach package, $(MSYS_PY_PACKAGES), python-$(package))
+endef
+
+MSYS_PACKAGES=$(foreach package, $(MSYS_PACKAGES_NAMES), $(MSYS_ENV)-$(package))
+
+$(MSYS_DIR)/.stamp: pacman/.stamp 
+	rm -rf $(MSYS_DIR)
+
+	$(call get_src_http,https://repo.msys2.org/distrib/x86_64,msys2-base-x86_64-20230718.tar.xz)\
 	tar -xJf $$dld
-	$(call pacman_install, mingw-w64-i686-gcc)
-	$(call pacman_install, make)
+
+	# Do NOT update package lists to make build reproducible
+	# All packages version are as given in base image.
+	## $(pacman_update)	
+
+	$(call pacman_install_ming,$(MSYS_PACKAGES))
 	touch $@
 
-$(msysfinaldir): $(msysdir)/.stamp | installer
+# filter-out all python packages already installed by pacman
+filtered_requirements.txt: $(MSYS_DIR)/.stamp sources/beremiz_src
+	grep sources/beremiz/requirements.txt -i -v \
+		`$(call pacman_call, -Qqs 'python-.*') | sed -e 's/$(MSYS_ENV)-python-/ -e /'` \
+		-e wxPython \
+		$(foreach package, $(MSYS_PY_PACKAGES), -e $(package)) > filtered_requirements.txt
+
+# download remaining pip packages separtately with local python
+# workaround msys2's git crashing when launched from pip on wine
+# bug: https://bugs.winehq.org/show_bug.cgi?id=40528
+pip_downloads/.stamp: filtered_requirements.txt
+	rm -rf pip_downloads
+	# python3 -m pip download --no-deps -r filtered_requirements.txt -d pip_downloads
+	python3 -m pip wheel --no-deps -r filtered_requirements.txt -w pip_downloads
+	touch $@
+
+# install downloaded .whl files with wine
+# TODO: find a less convoluited way instead of wine to unpack wheels
+#       but still populating __pycache__ for this particular python version
+winpythonbin = $(MSYS_ROOT)/$(MSYS_ENV_DIR)/bin/python.exe
+wine = WINEPREFIX=$(tmp) $(XVFBRUN) wine
+pip.stamp: pip_downloads/.stamp
+	cd pip_downloads; $(wine) $(winpythonbin) -m pip install --no-deps *
+	touch $@
+
+$(msysfinaldir)/.stamp: pip.stamp | installer
 	rm -rf $(msysfinaldir)
-	cp -a $(msysdir) $(msysfinaldir)
+	cp -a $(MSYS_DIR) $(msysfinaldir)
+	touch $@
 
-msiexec = WINEPREFIX=$(tmp) $(XVFBRUN) msiexec
-wine = WINEPREFIX=$(tmp) $(XVFBRUN) wine
-pydir = installer/python
-pysite = $(pydir)/Lib/site-packages
-
-python: $(pydir)/.stamp
-$(pydir)/.stamp: | installer
-	rm -rf $(pydir)
-	mkdir -p $(pydir)
-	
-	# Python
-	$(call get_src_http,http://www.python.org/ftp/python/2.7.13,python-2.7.13.msi)\
-	$(msiexec) /qn /i $$dld TARGETDIR=.\\$(pydir)
-	
-	# # wxPython fails if VC9.0 redistribuable is not fully here.
-	# $(call get_src_http,http://download.microsoft.com/download/1/1/1/1116b75a-9ec3-481a-a3c8-1777b5381140,vcredist_x86.exe)\
-	# cp $$dld $(tmp)
-	# $(wine) $(tmp)/vcredist_x86.exe /qn /i
-	# cp -fu $(tmp)/drive_c/windows/winsxs/x86_microsoft.vc90*/* $(pydir)
-	
-	$(wine) $(pydir)/python.exe -m pip install --only-binary :all: --cache-dir $(distfiles) \
-        wxPython            \
-        future              \
-        matplotlib          \
-        pywin32             \
-        twisted             \
-        pyOpenSSL           \
-        Nevow               \
-        autobahn            \
-        msgpack_python      \
-        u-msgpack-python    \
-        zeroconf-py2compat  \
-        lxml                \
-        sslpsk              \
-        pycountry           \
-        fonttools           \
-        Brotli
-	
-	$(wine) $(pydir)/python.exe -m pip install --cache-dir $(distfiles) \
-        Pyro                \
-        gnosis              
-	
-	# # FIXME : this uses 'some' binaries of openssl that forces us to stick to python 2.7.13
-	# # FIXME : (from here : https://www.npcglib.org/~stathis/blog/precompiled-openssl/)
-	# # FIXME : build it, and use openssl binaries from https://github.com/python/cpython-bin-deps/tree/openssl-bin-1.0.2k
-	# WxGlade
-	$(call get_src_http,https://github.com/wxGlade/wxGlade/archive,v0.8.3.zip)\
-	unzip -d $(tmp) $$dld
-	mv $(tmp)/wxGlade-0.8.3 $(pysite)/wxglade
-	
-	touch $@
+CROSS_COMPILE=x86_64-w64-mingw32
+CROSS_COMPILE_LIBS_DIR=$(shell dirname $(shell $(CROSS_COMPILE)-gcc -print-libgcc-file-name))
 
 matiecdir = installer/matiec
 matiec: $(matiecdir)/.stamp
 $(matiecdir)/.stamp: sources/matiec_src | installer
 	cp -a sources/matiec $(tmp);\
 	cd $(tmp)/matiec;\
-	autoreconf;\
-	automake --add-missing;\
-	./configure --host=$(CROSS_COMPILE);\
-	make -j$(CPUS);
+	autoreconf ;\
+	automake --add-missing ;\
+	LDFLAGS=-lstdc++ ./configure --host=$(CROSS_COMPILE);\
+	$(MAKE) -j$(CPUS);
 	rm -rf $(matiecdir)
 	mkdir -p $(matiecdir)
 	mv $(tmp)/matiec/*.exe $(matiecdir)
 	
 	# install necessary shared libraries from local cross-compiler
-	cp $(CROSS_COMPILE_LIBS_DIR)/libgcc_s_sjlj-1.dll $(matiecdir)
+	cp $(CROSS_COMPILE_LIBS_DIR)/libgcc_s_seh-1.dll $(matiecdir)
 	cp $(CROSS_COMPILE_LIBS_DIR)/libstdc++-6.dll $(matiecdir)
 	
 	mv $(tmp)/matiec/lib $(matiecdir)
@@ -125,28 +145,37 @@
 $(beremizdir)/.stamp:  sources/beremiz_src | installer
 	rm -rf $(beremizdir);\
 	cp -a sources/beremiz $(beremizdir);\
+	# populate __pycache__'s .pyc files
+	cd $(beremizdir) ;\
+		find . -name "*.py" | grep -v \
+			-e \./etherlab \
+			-e .*/web_settings.py \
+			-e \./tests \
+			-e \./exemples \
+			> tocompile.lst ;\
+		$(wine) $(winpythonbin) -m compileall -i tocompile.lst
+	rm $(beremizdir)/tocompile.lst
 	touch $@
 
 ide_revisions = installer/revisions.txt
 $(ide_revisions): revisions.txt
 	cp $< $@ 
 
-Beremiz-build: Beremiz-$(BVERSION)_build
-Beremiz-$(BVERSION)_build: $(msysfinaldir) $(pydir)/.stamp $(matiecdir)/.stamp $(beremizdir)/.stamp ide_targets_from_dist $(ide_revisions)
+Beremiz-windows-build: $(msysfinaldir)/.stamp pip.stamp $(matiecdir)/.stamp $(beremizdir)/.stamp ide_targets_from_dist $(ide_revisions)
 	touch $@
 
-Beremiz-archive: Beremiz-$(BVERSION).zip
-
-Beremiz-installer: Beremiz-$(BVERSION).exe
-
-Beremiz-$(BVERSION).zip: Beremiz-$(BVERSION)_build
+Beremiz-portable.zip: Beremiz-windows-build
 	rm -f $@
 	cd installer; zip -r -q ../$@ .
 
-Beremiz-$(BVERSION).exe: Beremiz-$(BVERSION)_build $(src)/license.txt $(src)/install.nsi 
-	sed -e 's/\$$BVERSION/$(BVERSION)/g' $(src)/license.txt > installer/license.txt
-	sed -e 's/\$$BVERSION/$(BVERSION)/g' $(src)/install.nsi |\
-	makensis -
+VERSIONPY=sources/beremiz/version.py
+
+Beremiz-nsis-installer.exe: Beremiz-windows-build $(src)/license.txt $(src)/install.nsi 
+	export BVERSION=`python3 $(VERSIONPY)` ;\
+	sed -e "s/\$$BVERSION/$$BVERSION/g" $(src)/license.txt > installer/license.txt ;\
+	sed -e "s/\$$BVERSION/$$BVERSION/g" $(src)/install.nsi |\
+	sed -e "s#\$$MSYS_DIR#$(MSYS_DIR)#g" |\
+	sed -e "s#\$$MSYS_ENV_DIR#$(MSYS_ENV_DIR)#g" > install.nsi
+	makensis install.nsi
 
 
-
--- a/winpaths.py	Fri Mar 03 19:26:38 2023 +0100
+++ b/winpaths.py	Thu Sep 28 22:29:30 2023 +0200
@@ -5,7 +5,7 @@
 os.environ["PATH"] = ';'.join([
     os.path.join(instdir, "msys2", "bin"),
     os.path.join(instdir, "msys2", "usr", "bin"),
-    os.path.join(instdir, "msys2", "mingw32", "bin"),
+    os.path.join(instdir, "msys2", "mingw64", "bin"),
     PATH
 ])