Skip to content

Commit 21a4170

Browse files
authored
wine: support both 32-bit and 64-bit Windows builds (Electron-Cash#3189)
* wine: Update gnupg2 to current version * wine: support both 32-bit and 64-bit Windows builds - Make `GCC_TRIPLET_HOST` configurable from environment - Map architecture to Python installer paths (`amd64`/`win32`) - Add SHA256 checksums for both 32-bit and 64-bit Python MSIs - Configure OpenSSL target (`mingw64`/`mingw`) based on architecture - Include architecture in output filenames (e.g. `Electron-Cash-4.2.2-x86_64.exe`) The 64-bit Wine install with Visual Studio can cross-compile to both x86 and x64 targets, so we only need a single build container. I tested: - All `ctypes` usages directly in the app. - tor - Ledger, Keepkey plugins - zbar and zxing-cpp
1 parent 57347c8 commit 21a4170

7 files changed

Lines changed: 90 additions & 48 deletions

File tree

contrib/build-wine/_build.sh

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ here=`pwd` # get an absolute path
77
popd
88

99
export BUILD_TYPE="wine"
10-
export GCC_TRIPLET_HOST="i686-w64-mingw32"
10+
export GCC_TRIPLET_HOST="${GCC_TRIPLET_HOST:-x86_64-w64-mingw32}"
11+
export GCC_TRIPLET_HOST_ARCH="${GCC_TRIPLET_HOST%%-*}" # e.g. x86_64
12+
# Map GCC arch to Python installer directory name
13+
case "$GCC_TRIPLET_HOST_ARCH" in
14+
x86_64) export PYTHON_ARCH="amd64" ;;
15+
i686) export PYTHON_ARCH="win32" ;;
16+
*) echo "Unknown architecture: $GCC_TRIPLET_HOST_ARCH" && exit 1 ;;
17+
esac
1118
export GCC_TRIPLET_BUILD="x86_64-pc-linux-gnu"
1219
export GCC_STRIP_BINARIES="1"
1320
export GIT_SUBMODULE_FLAGS="--recommend-shallow --depth 1"
@@ -88,19 +95,30 @@ prepare_wine() {
8895

8996
for msifile in $msifiles ; do
9097
info "Downloading $msifile..."
91-
wget "https://www.python.org/ftp/python/$PYTHON_VERSION/win32/${msifile}.msi"
92-
wget "https://www.python.org/ftp/python/$PYTHON_VERSION/win32/${msifile}.msi.asc"
98+
wget "https://www.python.org/ftp/python/$PYTHON_VERSION/$PYTHON_ARCH/${msifile}.msi"
99+
wget "https://www.python.org/ftp/python/$PYTHON_VERSION/$PYTHON_ARCH/${msifile}.msi.asc"
93100
verify_signature "${msifile}.msi.asc" $KEYRING_PYTHON_DEV
94101
done
95102

96-
$SHA256_PROG -c - << EOF
103+
if [ "$PYTHON_ARCH" = "amd64" ]; then
104+
$SHA256_PROG -c - << EOF
105+
d5499530d9cddc316811630736eb1bd35f22637f889d562cd3e8e980b1aebd17 core.msi
106+
eb413f9579079f961d3f4c034ba8e00d28ff1cb703f873b9b585c0f467321fba dev.msi
107+
b0a7aaffc9b03d5c7d04d8522e30c5027a8c70ec4c14a6922d6c2cf560bc1459 exe.msi
108+
1e6f5cedc0158f6f2f23d0657d3e6858853569084669dac8f367fc3b94dc4c9b lib.msi
109+
014460c0444bfff5a003ca0a6375c4b41a257f5ed380a714cda3fbcf5d3c1579 pip.msi
110+
6d34cbc645c1b2dd360a0b0df79205b24f0d5f85fea2865f1cc1428d6a64b9cd tools.msi
111+
EOF
112+
elif [ "$PYTHON_ARCH" = "win32" ]; then
113+
$SHA256_PROG -c - << EOF
97114
f49a951a6ad7e733e64877b36c8fe43477c2b1c26d316f30a2379bb35a8538a8 core.msi
98115
45c3faeccbd7fa5041f00fea2d05dfcd1a4ef0211aa519508e168b4bcea92bac dev.msi
99116
6b18e724b5ae84df94c3d6cbe55c9143a46802e49c6c7310db7c6e9c1996dc24 exe.msi
100117
6c97ba70fd48747489650b48db5be9ea165dd56f1c6e0ddd5e05c488cf2dd2e2 lib.msi
101118
2a1a5e6adb9d8120c448ab8df8501a16ad419daa93b230c635036f67e4719f5d pip.msi
102119
ee1a5d8ee16eaef3c84c6c4cea4621554d9d1de640fb84ba4f4d982a743fef81 tools.msi
103120
EOF
121+
fi
104122
test $? -eq 0 || fail "Failed to verify Python checksums"
105123

106124
for msifile in $msifiles ; do
@@ -133,13 +151,12 @@ EOF
133151
fi
134152
pushd bootloader
135153
# If switching to 64-bit Windows, edit CC= below
136-
python3 ./waf all CC=i686-w64-mingw32-gcc CFLAGS="-Wno-stringop-overflow -static"
154+
python3 ./waf all CC="$GCC_TRIPLET_HOST-gcc" CFLAGS="-Wno-stringop-overflow -static"
137155
# Note: it's possible for the EXE to not be there if the build
138156
# failed but didn't return exit status != 0 to the shell (waf bug?);
139157
# So we need to do this to make sure the EXE is actually there.
140-
# If we switch to 64-bit, edit this path below.
141158
popd
142-
[ -e PyInstaller/bootloader/Windows-32bit-intel/runw.exe ] || fail "Could not find runw.exe in target dir!"
159+
[ -e PyInstaller/bootloader/Windows-32bit-intel/runw.exe -o -e PyInstaller/bootloader/Windows-64bit-intel/runw.exe ] || fail "Could not find runw.exe in target dir!"
143160
rm -fv pyinstaller.py # workaround for https://github.com/pyinstaller/pyinstaller/pull/6701
144161
) || fail "PyInstaller bootloader build failed"
145162
info "Installing PyInstaller ..."
@@ -167,12 +184,9 @@ EOF
167184
git checkout -b pinned "${LIBUSB_COMMIT}^{commit}"
168185
echo "libusb_1_0_la_LDFLAGS += -Wc,-static" >> libusb/Makefile.am
169186
./bootstrap.sh || fail "Could not bootstrap libusb"
170-
host="i686-w64-mingw32"
171-
LDFLAGS="-Wl,--no-insert-timestamp" ./configure \
172-
--host=$host \
173-
--build=x86_64-pc-linux-gnu || fail "Could not run ./configure for libusb"
187+
LDFLAGS="-Wl,--no-insert-timestamp" ./configure $AUTOCONF_FLAGS || fail "Could not run ./configure for libusb"
174188
make -j4 || fail "Could not build libusb"
175-
${host}-strip libusb/.libs/libusb-1.0.dll
189+
host_strip libusb/.libs/libusb-1.0.dll
176190
) || fail "libusb build failed"
177191

