aboutsummaryrefslogtreecommitdiff
path: root/docs/WindowsOnLinux.md
blob: 540447cb267311df5edf1fe8579f88d1a2e410d5 (plain) (blame)
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.