Skip to content

Commit 42169d9

Browse files
authored
desktop: Add Windows Docker cross-compilation. (#3582)
* desktop: Add Windows Docker cross-compilation. Add a Dockerfile for cross-compiling bisonw-desktop.exe from Linux and add more docs. * tor: Update to tor 0.4.9.6. The pinned tor 0.4.7.x has a SYS_SECCOMP macro in sandbox.h that conflicts with newer glibc/kernel headers which now also define it. Update to tor 0.4.9.6 which has the fix upstream.
1 parent e5cd27b commit 42169d9

8 files changed

Lines changed: 196 additions & 14 deletions

File tree

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
client/webserver/site/node_modules/
22
spec/
33
docs/
4+
.git/
5+
build/

client/cmd/bisonw-desktop/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ sudo ufw disable # if ufw is installed on the host, this is neccessary for lxd t
4545

4646
The snap can be uploaded to the Snap Store using `./linux/publish-snap.sh`. This requires [Snapcraft developer account credentials](https://snapcraft.io/docs/releasing-your-app). After this is completed, the package can be installed on any system running `snap` by running `snap install bisonw`. The app will be available on the [Snap Store](https://snapcraft.io/store/bisonw).
4747

48+
## Windows
49+
50+
See [windows/README.md](windows/README.md) for full instructions on setting up the build environment and building the Windows binary and MSI installer.
51+
4852
## macOS (darwin)
4953

5054
macOS builds use Electron.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Dockerfile for cross-compiling bisonw-desktop.exe for Windows from Linux.
2+
#
3+
# Prerequisites:
4+
# The site bundle must be built before running the docker build:
5+
# cd client/webserver/site && npm clean-install && npm run build
6+
#
7+
# Build (from the repo root):
8+
# docker build -t bisonw-desktop-windows -f client/cmd/bisonw-desktop/windows/Dockerfile .
9+
#
10+
# Build with XMR support:
11+
# docker build -t bisonw-desktop-windows --build-arg XMR=1 -f client/cmd/bisonw-desktop/windows/Dockerfile .
12+
#
13+
# Extract the exe and DLLs:
14+
# mkdir -p build && docker run --rm bisonw-desktop-windows tar -cf - -C /out . | tar -xf - -C ./build
15+
16+
FROM golang:1.24-bookworm
17+
18+
ENV DEBIAN_FRONTEND=noninteractive
19+
20+
RUN apt-get update && apt-get install -y \
21+
gcc-mingw-w64-x86-64 \
22+
g++-mingw-w64-x86-64 \
23+
mingw-w64-tools \
24+
unzip \
25+
&& rm -rf /var/lib/apt/lists/*
26+
27+
ARG XMR=0
28+
ARG WEBVIEW2_VERSION=1.0.3856.49
29+
30+
COPY . /src
31+
WORKDIR /src/client/cmd/bisonw-desktop
32+
33+
# Fetch the WebView2 NuGet package for the runtime DLL (WebView2Loader.dll).
34+
RUN mkdir -p /tmp/webview2 && \
35+
curl -sSL "https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/${WEBVIEW2_VERSION}" -o /tmp/webview2.zip && \
36+
unzip -q /tmp/webview2.zip -d /tmp/webview2 && \
37+
rm /tmp/webview2.zip
38+
39+
# Create a stub EventToken.h. The webview_go module's bundled WebView2.h
40+
# includes this Windows SDK header, which MinGW does not provide.
41+
RUN mkdir -p /tmp/winsdk && \
42+
printf '#pragma once\ntypedef struct EventRegistrationToken { __int64 value; } EventRegistrationToken;\n' \
43+
> /tmp/winsdk/EventToken.h
44+
45+
# Generate a MinGW import library for the XMR DLL. The MinGW linker cannot
46+
# link directly against a .dll. Named .a (not .dll.a) because webview_go's
47+
# CGO LDFLAGS include -static, which makes the linker skip .dll.a files.
48+
RUN if [ "$XMR" = "1" ]; then \
49+
cd /src/client/asset/xmr/lib/windows-amd64 && \
50+
gendef libwallet2_api_c.dll && \
51+
x86_64-w64-mingw32-dlltool -d libwallet2_api_c.def \
52+
-l libwallet2_api_c.a -D libwallet2_api_c.dll; \
53+
fi
54+
55+
RUN mkdir -p /out
56+
57+
ENV GOOS=windows
58+
ENV GOARCH=amd64
59+
ENV CGO_ENABLED=1
60+
ENV CC=x86_64-w64-mingw32-gcc
61+
ENV CXX=x86_64-w64-mingw32-g++
62+
ENV CGO_CXXFLAGS="-I/tmp/winsdk"
63+
64+
RUN if [ "$XMR" = "1" ]; then \
65+
go build -v -tags xmr -ldflags="-H windowsgui" -o /out/bisonw-desktop.exe; \
66+
else \
67+
go build -v -ldflags="-H windowsgui" -o /out/bisonw-desktop.exe; \
68+
fi
69+
70+
# Bundle runtime DLLs that are not present on a stock Windows install.
71+
RUN cp /tmp/webview2/runtimes/win-x64/native/WebView2Loader.dll /out/ && \
72+
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll /out/
73+
74+
RUN if [ "$XMR" = "1" ]; then \
75+
cp /src/client/asset/xmr/lib/windows-amd64/libwallet2_api_c.dll /out/; \
76+
fi

client/cmd/bisonw-desktop/windows/Build-Windows.md renamed to client/cmd/bisonw-desktop/windows/README.md

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
## Windows build
1+
# Windows build
2+
3+
## Native build
24

35
### Setting up the build environment
46

57
This build setup is expected to be run on a freshly installed system (e.g. in a VM), which is the best practice for building binaries for release on Windows, therefore there are no prerequisites. The setup script will install all components of the toolchain, dependencies and SDKs required to build the `bisonw-desktop` binary and the MSI (MS installer), there is no need to install anything manually before running this (it can actually cause issues if different versions of the dependencies are already on the system). The builder was tested on Windows 10, Windows 11 and server equivalents, 2019/2022.
68

7-
Download and run setup as Administrator (privileges are required in order to set environment variables). Open a command prompt as Administrator, and run:
9+
Download and run setup as Administrator (privileges are required in order to set environment variables). Open a **Command Prompt** (cmd.exe) as Administrator (not PowerShell), and run:
810

911
```batch
1012
cd %UserProfile%
@@ -22,7 +24,7 @@ Download and run setup as Administrator (privileges are required in order to set
2224
cd dcrdex\client\cmd\bisonw-desktop
2325
```
2426

25-
Build the Windows binary:
27+
Build the Windows binary:
2628

2729
```batch
2830
windows\build-windows.cmd
@@ -39,3 +41,58 @@ windows\pkg-windows.cmd
3941
```
4042

4143
The resulting installer binary will be located in `build\msi`.
44+
45+
## Cross-compiling from Linux with Docker
46+
47+
The Windows `.exe` can be cross-compiled from Linux using Docker. This does not produce the MSI installer.
48+
49+
### Prerequisites
50+
51+
Build the site bundle if it hasn't been built already:
52+
53+
```bash
54+
cd client/webserver/site
55+
npm clean-install
56+
npm run build
57+
cd ../../..
58+
```
59+
60+
### Build the exe
61+
62+
From the repo root:
63+
64+
```bash
65+
docker build -t bisonw-desktop-windows -f client/cmd/bisonw-desktop/windows/Dockerfile .
66+
```
67+
68+
To include XMR support:
69+
70+
```bash
71+
docker build -t bisonw-desktop-windows --build-arg XMR=1 -f client/cmd/bisonw-desktop/windows/Dockerfile .
72+
```
73+
74+
### Extract the build output
75+
76+
```bash
77+
mkdir -p build && docker run --rm bisonw-desktop-windows tar -cf - -C /out . | tar -xf - -C ./build
78+
```
79+
80+
The `build/` directory will contain `bisonw-desktop.exe`, `WebView2Loader.dll`, `libwinpthread-1.dll`, and `libwallet2_api_c.dll` if XMR was enabled.
81+
82+
### Packaging the MSI on Windows
83+
84+
The MSI installer can only be built on Windows. If you cross-compiled the exe on Linux, copy the contents of `build/` to `client\cmd\bisonw-desktop\build\windows\` in the repo on a Windows machine with the build environment set up, then run from `client\cmd\bisonw-desktop`:
85+
86+
```batch
87+
windows\pkg-windows.cmd --skip-build
88+
```
89+
90+
To include XMR support in the MSI:
91+
92+
```batch
93+
windows\pkg-windows.cmd --skip-build --xmr
94+
```
95+
96+
The resulting installer will be in `build\msi`.
97+
98+
**Note:** The Docker cross-compilation uses MinGW, which produces a binary that depends on `libwinpthread-1.dll`. This DLL is bundled automatically by the Dockerfile. Native Windows builds use MSVC and do not require this DLL.

client/cmd/bisonw-desktop/windows/pkg-windows.cmd

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,40 @@
44

55
call windows\env-windows.cmd
66

7-
:: Run build
8-
call windows\build-windows.cmd %*
9-
10-
:: Check the error level after the first command
11-
if %errorlevel% equ 0 (
12-
echo Build completed successfully.
13-
echo Building MSI
14-
dotnet build --property:Platform=x64 --configuration Release --output build\msi -noWarn:WIX1076 windows\windows-msi\BisonWallet_Installer.wixproj
15-
echo MSI built in build\msi
7+
:: Parse flags.
8+
set "XMR_ENABLED=0"
9+
set "SKIP_BUILD=0"
10+
:parse_args
11+
if "%~1"=="" goto done_args
12+
if "%~1"=="--xmr" set "XMR_ENABLED=1"
13+
if "%~1"=="--skip-build" set "SKIP_BUILD=1"
14+
shift
15+
goto parse_args
16+
:done_args
17+
18+
if "%SKIP_BUILD%"=="1" (
19+
echo Skipping build, packaging existing files in build\windows...
20+
goto :MSI
21+
)
22+
23+
:: Run build. Only forward --xmr if set; build-windows.cmd does not
24+
:: understand --skip-build.
25+
if "%XMR_ENABLED%"=="1" (
26+
call windows\build-windows.cmd --xmr
1627
) else (
28+
call windows\build-windows.cmd
29+
)
30+
31+
if %errorlevel% neq 0 (
1732
echo Error occurred during build.
33+
exit /b 1
1834
)
35+
echo Build completed successfully.
36+
37+
:MSI
38+
echo Building MSI
39+
dotnet build --property:Platform=x64 --configuration Release --output build\msi -noWarn:WIX1076 -p:XmrEnabled=%XMR_ENABLED% -p:CrossCompiled=%SKIP_BUILD% windows\windows-msi\BisonWallet_Installer.wixproj
40+
echo MSI built in build\msi
1941

2042
echo Signing %exeFile%
21-
call windows\sign-windows.cmd %exeFile%
43+
call windows\sign-windows.cmd %exeFile%

client/cmd/bisonw-desktop/windows/windows-msi/BisonWallet.wxs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99
<File Source="..\..\build\windows\Bisonw-desktop.exe" Id="BisonwDesktopExe" KeyPath="yes" Checksum="yes" />
1010
<File Source="..\..\build\windows\WebView2Loader.dll" Checksum="yes" />
1111
</Component>
12+
<?if $(var.CrossCompiled) = 1 ?>
13+
<Component Id="MinGWRuntime" Guid="a1d4f8e2-7b39-4c56-8e1a-5f9d3c6b2e08">
14+
<File Source="..\..\build\windows\libwinpthread-1.dll" Checksum="yes" />
15+
</Component>
16+
<?endif ?>
17+
<?if $(var.XmrEnabled) = 1 ?>
18+
<Component Id="XmrLibrary" Guid="b7a3e1f4-5c82-4d19-9a6b-3e8f2d7c1a05">
19+
<File Source="..\..\build\windows\libwallet2_api_c.dll" Checksum="yes" />
20+
</Component>
21+
<?endif ?>
1222
</DirectoryRef>
1323

1424
<DirectoryRef Id="ApplicationProgramsFolder">
@@ -25,6 +35,12 @@
2535
<Feature Id="MainApplication" Title="Main Application" Level="1">
2636
<ComponentRef Id="BisonwDesktopExe" />
2737
<ComponentRef Id="ApplicationShortcut" />
38+
<?if $(var.CrossCompiled) = 1 ?>
39+
<ComponentRef Id="MinGWRuntime" />
40+
<?endif ?>
41+
<?if $(var.XmrEnabled) = 1 ?>
42+
<ComponentRef Id="XmrLibrary" />
43+
<?endif ?>
2844
</Feature>
2945

3046
<StandardDirectory Id="ProgramFiles64Folder">
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
<Project Sdk="WixToolset.Sdk/5.0.0">
2+
<PropertyGroup>
3+
<XmrEnabled Condition="'$(XmrEnabled)' == ''">0</XmrEnabled>
4+
<CrossCompiled Condition="'$(CrossCompiled)' == ''">0</CrossCompiled>
5+
<DefineConstants>XmrEnabled=$(XmrEnabled);CrossCompiled=$(CrossCompiled)</DefineConstants>
6+
</PropertyGroup>
27
</Project>

client/tor/build_linux.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ BASE_DIR=$(realpath $(dirname $0))
44
BUILD_DIR="${BASE_DIR}/build"
55
REPO_DIR="${BUILD_DIR}/torrepo"
66

7-
COMMIT_HASH=3cb6a690be60fcdab60130402ff88dcfc0657596
7+
COMMIT_HASH=d133d41f5d285c2f0a9c2fd75acde285d67afd3d
88

99
rm -r -f "${REPO_DIR}"
1010
mkdir -p "${REPO_DIR}"

0 commit comments

Comments
 (0)