178192
# libsecp256k1, libzbar & libusb
@@ -251,8 +265,8 @@ build_the_app() {
251265

252266
# rename the output files
253267
pushd dist
254-
mv $NAME_ROOT.exe $NAME_ROOT-$VERSION.exe
255-
mv $NAME_ROOT-portable.exe $NAME_ROOT-$VERSION-portable.exe
268+
mv $NAME_ROOT.exe $NAME_ROOT-$VERSION-$GCC_TRIPLET_HOST_ARCH.exe
269+
mv $NAME_ROOT-portable.exe $NAME_ROOT-$VERSION-$GCC_TRIPLET_HOST_ARCH-portable.exe
256270
popd
257271

258272
# set timestamps in dist, in order to make the installer reproducible
@@ -264,10 +278,10 @@ build_the_app() {
264278
# build NSIS installer
265279
info "Running makensis to build setup .exe version ..."
266280
# $VERSION could be passed to the electron-cash.nsi script, but this would require some rewriting in the script iself.
267-
wine "$WINEPREFIX/drive_c/Program Files/NSIS/makensis.exe" /DPRODUCT_VERSION=$VERSION electron-cash.nsi || fail "makensis failed"
281+
wine "$WINEPREFIX/drive_c/Program Files (x86)/NSIS/makensis.exe" /DPRODUCT_VERSION=$VERSION /DGCC_TRIPLET_HOST_ARCH=$GCC_TRIPLET_HOST_ARCH electron-cash.nsi || fail "makensis failed"
268282

269283
cd dist
270-
mv $NAME_ROOT-setup.exe $NAME_ROOT-$VERSION-setup.exe || fail "Failed to move $NAME_ROOT-$VERSION-setup.exe to the output dist/ directory"
284+
mv $NAME_ROOT-setup.exe $NAME_ROOT-$VERSION-$GCC_TRIPLET_HOST_ARCH-setup.exe || fail "Failed to move $NAME_ROOT-$VERSION-$GCC_TRIPLET_HOST_ARCH-setup.exe to the output dist/ directory"
271285

272286
ls -la *.exe
273287
sha256sum *.exe

contrib/build-wine/build.sh

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -78,32 +78,42 @@ FRESH_CLONE_DIR="$FRESH_CLONE/$GIT_DIR_NAME"
7878
) || fail "Could not create a fresh clone from git"
7979

8080
(
81-
# NOTE: We propagate forward the GIT_REPO override to the container's env,
82-
# just in case it needs to see it.
83-
$SUDO docker run $DOCKER_RUN_TTY \
84-
-u $USER_ID:$GROUP_ID \
85-
-e GIT_REPO="$GIT_REPO" \
86-
-e BUILD_DEBUG="$BUILD_DEBUG" \
87-
-e PYI_SKIP_TAG="$PYI_SKIP_TAG" \
88-
--name ec-wine-builder-cont \
89-
-v "$FRESH_CLONE_DIR":/homedir/wine/drive_c/electroncash:delegated \
90-
--rm \
91-
--workdir /homedir/wine/drive_c/electroncash/contrib/build-wine \
92-
$IMGNAME \
93-
./_build.sh $REV
81+
for triplet in x86_64-w64-mingw32 i686-w64-mingw32; do
82+
pushd "$FRESH_CLONE_DIR"
83+
git reset --hard || fail "Failed to reset git repository"
84+
git clean -dfxq || fail "Failed to clean git repository"
85+
git submodule foreach 'git reset --hard' || fail "Failed to reset git submodules"
86+
git submodule foreach 'git clean -dfxq' || fail "Failed to clean git submodules"
87+
popd
88+
89+
# NOTE: We propagate forward the GIT_REPO override to the container's env,
90+
# just in case it needs to see it.
91+
$SUDO docker run $DOCKER_RUN_TTY \
92+
-u $USER_ID:$GROUP_ID \
93+
-e GIT_REPO="$GIT_REPO" \
94+
-e BUILD_DEBUG="$BUILD_DEBUG" \
95+
-e PYI_SKIP_TAG="$PYI_SKIP_TAG" \
96+
-e GCC_TRIPLET_HOST="$triplet" \
97+
--name ec-wine-builder-cont \
98+
-v "$FRESH_CLONE_DIR":/homedir/wine/drive_c/electroncash:delegated \
99+
--rm \
100+
--workdir /homedir/wine/drive_c/electroncash/contrib/build-wine \
101+
$IMGNAME \
102+
./_build.sh $REV || fail "Build for $triplet inside docker container failed"
103+
104+
info "Copying .exe files out of our build directory ..."
105+
mkdir -p "$here"/../../dist
106+
files="$FRESH_CLONE_DIR"/contrib/build-wine/dist/*.exe
107+
for f in $files; do
108+
bn=`basename "$f"`
109+
cp -fpv "$f" "$here"/../../dist/"$bn" || fail "Failed to copy $bn"
110+
touch "$here"/../../dist/"$bn" || fail "Failed to update timestamp on $bn"
111+
done
112+
done
94113
) || fail "Build inside docker container failed"
95114

96115
popd
97116

98-
info "Copying .exe files out of our build directory ..."
99-
mkdir -p dist/
100-
files="$FRESH_CLONE_DIR"/contrib/build-wine/dist/*.exe
101-
for f in $files; do
102-
bn=`basename "$f"`
103-
cp -fpv "$f" dist/"$bn" || fail "Failed to copy $bn"
104-
touch dist/"$bn" || fail "Failed to update timestamp on $bn"
105-
done
106-
107117
info "Removing $FRESH_CLONE ..."
108118
$SUDO rm -fr "$FRESH_CLONE"
109119

contrib/build-wine/deterministic.spec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ binaries += [('C:/tmp/tor.exe', '.')]
4444
# Workaround for "Retro Look":
4545
binaries += [b for b in collect_dynamic_libs('PyQt5') if 'qwindowsvista' in b[0]]
4646

47-
binaries += [('C:/python*/Lib/site-packages/smartcard/scard/_scard.cp*-win32.pyd', '.')] # Satochip
47+
binaries += [('C:/python*/Lib/site-packages/smartcard/scard/_scard.*.pyd', '.')] # Satochip
4848

4949
datas = [
5050
(home+'electroncash/currencies.json', 'electroncash'),

contrib/build-wine/docker/Dockerfile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN echo deb ${UBUNTU_MIRROR} ${UBUNTUDIST} main restricted universe multiverse
1616
dpkg --add-architecture i386 && \
1717
apt-get update -q && \
1818
apt-get install -qy \
19-
gnupg2=2.2.27-3ubuntu2.4 \
19+
gnupg2=2.2.27-3ubuntu2.5 \
2020
ca-certificates=20211016 \
2121
wget=1.21.2-2ubuntu1 \
2222
git=1:2.34.1-1ubuntu1.15 \
@@ -67,7 +67,7 @@ ARG USER_ID
6767
ARG GROUP_ID
6868

6969
ENV HOME=/homedir
70-
ENV WINEARCH=win32
70+
ENV WINEARCH=win64
7171
ENV WINEPREFIX=${HOME}/wine
7272
ENV WINEDEBUG=-all
7373

@@ -104,18 +104,18 @@ RUN wget https://aka.ms/vs/16/release/installer -O /tmp/vs_installer.opc && \
104104
--add "Microsoft.VisualStudio.Component.VC.Tools.x86.x64" \
105105
--add "Microsoft.VisualStudio.Component.Windows10SDK.19041" && \
106106
# vswhere.exe needs to be installed in this path so setuptools can detect the VS installation
107-
mkdir "${WINEPREFIX}"/"drive_c/Program Files/Microsoft Visual Studio/Installer" && \
108-
mv opc/Contents/vswhere.exe "${WINEPREFIX}"/"drive_c/Program Files/Microsoft Visual Studio/Installer" && \
107+
mkdir "${WINEPREFIX}"/"drive_c/Program Files (x86)/Microsoft Visual Studio/Installer" && \
108+
mv opc/Contents/vswhere.exe "${WINEPREFIX}"/"drive_c/Program Files (x86)/Microsoft Visual Studio/Installer" && \
109109
rm -rf opc && wineserver -w
110110

111111
#RUN wine "${WINEPREFIX}"/"drive_c/windows/Microsoft.NET/Framework/v4.0.30319/ngen.exe" executequeueditems && \
112112
# wineserver -w
113113

114114
# Patch to make vcvarsall.bat work
115-
# "C:\Program Files\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x86 && set
115+
# "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x86 && set
116116
# python -c "from setuptools import msvc; print(msvc.msvc14_get_vc_env('x86'))"
117117
# Caused by wrong delayed expansion in Wine, see https://bugs.winehq.org/show_bug.cgi?id=38289
118-
RUN sed -i -e 's/!result:~0,3!/10./g' "${WINEPREFIX}"/"drive_c/Program Files/Microsoft Visual Studio/2019/BuildTools/Common7/Tools/vsdevcmd/core/winsdk.bat"
118+
RUN sed -i -e 's/!result:~0,3!/10./g' "${WINEPREFIX}"/"drive_c/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/Common7/Tools/vsdevcmd/core/winsdk.bat"
119119

120120
# Clean up some left overs only needed for the Visual Studio installer
121121
USER 0:0

contrib/build-wine/docker/wrapper_install.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@echo off
22

33
set VCYEAR=2019
4-
set VCDIR=c:\Program Files\Microsoft Visual Studio\%VCYEAR%\BuildTools\VC
4+
set VCDIR=c:\Program Files (x86)\Microsoft Visual Studio\%VCYEAR%\BuildTools\VC
55

66
call "%VCDIR%\Auxiliary\Build\vcvarsall.bat" x86
77

contrib/build-wine/electron-cash.nsi

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@
2929
OutFile "dist/${INTERNAL_NAME}-setup.exe"
3030

3131
;Default installation folder
32-
InstallDir "$PROGRAMFILES\${PRODUCT_NAME}"
32+
!if "${GCC_TRIPLET_HOST_ARCH}" == "x86_64"
33+
InstallDir "$PROGRAMFILES64\${PRODUCT_NAME}"
34+
!else
35+
InstallDir "$PROGRAMFILES\${PRODUCT_NAME}"
36+
!endif
3337

3438
;Get installation folder from registry if available
3539
InstallDirRegKey ${INSTDIR_REG_ROOT} "Software\${PRODUCT_NAME}" ""
@@ -105,6 +109,12 @@
105109
;--------------------------------
106110
;Functions
107111

112+
!macro SetRegView64
113+
!if "${GCC_TRIPLET_HOST_ARCH}" == "x86_64"
114+
SetRegView 64 ; Use the 64-bit registry view
115+
!endif
116+
!macroend
117+
108118
!macro CreateEnsureNotRunning prefix operation
109119

110120
Function ${prefix}EnsureNotRunning
@@ -164,6 +174,7 @@ Function .onInit
164174
FunctionEnd
165175

166176
Section
177+
!insertmacro SetRegView64
167178
SetOutPath $INSTDIR ; side-effect is it creates dir if not exist
168179

169180
!insertmacro UNINSTALL.LOG_OPEN_INSTALL
@@ -236,6 +247,8 @@ SectionEnd
236247
;Uninstaller Section
237248

238249
Section "Uninstall"
250+
!insertmacro SetRegView64
251+
239252
!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR"
240253

241254
Delete "$DESKTOP\${PRODUCT_NAME}.lnk"

contrib/make_openssl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ if ! [ -d dist ] ; then
3232
./Configure darwin64-$(uname -m)-cc --prefix="$here/$pkgname/dist" $CONFIG_OPTIONS
3333
;;
3434
wine)
35-
./Configure --cross-compile-prefix=${GCC_TRIPLET_HOST}- mingw --prefix="$here/$pkgname/dist" $CONFIG_OPTIONS
35+
case "${GCC_TRIPLET_HOST_ARCH:-${GCC_TRIPLET_HOST%%-*}}" in
36+
x86_64) OPENSSL_TARGET="mingw64" ;;
37+
i686) OPENSSL_TARGET="mingw" ;;
38+
*) fail "Unknown architecture for OpenSSL: $GCC_TRIPLET_HOST" ;;
39+
esac
40+
./Configure --cross-compile-prefix="$GCC_TRIPLET_HOST"- $OPENSSL_TARGET --prefix="$here/$pkgname/dist" $CONFIG_OPTIONS
3641
;;
3742
esac
3843
) || fail "Could not configure $pkgname. Please make sure you have a C compiler installed and try again."

0 commit comments

Comments
 (0)