1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
# Cross-Compiling Windows Binaries on Linux
This document describes how to build `zenserver.exe` and `zen.exe` for Windows
from a Linux host using clang-cl, lld-link, and the Windows SDK fetched via
[xwin](https://github.com/Jake-Shadle/xwin).
## Prerequisites
- **LLVM/Clang 17+** with the following tools (typically in `/usr/lib/llvm-<ver>/bin/`):
- `clang` (used as `clang-cl` via `--driver-mode=cl`)
- `lld-link`
- `llvm-lib`
- `llvm-rc`
- `llvm-ml`
- `llvm-mt`
On Ubuntu/Debian:
```bash
sudo apt install clang-18 lld-18 llvm-18
```
- **xmake** (build system) — see [xmake.io](https://xmake.io) for installation.
## Step 1: Fetch the Windows SDK
Run the provided script to download the Windows SDK and MSVC CRT headers/libs:
```bash
./scripts/win_cross/get_win_sdk.sh
```
This downloads the SDK to `~/.xwin-sdk` by default. Override the location with
an argument or the `$XWIN_SDK_DIR` environment variable:
```bash
./scripts/win_cross/get_win_sdk.sh /path/to/sdk
```
The script also creates:
- Tool wrapper scripts (clang-cl, lld-link, llvm-lib, etc.) in the SDK `bin/` directory
- An MSVC-compatible directory layout that xmake's built-in clang-cl toolchain can discover
- Debug CRT lib symlinks so cmake package builds succeed
## Step 2: Configure and Build
```bash
xmake config -y -p windows -a x64 \
--toolchain=clang-cl \
--sdk=$HOME/.xwin-sdk \
--mrc=$HOME/.xwin-sdk/bin/x64/rc.exe \
-m release \
--zensentry=n \
--zenmimalloc=n
xmake
```
### Notes
- **`--sdk` must use an absolute path** — `$HOME/.xwin-sdk` works, but
`~/.xwin-sdk` does not (xmake doesn't expand `~`).
- **`--mrc`** points to the resource compiler wrapper. Without it, xmake can't
auto-detect `llvm-rc` (it doesn't support `--version`).
- **`--zensentry=no`** is recommended — crashpad (used by sentry-native) is
difficult to cross-compile.
- **`--zenmimalloc=no`** is recommended initially to reduce the package surface.
- **LTO is automatically disabled** for cross-compilation builds.
## Step 3: Verify
```bash
file build/windows/x64/release/zenserver.exe
# PE32+ executable (console) x86-64, for MS Windows, 12 sections
file build/windows/x64/release/zen.exe
# PE32+ executable (console) x86-64, for MS Windows, 12 sections
```
## Running with Wine (optional)
The resulting binaries can be run under Wine for testing:
```bash
wine build/windows/x64/release/zenserver.exe --help
```
## Troubleshooting
### Library not found (case sensitivity)
The Windows SDK ships headers and libs with specific casing (e.g. `DbgHelp.h`,
`ws2_32.lib`). Linux filesystems are case-sensitive, so `#include <Dbghelp.h>`
won't find `DbgHelp.h`. The codebase uses lowercase includes where possible. If
you encounter a missing header/lib, check the actual casing in the SDK directory.
### `add_ldflags(...) is ignored`
xmake's auto flag checker may reject MSVC linker flags when using clang-cl. Add
`{force = true}` to the `add_ldflags()` call.
### Stale build state
If you hit unexpected errors after changing toolchain settings, clean everything:
```bash
rm -rf .xmake build ~/.xmake
```
Then reconfigure and rebuild.
|