Skip to content

Commit 306d9d6

Browse files
authored
Merge pull request #1329 from spkenv/windows-cross-compilation
Enable Arch Linux to Windows cross-compilation workflow
2 parents 9392b2e + 9f55998 commit 306d9d6

File tree

9 files changed

+159
-10
lines changed

9 files changed

+159
-10
lines changed

.cargo/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[target.x86_64-pc-windows-gnu]
2+
linker = "x86_64-w64-mingw32-gcc"
3+
ar = "x86_64-w64-mingw32-gcc-ar"

.github/workflows/rust.yml

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,56 @@ jobs:
2323
uses: crazy-max/ghaction-chocolatey@v3
2424
with:
2525
args: install protoc llvm winfsp make
26+
- name: Verify Chocolatey packages and retry if needed
27+
# The chocolatey install step can partially succeed: if the
28+
# Chocolatey CDN returns a transient error (e.g. 504 Gateway
29+
# Timeout) for one package, other packages may still install
30+
# fine and the step exits successfully. This leaves the build
31+
# missing critical dependencies, causing confusing failures
32+
# later (e.g. winfsp-sys build.rs panic). This step verifies
33+
# that all required packages are actually present and retries
34+
# any that are missing.
35+
shell: pwsh
36+
run: |
37+
function Test-Packages {
38+
$missing = @()
39+
if (-not (Test-Path "C:\Program Files (x86)\WinFsp")) {
40+
$missing += "winfsp"
41+
}
42+
if (-not (Get-Command protoc -ErrorAction SilentlyContinue)) {
43+
$missing += "protoc"
44+
}
45+
if (-not (Get-Command make -ErrorAction SilentlyContinue)) {
46+
$missing += "make"
47+
}
48+
if (-not (Get-Command clang -ErrorAction SilentlyContinue)) {
49+
$missing += "llvm"
50+
}
51+
return $missing
52+
}
53+
54+
$missing = Test-Packages
55+
if ($missing.Count -eq 0) {
56+
Write-Host "All required packages verified successfully."
57+
exit 0
58+
}
59+
60+
$maxRetries = 2
61+
for ($attempt = 1; $attempt -le $maxRetries; $attempt++) {
62+
Write-Host "::warning::Missing packages: $($missing -join ', '). Retry attempt $attempt of $maxRetries..."
63+
Start-Sleep -Seconds 15
64+
choco install $missing -y --allow-unofficial
65+
$missing = Test-Packages
66+
if ($missing.Count -eq 0) {
67+
Write-Host "All required packages verified successfully after retry."
68+
exit 0
69+
}
70+
}
71+
72+
foreach ($pkg in $missing) {
73+
Write-Host "::error::Required package not installed after retries: $pkg"
74+
}
75+
exit 1
2676
- name: Install FlatBuffers Compiler
2777
run: |
2878
$url = "https://github.com/google/flatbuffers/releases/download/v23.5.26/Windows.flatc.binary.zip"
@@ -146,7 +196,7 @@ jobs:
146196
crates/spfs/tests/integration/run_privileged_tests.sh
147197
148198
matrix-build:
149-
name: build features ${{ matrix.no-default-features }} ${{ matrix.features }}
199+
name: build ${{ matrix.platform }} features ${{ matrix.no-default-features }} ${{ matrix.features }}
150200
runs-on: ubuntu-latest
151201
timeout-minutes: 45
152202
container:
@@ -159,12 +209,24 @@ jobs:
159209
strategy:
160210
fail-fast: false
161211
matrix:
212+
platform:
213+
- linux
162214
features:
163215
# SPI's standand features
164216
- migration-to-components,sentry,spfs/protobuf-src,spfs-vfs/protobuf-src,statsd,fuse-backend-rhel-7-6
165217
no-default-features:
166218
- ""
167219
- --no-default-features
220+
target:
221+
- ""
222+
exclude_crates:
223+
- ""
224+
include:
225+
- platform: windows
226+
features: server,spfs/server
227+
no-default-features: ""
228+
target: x86_64-pc-windows-gnu
229+
exclude_crates: --exclude spfs-cli-winfsp --workspace
168230
steps:
169231
- name: Cancel Previous Runs
170232
uses: styfle/cancel-workflow-action@0.11.0
@@ -179,6 +241,11 @@ jobs:
179241
curl --proto '=https' --tlsv1.2 -sSfL ${FB_REL}/download/v23.5.26/Linux.flatc.binary.g++-10.zip | funzip > /usr/bin/flatc
180242
chmod +x /usr/bin/flatc
181243
rustup component add clippy
244+
- name: Setup cross-compilation
245+
if: matrix.platform == 'windows'
246+
run: |
247+
apt-get install -y gcc-mingw-w64-x86-64
248+
rustup target add ${{ matrix.target }}
182249
- name: Configure cargo
183250
run: |
184251
mkdir -p .cargo
@@ -188,6 +255,14 @@ jobs:
188255
# can't cache incremental compiles.
189256
incremental = false
190257
EOF
258+
- name: Configure cross-compile linker
259+
if: matrix.platform == 'windows'
260+
run: |
261+
cat << 'EOF' >> .cargo/config.toml
262+
[target.x86_64-pc-windows-gnu]
263+
linker = "x86_64-w64-mingw32-gcc"
264+
ar = "x86_64-w64-mingw32-gcc-ar"
265+
EOF
191266
- name: Run sccache-cache
192267
uses: mozilla-actions/sccache-action@v0.0.9
193268
- name: Restore ast-grep cache
@@ -213,3 +288,5 @@ jobs:
213288
${{ matrix.no-default-features }}
214289
--features "${{ matrix.features }}"
215290
--all-targets
291+
${{ matrix.target && format('--target {0}', matrix.target) || '' }}
292+
${{ matrix.exclude_crates }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ target/
3333
.cache/
3434
.hugo_build.lock
3535
/.cargo/
36+
!/.cargo/
37+
!/.cargo/config.toml

Cross.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
[target.x86_64-pc-windows-gnu]
2-
pre-build = ["apt-get install -y protobuf-compiler"]
2+
pre-build = [
3+
"apt-get update && apt-get install -y protobuf-compiler curl unzip",
4+
"curl --proto '=https' --tlsv1.2 -sSfL https://github.com/google/flatbuffers/releases/download/v23.5.26/Linux.flatc.binary.g++-10.zip | funzip > /usr/local/bin/flatc",
5+
"chmod +x /usr/local/bin/flatc",
6+
"cargo install --locked ast-grep",
7+
]

Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ cargo_features_arg = $(if $(FEATURES),--features $(FEATURES))
99
cargo_packages_arg := $(if $(CRATES),-p=$(CRATES))
1010
cargo_packages_arg := $(subst $(comma), -p=,$(cargo_packages_arg))
1111
cargo_packages_arg := $(if $(cargo_packages_arg),$(cargo_packages_arg),--workspace)
12+
cargo_excludes_arg ?=
1213

1314
# Suppress this warning to not muddle the test output.
1415
export SPFS_SUPPRESS_OVERLAYFS_PARAMS_WARNING = 1
@@ -54,11 +55,11 @@ lint-fmt:
5455

5556
.PHONY: lint-clippy
5657
lint-clippy:
57-
$(CARGO) clippy --tests $(cargo_features_arg) $(cargo_packages_arg) $(CARGO_ARGS) -- -Dwarnings
58+
$(CARGO) clippy --tests $(cargo_features_arg) $(cargo_packages_arg) $(cargo_excludes_arg) $(CARGO_ARGS) -- -Dwarnings
5859

5960
.PHONY: lint-docs
6061
lint-docs:
61-
env RUSTDOCFLAGS="-Dwarnings" cargo doc --no-deps $(cargo_features_arg) $(cargo_packages_arg)
62+
env RUSTDOCFLAGS="-Dwarnings" cargo doc --no-deps $(cargo_features_arg) $(cargo_packages_arg) $(cargo_excludes_arg)
6263

6364
.PHONY: format
6465
format:
@@ -68,13 +69,13 @@ format:
6869
build: debug
6970

7071
debug:
71-
$(CARGO) build $(cargo_packages_arg) $(cargo_features_arg) $(CARGO_ARGS)
72+
$(CARGO) build $(cargo_packages_arg) $(cargo_excludes_arg) $(cargo_features_arg) $(CARGO_ARGS)
7273

7374
debug-spfs:
7475
$(MAKE) debug CRATES=$(spfs_packages)
7576

7677
release:
77-
$(CARGO) build --release $(cargo_packages_arg) $(cargo_features_arg) $(CARGO_ARGS)
78+
$(CARGO) build --release $(cargo_packages_arg) $(cargo_excludes_arg) $(cargo_features_arg) $(CARGO_ARGS)
7879

7980
release-spfs:
8081
$(MAKE) release CRATES=$(spfs_packages)

Makefile.linux

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,16 @@ CARGO_TARGET_DIR := $(shell \
88

99
export PLATFORM ?= unix
1010
ifeq ($(PLATFORM),windows)
11-
spfs_packages := $(spfs_packages),spfs-cli-winfsp
12-
CARGO_ARGS += --target x86_64-pc-windows-gnu
13-
# swap cargo for cross when building for other platforms
14-
CARGO = cross
11+
WINDOWS_TARGET ?= x86_64-pc-windows-gnu
12+
CARGO_ARGS += --target $(WINDOWS_TARGET)
13+
# winfsp-sys requires a Windows host in its build script, so exclude the
14+
# winfsp CLI crate for Linux-hosted workspace cross-compiles.
15+
cargo_excludes_arg += $(if $(CRATES),,--exclude spfs-cli-winfsp)
16+
# Default to cargo for Linux -> Windows cross-compilation. This works on
17+
# Arch Linux with mingw-w64-gcc. To use containerized cross, set:
18+
# WINDOWS_CARGO=cross
19+
WINDOWS_CARGO ?= cargo
20+
CARGO = $(WINDOWS_CARGO)
1521
else
1622
spfs_packages := $(spfs_packages),spfs-cli-fuse,spfs-cli-monitor
1723
endif

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,42 @@ ast-grep is also used when compiling, it can be installed with the following com
234234
cargo install --locked ast-grep
235235
```
236236

237+
### Cross-Compiling for Windows from Arch Linux
238+
239+
You can cross-compile Windows binaries on Arch Linux without Docker by using
240+
the GNU Windows target and MinGW tools.
241+
242+
```sh
243+
sudo pacman -S --needed \
244+
mingw-w64-gcc \
245+
protobuf \
246+
flatbuffers \
247+
ast-grep
248+
rustup target add x86_64-pc-windows-gnu
249+
```
250+
251+
Then build with:
252+
253+
```sh
254+
make release PLATFORM=windows FEATURES=server,spfs/server
255+
```
256+
257+
Output binaries are written to:
258+
259+
```text
260+
target/x86_64-pc-windows-gnu/release/
261+
```
262+
263+
When cross-compiling from Linux, workspace builds automatically exclude
264+
`spfs-cli-winfsp` because `winfsp-sys` requires running its build script on a
265+
Windows host. Build that crate natively on Windows if needed.
266+
267+
If you prefer containerized cross-compilation, install `cross` and run:
268+
269+
```sh
270+
make release PLATFORM=windows WINDOWS_CARGO=cross FEATURES=server,spfs/server
271+
```
272+
237273
### Benchmarks
238274

239275
Benchmark tests can be found in `benches/`. All benchmark tests can be run with `cargo bench`, but in order to successfully pass `criterion`-specific options to the `criterion`-based benchmarks, those types of benchmarks need to be filtered for.

cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@
522522
"OWYWHJKCVRKGSBL",
523523
"OXFB",
524524
"OYMIQUY",
525+
"pacman",
525526
"parsedbuf",
526527
"parsewords",
527528
"partio",

docs/admin/install.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,21 @@ make install-spfs # only spfs
2222
Currently, only spfs is supported on windows and is still considered experimental. File systems can be mounted and viewed, but not modified. See above on building from source - windows builds will require WinFSP to be installed rather than fuse libraries.
2323

2424
<!-- TODO: include really basic make instructions as above for playing with this -->
25+
26+
### Cross-Compile for Windows From Arch Linux
27+
28+
To cross-compile from Arch Linux, install:
29+
30+
```sh
31+
sudo pacman -S --needed mingw-w64-gcc protobuf flatbuffers ast-grep
32+
rustup target add x86_64-pc-windows-gnu
33+
```
34+
35+
Then build:
36+
37+
```sh
38+
make release PLATFORM=windows FEATURES=server,spfs/server
39+
```
40+
41+
For Linux-hosted workspace builds, `spfs-cli-winfsp` is excluded because its
42+
`winfsp-sys` dependency requires a Windows host during build-script execution.

0 commit comments

Comments
 (0)