Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
client/webserver/site/node_modules/
spec/
docs/
.git/
build/
4 changes: 4 additions & 0 deletions client/cmd/bisonw-desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ sudo ufw disable # if ufw is installed on the host, this is neccessary for lxd t

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).

## Windows

See [windows/README.md](windows/README.md) for full instructions on setting up the build environment and building the Windows binary and MSI installer.

## macOS (darwin)

macOS builds use Electron.
Expand Down
76 changes: 76 additions & 0 deletions client/cmd/bisonw-desktop/windows/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Dockerfile for cross-compiling bisonw-desktop.exe for Windows from Linux.
#
# Prerequisites:
# The site bundle must be built before running the docker build:
# cd client/webserver/site && npm clean-install && npm run build
#
# Build (from the repo root):
# docker build -t bisonw-desktop-windows -f client/cmd/bisonw-desktop/windows/Dockerfile .
#
# Build with XMR support:
# docker build -t bisonw-desktop-windows --build-arg XMR=1 -f client/cmd/bisonw-desktop/windows/Dockerfile .
#
# Extract the exe and DLLs:
# mkdir -p build && docker run --rm bisonw-desktop-windows tar -cf - -C /out . | tar -xf - -C ./build

FROM golang:1.24-bookworm

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
gcc-mingw-w64-x86-64 \
g++-mingw-w64-x86-64 \
mingw-w64-tools \
unzip \
&& rm -rf /var/lib/apt/lists/*

ARG XMR=0
ARG WEBVIEW2_VERSION=1.0.3856.49

COPY . /src
WORKDIR /src/client/cmd/bisonw-desktop

# Fetch the WebView2 NuGet package for the runtime DLL (WebView2Loader.dll).
RUN mkdir -p /tmp/webview2 && \
curl -sSL "https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/${WEBVIEW2_VERSION}" -o /tmp/webview2.zip && \
unzip -q /tmp/webview2.zip -d /tmp/webview2 && \
rm /tmp/webview2.zip

# Create a stub EventToken.h. The webview_go module's bundled WebView2.h
# includes this Windows SDK header, which MinGW does not provide.
RUN mkdir -p /tmp/winsdk && \
printf '#pragma once\ntypedef struct EventRegistrationToken { __int64 value; } EventRegistrationToken;\n' \
> /tmp/winsdk/EventToken.h

# Generate a MinGW import library for the XMR DLL. The MinGW linker cannot
# link directly against a .dll. Named .a (not .dll.a) because webview_go's
# CGO LDFLAGS include -static, which makes the linker skip .dll.a files.
RUN if [ "$XMR" = "1" ]; then \
cd /src/client/asset/xmr/lib/windows-amd64 && \
gendef libwallet2_api_c.dll && \
x86_64-w64-mingw32-dlltool -d libwallet2_api_c.def \
-l libwallet2_api_c.a -D libwallet2_api_c.dll; \
fi

RUN mkdir -p /out

ENV GOOS=windows
ENV GOARCH=amd64
ENV CGO_ENABLED=1
ENV CC=x86_64-w64-mingw32-gcc
ENV CXX=x86_64-w64-mingw32-g++
ENV CGO_CXXFLAGS="-I/tmp/winsdk"

RUN if [ "$XMR" = "1" ]; then \
go build -v -tags xmr -ldflags="-H windowsgui" -o /out/bisonw-desktop.exe; \
else \
go build -v -ldflags="-H windowsgui" -o /out/bisonw-desktop.exe; \
fi

# Bundle runtime DLLs that are not present on a stock Windows install.
RUN cp /tmp/webview2/runtimes/win-x64/native/WebView2Loader.dll /out/ && \
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll /out/

RUN if [ "$XMR" = "1" ]; then \
cp /src/client/asset/xmr/lib/windows-amd64/libwallet2_api_c.dll /out/; \
fi
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
## Windows build
# Windows build

## Native build

### Setting up the build environment

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.

Download and run setup as Administrator (privileges are required in order to set environment variables). Open a command prompt as Administrator, and run:
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:

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

Build the Windows binary:
Build the Windows binary:

```batch
windows\build-windows.cmd
Expand All @@ -39,3 +41,58 @@ windows\pkg-windows.cmd
```

The resulting installer binary will be located in `build\msi`.

## Cross-compiling from Linux with Docker

The Windows `.exe` can be cross-compiled from Linux using Docker. This does not produce the MSI installer.

### Prerequisites

Build the site bundle if it hasn't been built already:

```bash
cd client/webserver/site
npm clean-install
npm run build
cd ../../..
```

### Build the exe

From the repo root:

```bash
docker build -t bisonw-desktop-windows -f client/cmd/bisonw-desktop/windows/Dockerfile .
```

To include XMR support:

```bash
docker build -t bisonw-desktop-windows --build-arg XMR=1 -f client/cmd/bisonw-desktop/windows/Dockerfile .
```

### Extract the build output

```bash
mkdir -p build && docker run --rm bisonw-desktop-windows tar -cf - -C /out . | tar -xf - -C ./build
```

The `build/` directory will contain `bisonw-desktop.exe`, `WebView2Loader.dll`, `libwinpthread-1.dll`, and `libwallet2_api_c.dll` if XMR was enabled.

### Packaging the MSI on Windows

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`:

```batch
windows\pkg-windows.cmd --skip-build
```

To include XMR support in the MSI:

```batch
windows\pkg-windows.cmd --skip-build --xmr
```

The resulting installer will be in `build\msi`.

**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.
42 changes: 32 additions & 10 deletions client/cmd/bisonw-desktop/windows/pkg-windows.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,40 @@

call windows\env-windows.cmd

:: Run build
call windows\build-windows.cmd %*

:: Check the error level after the first command
if %errorlevel% equ 0 (
echo Build completed successfully.
echo Building MSI
dotnet build --property:Platform=x64 --configuration Release --output build\msi -noWarn:WIX1076 windows\windows-msi\BisonWallet_Installer.wixproj
echo MSI built in build\msi
:: Parse flags.
set "XMR_ENABLED=0"
set "SKIP_BUILD=0"
:parse_args
if "%~1"=="" goto done_args
if "%~1"=="--xmr" set "XMR_ENABLED=1"
if "%~1"=="--skip-build" set "SKIP_BUILD=1"
shift
goto parse_args
:done_args

if "%SKIP_BUILD%"=="1" (
echo Skipping build, packaging existing files in build\windows...
goto :MSI
)

:: Run build. Only forward --xmr if set; build-windows.cmd does not
:: understand --skip-build.
if "%XMR_ENABLED%"=="1" (
call windows\build-windows.cmd --xmr
) else (
call windows\build-windows.cmd
)

if %errorlevel% neq 0 (
echo Error occurred during build.
exit /b 1
)
echo Build completed successfully.

:MSI
echo Building MSI
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
echo MSI built in build\msi

echo Signing %exeFile%
call windows\sign-windows.cmd %exeFile%
call windows\sign-windows.cmd %exeFile%
16 changes: 16 additions & 0 deletions client/cmd/bisonw-desktop/windows/windows-msi/BisonWallet.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@
<File Source="..\..\build\windows\Bisonw-desktop.exe" Id="BisonwDesktopExe" KeyPath="yes" Checksum="yes" />
<File Source="..\..\build\windows\WebView2Loader.dll" Checksum="yes" />
</Component>
<?if $(var.CrossCompiled) = 1 ?>
<Component Id="MinGWRuntime" Guid="a1d4f8e2-7b39-4c56-8e1a-5f9d3c6b2e08">
<File Source="..\..\build\windows\libwinpthread-1.dll" Checksum="yes" />
</Component>
<?endif ?>
<?if $(var.XmrEnabled) = 1 ?>
<Component Id="XmrLibrary" Guid="b7a3e1f4-5c82-4d19-9a6b-3e8f2d7c1a05">
<File Source="..\..\build\windows\libwallet2_api_c.dll" Checksum="yes" />
</Component>
<?endif ?>
</DirectoryRef>

<DirectoryRef Id="ApplicationProgramsFolder">
Expand All @@ -25,6 +35,12 @@
<Feature Id="MainApplication" Title="Main Application" Level="1">
<ComponentRef Id="BisonwDesktopExe" />
<ComponentRef Id="ApplicationShortcut" />
<?if $(var.CrossCompiled) = 1 ?>
<ComponentRef Id="MinGWRuntime" />
<?endif ?>
<?if $(var.XmrEnabled) = 1 ?>
<ComponentRef Id="XmrLibrary" />
<?endif ?>
</Feature>

<StandardDirectory Id="ProgramFiles64Folder">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
<Project Sdk="WixToolset.Sdk/5.0.0">
<PropertyGroup>
<XmrEnabled Condition="'$(XmrEnabled)' == ''">0</XmrEnabled>
<CrossCompiled Condition="'$(CrossCompiled)' == ''">0</CrossCompiled>
<DefineConstants>XmrEnabled=$(XmrEnabled);CrossCompiled=$(CrossCompiled)</DefineConstants>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion client/tor/build_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ BASE_DIR=$(realpath $(dirname $0))
BUILD_DIR="${BASE_DIR}/build"
REPO_DIR="${BUILD_DIR}/torrepo"

COMMIT_HASH=3cb6a690be60fcdab60130402ff88dcfc0657596
COMMIT_HASH=d133d41f5d285c2f0a9c2fd75acde285d67afd3d

rm -r -f "${REPO_DIR}"
mkdir -p "${REPO_DIR}"
Expand Down
Loading