Use Rust in the Windows CI jobs
Subsystems (2)
cover Use Rust in the Windows CI jobs
With v2.55.0, Git requires Rust by default, with an opt-out that is intended to be dropped in one of the next versions.
Due to the special circumstances in the Windows part of the CI builds, each Windows build job first downloads a "minimal Git for Windows SDK" that contains the GCC toolchain required to build and test Git. As a consequence, brian m. carlson opted out of Rust in Git's CI definition in 32d5b905909e (Enable Rust by default, 2026-04-09).
So: How could we stop opting out? Notably, Rust is not part of that minimal Git for Windows SDK, and including it would more than double that payload, which I consider prohibitive. Yet including Rust in the minimal Git for Windows SDK is not actually necessary, at least not for the GitHub workflow:
The runners on which this workflow is defined to run come with Rust pre-installed.
Granted, this Rust installation is configured to target the Windows-native C compiler, Visual C. To accommodate for the Windows CI job building with GCC, this patch series adds a step to the workflow that ensures that the needed Rust bits are installed and configured.
RFH: I haven't been able to confirm that GitLab's Windows runners come with Rust preinstalled,
https://docs.gitlab.com/ci/runners/hosted_runners/windows/#available-runtimes
did not clarify that for me. Patrick (or anyone else with access to GitLab CI), could you see whether this patch series builds on saas-windows-medium-amd64 without need for further changes?
Johannes Schindelin (2):
rust: pick a GCC-compatible Cargo target under MSYS2/MinGW ci(windows): build with Rust
.github/workflows/main.yml | 24 ++++++++++++++++++++++++ Makefile | 3 ++- ci/lib.sh | 3 --- config.mak.uname | 24 +++++++++++++++++++++++- 4 files changed, 49 insertions(+), 5 deletions(-)
base-commit: 8cd717011ba08f30f451ec802047df275fe2980d
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2213%2Fdscho%2Fuse-rust-in-windows-ci-builds-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2213/dscho/use-rust-in-windows-ci-builds-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2213
Signature · 1 line
gitgitgadget
PATCH 1/2 rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
From: Johannes Schindelin <[email protected]>
When Git is built under MSYS2/MinGW with Rust support enabled, the Makefile expects cargo build to drop a target/release/libgitcore.a that is linkable by the same MinGW GCC used for every other object. With Rust installed via rustup (the way it ships on the GitHub-hosted windows-2022 and windows-11-arm runners that build microsoft/git), the default toolchain targets the MSVC ABI; cargo then writes target/release/gitcore.lib instead, which the MinGW ld.exe cannot consume:
LINK git-shell.exe
D:\git-sdk-64-minimal\mingw64\bin/ld.exe: cannot find target/release/libgitcore.a: No such file or directory collect2.exe: error: ld returned 1 exit status
See https://github.com/microsoft/git/actions/runs/27341625000 for the full log.
Let's define the correct target. Re-use (and fix) the existing HOST_CPU variable for that purpose. Avoid relying on environment variables that are simply not defined in Git for Windows' minimal SDK that Git uses in its CI runs.
--- Makefile | 3 ++- config.mak.uname | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-)
Makefile +2 -1
@@ -959,7 +959,7 @@ RUST_LIB_NAME = gitcore.lib else RUST_LIB_NAME = libgitcore.a endif -RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) +RUST_LIB = target$(if $(CARGO_TARGET),/$(CARGO_TARGET))/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) endif GITLIBS = common-main.o $(LIB_FILE)
@@ -993,6 +993,7 @@ endif ifndef DEBUG CARGO_ARGS += --release endif +CARGO_ARGS += $(if $(CARGO_TARGET),--target $(CARGO_TARGET)) # For the 'sparse' target SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__
config.mak.uname +23 -1
@@ -758,7 +758,29 @@ ifeq ($(uname_S),MINGW) MINGW_PREFIX := /$(shell echo '$(MSYSTEM)' | tr A-Z a-z) endif prefix = $(MINGW_PREFIX) - HOST_CPU = $(patsubst %-w64-mingw32,%,$(MINGW_CHOST)) + + # A rustup-managed Rust on Windows defaults to the MSVC ABI and + # produces a `gitcore.lib` that the MinGW `ld.exe` cannot link. + # Pick a GCC-compatible Rust target triple matching the MSYS2 + # subsystem instead: `*-pc-windows-gnullvm` for the Clang/LLVM + # subsystems (which on Windows is also the only choice for + # ARM64, where no MinGW-GCC port exists) and `*-pc-windows-gnu` + # for the MSVCRT-based MinGW subsystems. For a `staticlib` + # crate-type Cargo does not invoke an external linker, so + # `rustup target add <triple>` is sufficient. + ifneq (,$(filter %ARM64, $(MSYSTEM))) + HOST_CPU = aarch64 + else ifneq (,$(filter %32, $(MSYSTEM))) + HOST_CPU = i686 + else + HOST_CPU = x86_64 + endif + ifneq (,$(filter CLANG%, $(MSYSTEM))) + CARGO_TARGET = $(HOST_CPU)-pc-windows-gnullvm + else + CARGO_TARGET = $(HOST_CPU)-pc-windows-gnu + endif + BASIC_LDFLAGS += -Wl,--pic-executable COMPAT_CFLAGS += -DDETECT_MSYS_TTY \ -DENSURE_MSYSTEM_IS_SET="\"$(MSYSTEM)\"" \
Signature · 1 line
gitgitgadget
PATCH 2/2 ci(windows): build with Rust
In reply to Johannes Schindelin via GitGitGadgetFrom: Johannes Schindelin <[email protected]>
The Windows runners used by Git's GitHub workflow's windows-build job ship rustup plus a *-pc-windows-msvc default toolchain (see
https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md
and
https://github.com/actions/partner-runner-images/blob/main/images/arm-windows-11-image.md),
but no precompiled std for *-pc-windows-gnu or *-pc-windows-gnullvm. With the Makefile now picking a GCC-compatible target triple based on $(MSYSTEM), the build step needs that precompiled std to be installed before invoking make, otherwise cargo build --target <triple> fails to find a usable std for the chosen target.
Add a step between the SDK setup and the make invocation that selects the matching triple from $MSYSTEM (which git-for-windows/setup-git-for-windows-sdk exports for every subsequent step) and runs rustup target add for it. The mapping mirrors what config.mak.uname derives from $(MSYSTEM) and $(HOST_CPU), just enumerated explicitly here since CI has direct knowledge of which MSYS2 subsystems the matrix actually exercises (CLANGARM64 for the ARM64 runner, MINGW64 for the x86_64 runner). Technically, we only need to handle MINGW64 at present, but the switch to UCRT64 is imminent, and the other case arms serve as a very fine documentation of what people should do for other MSYSTEM values.
For a staticlib crate-type cargo build does not invoke an external linker, so no further toolchain components (e.g. the gnullvm LLVM linker) need to be installed; rustup target add alone is sufficient.
--- .github/workflows/main.yml | 24 ++++++++++++++++++++++++ ci/lib.sh | 3 --- 2 files changed, 24 insertions(+), 3 deletions(-)
.github/workflows/main.yml +24 -0
@@ -114,6 +114,30 @@ jobs: steps: - uses: actions/checkout@v6 - uses: git-for-windows/setup-git-for-windows-sdk@v2 + - name: Install GCC-compatible Rust target + shell: bash + run: | + # The hosted Windows runners ship a rustup-managed Rust whose + # default toolchain targets the MSVC ABI. That produces a + # `gitcore.lib` which the MinGW GCC used by the rest of the + # build cannot link. Install the precompiled `std` for a + # GCC-compatible target triple matching the MSYS2 subsystem; + # the Makefile selects the same triple via $(MSYSTEM) and + # passes it to `cargo build --target`. + case "$MSYSTEM" in + CLANGARM64) target=aarch64-pc-windows-gnullvm ;; + CLANG64) target=x86_64-pc-windows-gnullvm ;; + CLANG32) target=i686-pc-windows-gnullvm ;; + UCRT64) target=x86_64-pc-windows-gnullvm ;; + MINGW64) target=x86_64-pc-windows-gnu ;; + MINGW32) target=i686-pc-windows-gnu ;; + *) echo "::error::Unsupported MSYSTEM: $MSYSTEM"; exit 1 ;; + esac && + rustup target add "$target" && + + # Ensure that cargo.exe is found even with the minimal SDK's restricted PATH + CARGO="$(type -p cargo.exe)" && + echo "export PATH=\$PATH:${CARGO%/cargo.exe}" >>/etc/profile - name: build shell: bash env:
ci/lib.sh +0 -3
@@ -391,9 +391,6 @@ linux-asan-ubsan) osx-meson) MESONFLAGS="$MESONFLAGS -Dcredential_helpers=osxkeychain" ;; -windows-*) - export NO_RUST=UnfortunatelyYes - ;; esac MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}"
Signature · 1 line
gitgitgadget
Re: [PATCH 1/2] rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
In reply to Johannes Schindelin via GitGitGadget"Johannes Schindelin via GitGitGadget" <[email protected]>
config.mak.uname ifeq ($(uname_S),MINGW) · line 782
Quoted 12 lines · writes:
config.mak.uname +12
-0+ ifneq (,$(filter %ARM64, $(MSYSTEM))) + HOST_CPU = aarch64 + else ifneq (,$(filter %32, $(MSYSTEM))) + HOST_CPU = i686 + else + HOST_CPU = x86_64 + endif + ifneq (,$(filter CLANG%, $(MSYSTEM))) + CARGO_TARGET = $(HOST_CPU)-pc-windows-gnullvm + else + CARGO_TARGET = $(HOST_CPU)-pc-windows-gnu + endif
Assuming HOST_CPU is x86_64 in the above, as UCRT64, unlike CLANG{ARM64,64,32}, does not match CLANG%, I presume that the above gives "x86_64-pc-windows-gnu" to builds with MSYSTEM set to UCRT64.
There is this "we only need MINGW64 but the switch to UCRT64 is imminent, and others are for documentation" part we see in the [PATCH 2/2]
+ case "$MSYSTEM" in + CLANGARM64) target=aarch64-pc-windows-gnullvm ;; + CLANG64) target=x86_64-pc-windows-gnullvm ;; + CLANG32) target=i686-pc-windows-gnullvm ;; + UCRT64) target=x86_64-pc-windows-gnullvm ;; + MINGW64) target=x86_64-pc-windows-gnu ;; + MINGW32) target=i686-pc-windows-gnu ;; + *) echo "::error::Unsupported MSYSTEM: $MSYSTEM"; exit 1 ;; + esac && + rustup target add "$target" &&
that maps UCRT64 to "x86_64-pc-windows-gnullvm"
I do not know if it is intended. If so, please ignore.
Thanks.
Re: [PATCH 1/2] rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
Hi Junio,
Quoted 19 lines · Junio C Hamano
"Johannes Schindelin via GitGitGadget" <[email protected]>
config.mak.uname ifeq ($(uname_S),MINGW) · line 782
Quoted 12 lines · writes:
config.mak.uname +12
-0+ ifneq (,$(filter %ARM64, $(MSYSTEM))) + HOST_CPU = aarch64 + else ifneq (,$(filter %32, $(MSYSTEM))) + HOST_CPU = i686 + else + HOST_CPU = x86_64 + endif + ifneq (,$(filter CLANG%, $(MSYSTEM))) + CARGO_TARGET = $(HOST_CPU)-pc-windows-gnullvm + else + CARGO_TARGET = $(HOST_CPU)-pc-windows-gnu + endifAssuming
HOST_CPUisx86_64in the above, as UCRT64, unlike CLANG{ARM64,64,32}, does not match CLANG%, I presume that the above gives "x86_64-pc-windows-gnu" to builds with MSYSTEM set to UCRT64.
Correct.
Quoted 15 lines
There is this "we only need MINGW64 but the switch to UCRT64 is imminent, and others are for documentation" part we see in the [PATCH 2/2]
(quoted diff) +10
-0+ case "$MSYSTEM" in + CLANGARM64) target=aarch64-pc-windows-gnullvm ;; + CLANG64) target=x86_64-pc-windows-gnullvm ;; + CLANG32) target=i686-pc-windows-gnullvm ;; + UCRT64) target=x86_64-pc-windows-gnullvm ;; + MINGW64) target=x86_64-pc-windows-gnu ;; + MINGW32) target=i686-pc-windows-gnu ;; + *) echo "::error::Unsupported MSYSTEM: $MSYSTEM"; exit 1 ;; + esac && + rustup target add "$target" &&
Quoted 3 lines
that maps UCRT64 to "x86_64-pc-windows-gnullvm"
I do not know if it is intended. If so, please ignore.
Since UCRT64 is still using GCC, it should be -gnu. Thanks for catching.
Ciao,
Johannes
v2 cover Use Rust in the Windows CI jobs
In reply to Johannes Schindelin via GitGitGadgetWith v2.55.0, Git requires Rust by default, with an opt-out that is intended to be dropped in one of the next versions.
Due to the special circumstances in the Windows part of the CI builds, each Windows build job first downloads a "minimal Git for Windows SDK" that contains the GCC toolchain required to build and test Git. As a consequence, brian m. carlson opted out of Rust in Git's CI definition in 32d5b905909e (Enable Rust by default, 2026-04-09).
So: How could we stop opting out? Notably, Rust is not part of that minimal Git for Windows SDK, and including it would more than double that payload, which I consider prohibitive. Yet including Rust in the minimal Git for Windows SDK is not actually necessary, at least not for the GitHub workflow:
The runners on which this workflow is defined to run come with Rust pre-installed.
Granted, this Rust installation is configured to target the Windows-native C compiler, Visual C. To accommodate for the Windows CI job building with GCC, this patch series adds a step to the workflow that ensures that the needed Rust bits are installed and configured.
RFH: I haven't been able to confirm that GitLab's Windows runners come with Rust preinstalled,
https://docs.gitlab.com/ci/runners/hosted_runners/windows/#available-runtimes
did not clarify that for me. Patrick (or anyone else with access to GitLab CI), could you see whether this patch series builds on saas-windows-medium-amd64 without need for further changes?
Changes since v1:
* The inconsistency pointed out by Junio, that UCRT64 was once marked as using clang and once as using gcc was fixed by clarifying that UCRT64 uses GCC.
Johannes Schindelin (2):
rust: pick a GCC-compatible Cargo target under MSYS2/MinGW ci(windows): build with Rust
.github/workflows/main.yml | 24 ++++++++++++++++++++++++ Makefile | 3 ++- ci/lib.sh | 3 --- config.mak.uname | 24 +++++++++++++++++++++++- 4 files changed, 49 insertions(+), 5 deletions(-)
base-commit: f4742f3165d096130c39a71feb26374da37620f2
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2213%2Fdscho%2Fuse-rust-in-windows-ci-builds-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2213/dscho/use-rust-in-windows-ci-builds-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/2213
Range-diff vs v1:
1: 2b7f58a037 = 1: 6567eceb32 rust: pick a GCC-compatible Cargo target under MSYS2/MinGW 2: 7a24630fb9 ! 2: 07415393e5 ci(windows): build with Rust
@@ Commit message
linker) need to be installed; rustup target add alone is sufficient.
+ Helped-by: Junio C Hamano <[email protected]>
## .github/workflows/main.yml ##
@@ .github/workflows/main.yml: jobs:
+ CLANGARM64) target=aarch64-pc-windows-gnullvm ;;
+ CLANG64) target=x86_64-pc-windows-gnullvm ;;
+ CLANG32) target=i686-pc-windows-gnullvm ;;
-+ UCRT64) target=x86_64-pc-windows-gnullvm ;;
++ UCRT64) target=x86_64-pc-windows-gnu ;;
+ MINGW64) target=x86_64-pc-windows-gnu ;;
+ MINGW32) target=i686-pc-windows-gnu ;;
+ *) echo "::error::Unsupported MSYSTEM: $MSYSTEM"; exit 1 ;;
Signature · 1 line
gitgitgadget
PATCH v2 1/2 rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
From: Johannes Schindelin <[email protected]>
When Git is built under MSYS2/MinGW with Rust support enabled, the Makefile expects cargo build to drop a target/release/libgitcore.a that is linkable by the same MinGW GCC used for every other object. With Rust installed via rustup (the way it ships on the GitHub-hosted windows-2022 and windows-11-arm runners that build microsoft/git), the default toolchain targets the MSVC ABI; cargo then writes target/release/gitcore.lib instead, which the MinGW ld.exe cannot consume:
LINK git-shell.exe
D:\git-sdk-64-minimal\mingw64\bin/ld.exe: cannot find target/release/libgitcore.a: No such file or directory collect2.exe: error: ld returned 1 exit status
See https://github.com/microsoft/git/actions/runs/27341625000 for the full log.
Let's define the correct target. Re-use (and fix) the existing HOST_CPU variable for that purpose. Avoid relying on environment variables that are simply not defined in Git for Windows' minimal SDK that Git uses in its CI runs.
--- Makefile | 3 ++- config.mak.uname | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-)
Makefile +2 -1
@@ -959,7 +959,7 @@ RUST_LIB_NAME = gitcore.lib else RUST_LIB_NAME = libgitcore.a endif -RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) +RUST_LIB = target$(if $(CARGO_TARGET),/$(CARGO_TARGET))/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) endif GITLIBS = common-main.o $(LIB_FILE)
@@ -993,6 +993,7 @@ endif ifndef DEBUG CARGO_ARGS += --release endif +CARGO_ARGS += $(if $(CARGO_TARGET),--target $(CARGO_TARGET)) # For the 'sparse' target SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__
config.mak.uname +23 -1
@@ -758,7 +758,29 @@ ifeq ($(uname_S),MINGW) MINGW_PREFIX := /$(shell echo '$(MSYSTEM)' | tr A-Z a-z) endif prefix = $(MINGW_PREFIX) - HOST_CPU = $(patsubst %-w64-mingw32,%,$(MINGW_CHOST)) + + # A rustup-managed Rust on Windows defaults to the MSVC ABI and + # produces a `gitcore.lib` that the MinGW `ld.exe` cannot link. + # Pick a GCC-compatible Rust target triple matching the MSYS2 + # subsystem instead: `*-pc-windows-gnullvm` for the Clang/LLVM + # subsystems (which on Windows is also the only choice for + # ARM64, where no MinGW-GCC port exists) and `*-pc-windows-gnu` + # for the MSVCRT-based MinGW subsystems. For a `staticlib` + # crate-type Cargo does not invoke an external linker, so + # `rustup target add <triple>` is sufficient. + ifneq (,$(filter %ARM64, $(MSYSTEM))) + HOST_CPU = aarch64 + else ifneq (,$(filter %32, $(MSYSTEM))) + HOST_CPU = i686 + else + HOST_CPU = x86_64 + endif + ifneq (,$(filter CLANG%, $(MSYSTEM))) + CARGO_TARGET = $(HOST_CPU)-pc-windows-gnullvm + else + CARGO_TARGET = $(HOST_CPU)-pc-windows-gnu + endif + BASIC_LDFLAGS += -Wl,--pic-executable COMPAT_CFLAGS += -DDETECT_MSYS_TTY \ -DENSURE_MSYSTEM_IS_SET="\"$(MSYSTEM)\"" \
Signature · 1 line
gitgitgadget
PATCH v2 2/2 ci(windows): build with Rust
In reply to Johannes Schindelin via GitGitGadgetFrom: Johannes Schindelin <[email protected]>
The Windows runners used by Git's GitHub workflow's windows-build job ship rustup plus a *-pc-windows-msvc default toolchain (see
https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md
and
https://github.com/actions/partner-runner-images/blob/main/images/arm-windows-11-image.md),
but no precompiled std for *-pc-windows-gnu or *-pc-windows-gnullvm. With the Makefile now picking a GCC-compatible target triple based on $(MSYSTEM), the build step needs that precompiled std to be installed before invoking make, otherwise cargo build --target <triple> fails to find a usable std for the chosen target.
Add a step between the SDK setup and the make invocation that selects the matching triple from $MSYSTEM (which git-for-windows/setup-git-for-windows-sdk exports for every subsequent step) and runs rustup target add for it. The mapping mirrors what config.mak.uname derives from $(MSYSTEM) and $(HOST_CPU), just enumerated explicitly here since CI has direct knowledge of which MSYS2 subsystems the matrix actually exercises (CLANGARM64 for the ARM64 runner, MINGW64 for the x86_64 runner). Technically, we only need to handle MINGW64 at present, but the switch to UCRT64 is imminent, and the other case arms serve as a very fine documentation of what people should do for other MSYSTEM values.
For a staticlib crate-type cargo build does not invoke an external linker, so no further toolchain components (e.g. the gnullvm LLVM linker) need to be installed; rustup target add alone is sufficient.
--- .github/workflows/main.yml | 24 ++++++++++++++++++++++++ ci/lib.sh | 3 --- 2 files changed, 24 insertions(+), 3 deletions(-)
.github/workflows/main.yml +24 -0
@@ -114,6 +114,30 @@ jobs: steps: - uses: actions/checkout@v6 - uses: git-for-windows/setup-git-for-windows-sdk@v2 + - name: Install GCC-compatible Rust target + shell: bash + run: | + # The hosted Windows runners ship a rustup-managed Rust whose + # default toolchain targets the MSVC ABI. That produces a + # `gitcore.lib` which the MinGW GCC used by the rest of the + # build cannot link. Install the precompiled `std` for a + # GCC-compatible target triple matching the MSYS2 subsystem; + # the Makefile selects the same triple via $(MSYSTEM) and + # passes it to `cargo build --target`. + case "$MSYSTEM" in + CLANGARM64) target=aarch64-pc-windows-gnullvm ;; + CLANG64) target=x86_64-pc-windows-gnullvm ;; + CLANG32) target=i686-pc-windows-gnullvm ;; + UCRT64) target=x86_64-pc-windows-gnu ;; + MINGW64) target=x86_64-pc-windows-gnu ;; + MINGW32) target=i686-pc-windows-gnu ;; + *) echo "::error::Unsupported MSYSTEM: $MSYSTEM"; exit 1 ;; + esac && + rustup target add "$target" && + + # Ensure that cargo.exe is found even with the minimal SDK's restricted PATH + CARGO="$(type -p cargo.exe)" && + echo "export PATH=\$PATH:${CARGO%/cargo.exe}" >>/etc/profile - name: build shell: bash env:
ci/lib.sh +0 -3
@@ -391,9 +391,6 @@ linux-asan-ubsan) osx-meson) MESONFLAGS="$MESONFLAGS -Dcredential_helpers=osxkeychain" ;; -windows-*) - export NO_RUST=UnfortunatelyYes - ;; esac MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}"
Signature · 1 line
gitgitgadget
Re: [PATCH v2 1/2] rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
In reply to Johannes Schindelin via GitGitGadget"Johannes Schindelin via GitGitGadget" <[email protected]>
Review endif · line 996
Quoted 5 lines · writes:
(quoted diff) +1
-0@@ -993,6 +993,7 @@ endif ifndef DEBUG CARGO_ARGS += --release endif +CARGO_ARGS += $(if $(CARGO_TARGET),--target $(CARGO_TARGET))
Should this use CARGO_BUILD_TARGET (instead of CARGO_TARGET) to match what the officially supported Cargo environment variable is called? It would also help us work better with the changes from the jc/rust-cargo-build-target topic.
Thanks.
Author: James Le Cuirot <[email protected]> Date: Thu Sep 10 11:20:14 2026 +0100
rust: respect CARGO_BUILD_TARGET when locating build output
When cross-compiling, Cargo always writes to a target-tuple subdirectory determined by CARGO_BUILD_TARGET, even when it matches the native tuple. The build looked in $BUILD_DIR/$BUILD_TYPE directly, so it failed to locate the freshly built library.
Respect CARGO_BUILD_TARGET in the output path so the correct artifact is located.
Makefile +1 -1
@@ -959,7 +959,7 @@ RUST_LIB_NAME = gitcore.lib else RUST_LIB_NAME = libgitcore.a endif -RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) +RUST_LIB = target/$(if $(CARGO_BUILD_TARGET),$(CARGO_BUILD_TARGET)/)$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) endif GITLIBS = common-main.o $(LIB_FILE)
src/cargo-meson.sh +2 -2
@@ -38,7 +38,7 @@ then exit $RET fi -if ! cmp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 +if ! cmp "$BUILD_DIR/${CARGO_BUILD_TARGET:+$CARGO_BUILD_TARGET/}$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 then - cp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" + cp "$BUILD_DIR/${CARGO_BUILD_TARGET:+$CARGO_BUILD_TARGET/}$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" fi
Re: [PATCH v2 1/2] rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
Quoted 14 lines · Junio C Hamano
"Johannes Schindelin via GitGitGadget" <[email protected]>
Review endif · line 996
Quoted 5 lines · writes:
(quoted diff) +1
-0@@ -993,6 +993,7 @@ endif ifndef DEBUG CARGO_ARGS += --release endif +CARGO_ARGS += $(if $(CARGO_TARGET),--target $(CARGO_TARGET))Should this use
CARGO_BUILD_TARGET(instead ofCARGO_TARGET) to match what the officially supported Cargo environment variable is called? It would also help us work better with the changes from the jc/rust-cargo-build-target topic.
Quoted 1 line
Thanks.
Yes, without explicitly setting --target at all. This is how Gentoo Linux supports cross-compiling of its Rust packages. Just avoid setting CARGO_BUILD_TARGET (or passing --target) when you're not cross-compiling. It will cause Cargo to behave differently, even if you give the native tuple. For example, RUSTFLAGS is normally applied to both the build host binaries and the target host binaries, but when an explicit target is set, RUSTFLAGS is only applied to the target host binaries.
Regards,
Chewi
Quoted 43 lines
Author: James Le Cuirot <[email protected]> Date: Thu Sep 10 11:20:14 2026 +0100rust: respect
CARGO_BUILD_TARGETwhen locating build outputWhen cross-compiling, Cargo always writes to a target-tuple subdirectory determined by
CARGO_BUILD_TARGET, even when it matches the native tuple. The build looked in $BUILD_DIR/$BUILD_TYPE directly, so it failed to locate the freshly built library.Respect
CARGO_BUILD_TARGETin the output path so the correct artifact is located.Signed-off-by James Le Cuirot <[email protected]>Signed-off-by Junio C Hamano <[email protected]>Makefile +1
-1@@ -959,7 +959,7 @@ RUST_LIB_NAME = gitcore.lib else RUST_LIB_NAME = libgitcore.a endif -RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) +RUST_LIB = target/$(if $(CARGO_BUILD_TARGET),$(CARGO_BUILD_TARGET)/)$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) endif GITLIBS = common-main.o $(LIB_FILE)src/cargo-meson.sh +2
-2@@ -38,7 +38,7 @@ then exit $RET fi -if ! cmp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 +if ! cmp "$BUILD_DIR/${CARGO_BUILD_TARGET:+$CARGO_BUILD_TARGET/}$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 then - cp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" + cp "$BUILD_DIR/${CARGO_BUILD_TARGET:+$CARGO_BUILD_TARGET/}$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" fi
Re: [PATCH v2 1/2] rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
Hi Junio & James,
Quoted 4 lines · James Le Cuirot
Quoted 3 lines · Junio C Hamano
"Johannes Schindelin via GitGitGadget" <[email protected]> writes:
Quoted 10 lines
Quoted 10 lines
Review endif · line 996
Quoted 5 lines
(quoted diff) +1
-0@@ -993,6 +993,7 @@ endif ifndef DEBUG CARGO_ARGS += --release endif +CARGO_ARGS += $(if $(CARGO_TARGET),--target $(CARGO_TARGET))Should this use
CARGO_BUILD_TARGET(instead ofCARGO_TARGET) to match what the officially supported Cargo environment variable is called? It would also help us work better with the changes from the jc/rust-cargo-build-target topic.
Sure.
Quoted 4 lines
Quoted 2 lines
Thanks.
Yes, without explicitly setting --target at all.
Cool! My first experiment failed because I missed that Makefile does not automatically export CARGO_BUILD_TARGET... 🤦 But now that I explicitly export it, it works as you claimed it would.
Thank you!
Johannes
Quoted 55 lines
This is how Gentoo Linux supports cross-compiling of its Rust packages. Just avoid setting
CARGO_BUILD_TARGET(or passing --target) when you're not cross-compiling. It will cause Cargo to behave differently, even if you give the native tuple. For example, RUSTFLAGS is normally applied to both the build host binaries and the target host binaries, but when an explicit target is set, RUSTFLAGS is only applied to the target host binaries.Regards,
ChewiQuoted 43 lines
Author: James Le Cuirot <[email protected]> Date: Thu Sep 10 11:20:14 2026 +0100rust: respect
CARGO_BUILD_TARGETwhen locating build outputWhen cross-compiling, Cargo always writes to a target-tuple subdirectory determined by
CARGO_BUILD_TARGET, even when it matches the native tuple. The build looked in $BUILD_DIR/$BUILD_TYPE directly, so it failed to locate the freshly built library.Respect
CARGO_BUILD_TARGETin the output path so the correct artifact is located.Signed-off-by James Le Cuirot <[email protected]>Signed-off-by Junio C Hamano <[email protected]>Makefile +1
-1@@ -959,7 +959,7 @@ RUST_LIB_NAME = gitcore.lib else RUST_LIB_NAME = libgitcore.a endif -RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) +RUST_LIB = target/$(if $(CARGO_BUILD_TARGET),$(CARGO_BUILD_TARGET)/)$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) endif GITLIBS = common-main.o $(LIB_FILE)src/cargo-meson.sh +2
-2@@ -38,7 +38,7 @@ then exit $RET fi -if ! cmp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 +if ! cmp "$BUILD_DIR/${CARGO_BUILD_TARGET:+$CARGO_BUILD_TARGET/}$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 then - cp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" + cp "$BUILD_DIR/${CARGO_BUILD_TARGET:+$CARGO_BUILD_TARGET/}$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" fi
v3 cover Use Rust in the Windows CI jobs
In reply to Johannes Schindelin via GitGitGadgetWith v2.55.0, Git requires Rust by default, with an opt-out that is intended to be dropped in one of the next versions.
Due to the special circumstances in the Windows part of the CI builds, each Windows build job first downloads a "minimal Git for Windows SDK" that contains the GCC toolchain required to build and test Git. As a consequence, brian m. carlson opted out of Rust in Git's CI definition in 32d5b905909e (Enable Rust by default, 2026-04-09).
So: How could we stop opting out? Notably, Rust is not part of that minimal Git for Windows SDK, and including it would more than double that payload, which I consider prohibitive. Yet including Rust in the minimal Git for Windows SDK is not actually necessary, at least not for the GitHub workflow:
The runners on which this workflow is defined to run come with Rust pre-installed.
Granted, this Rust installation is configured to target the Windows-native C compiler, Visual C. To accommodate for the Windows CI job building with GCC, this patch series adds a step to the workflow that ensures that the needed Rust bits are installed and configured.
RFH: I haven't been able to confirm that GitLab's Windows runners come with Rust preinstalled,
https://docs.gitlab.com/ci/runners/hosted_runners/windows/#available-runtimes
did not clarify that for me. Patrick (or anyone else with access to GitLab CI), could you see whether this patch series builds on saas-windows-medium-amd64 without need for further changes?
Changes since v1:
* The inconsistency pointed out by Junio, that UCRT64 was once marked as using clang and once as using gcc was fixed by clarifying that UCRT64 uses GCC.
Johannes Schindelin (2):
rust: pick a GCC-compatible Cargo target under MSYS2/MinGW ci(windows): build with Rust
.github/workflows/main.yml | 24 ++++++++++++++++++++++++ Makefile | 2 +- ci/lib.sh | 3 --- config.mak.uname | 25 ++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 5 deletions(-)
base-commit: f4742f3165d096130c39a71feb26374da37620f2
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2213%2Fdscho%2Fuse-rust-in-windows-ci-builds-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2213/dscho/use-rust-in-windows-ci-builds-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/2213
Range-diff vs v2:
1: 6567eceb32 ! 1: b70b001f62 rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
@@ Commit message
When Git is built under MSYS2/MinGW with Rust support enabled, the Makefile expects cargo build to drop a target/release/libgitcore.a
- that is linkable by the same MinGW GCC used for every other object.
- With Rust installed via rustup (the way it ships on the
- GitHub-hosted windows-2022 and windows-11-arm runners that build
- microsoft/git), the default toolchain targets the MSVC ABI; cargo
- then writes target/release/gitcore.lib instead, which the MinGW
- ld.exe cannot consume:
+ that is linkable by the same MinGW GCC used for every other object. With
+ Rust installed via rustup (the way it ships on the GitHub-hosted
+ windows-2022 and windows-11-arm runners that build git/git and its
+ forks), the default toolchain targets the MSVC ABI; cargo then writes
+ target/release/gitcore.lib instead, which the MinGW ld.exe cannot
+ consume:
LINK git-shell.exe
D:\git-sdk-64-minimal\mingw64\bin/ld.exe: cannot find target/release/libgitcore.a: No such file or directory collect2.exe: error: ld returned 1 exit status
- See https://github.com/microsoft/git/actions/runs/27341625000 for the
- full log.
+ See https://github.com/microsoft/git/actions/runs/27341625000 for a
+ full example log.
- Let's define the correct target. Re-use (and fix) the existing
- HOST_CPU variable for that purpose. Avoid relying on environment
- variables that are simply not defined in Git for Windows' minimal SDK
- that Git uses in its CI runs.
+ Let's define the correct target, using the CARGO_BUILD_TARGET variable
+ that will be picked up by Rust, see
+ https://dirname.github.io/rust-std-doc/cargo/reference/environment-variables.html#:~:text=CARGO%5FBUILD%5FTARGET
+
+ Re-use (and fix) the existing HOST_CPU variable to determine the
+ correct value. Avoid relying on environment variables that are simply
+ not defined in Git for Windows' minimal SDK that Git uses in its CI
+ runs.
+
+ Note that this _still_ requires an explicit --target option to be
+ picked up in the way Git's build process calls cargo.
@@ Makefile: RUST_LIB_NAME = gitcore.lib
RUST_LIB_NAME = libgitcore.a
endif
-RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)
-+RUST_LIB = target$(if $(CARGO_TARGET),/$(CARGO_TARGET))/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) ++RUST_LIB = target$(if $(CARGO_BUILD_TARGET),/$(CARGO_BUILD_TARGET))/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)
endif
GITLIBS = common-main.o $(LIB_FILE)
-@@ Makefile: endif
- ifndef DEBUG
- CARGO_ARGS += --release
- endif
-+CARGO_ARGS += $(if $(CARGO_TARGET),--target $(CARGO_TARGET)) -
- # For the 'sparse' target
- SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__
## config.mak.uname ##
@@ config.mak.uname: ifeq ($(uname_S),MINGW)
@@ config.mak.uname: ifeq ($(uname_S),MINGW)
+ HOST_CPU = x86_64
+ endif
+ ifneq (,$(filter CLANG%, $(MSYSTEM)))
-+ CARGO_TARGET = $(HOST_CPU)-pc-windows-gnullvm
++ CARGO_BUILD_TARGET = $(HOST_CPU)-pc-windows-gnullvm
+ else
-+ CARGO_TARGET = $(HOST_CPU)-pc-windows-gnu
++ CARGO_BUILD_TARGET = $(HOST_CPU)-pc-windows-gnu
+ endif
++ export CARGO_BUILD_TARGET
+
BASIC_LDFLAGS += -Wl,--pic-executable COMPAT_CFLAGS += -DDETECT_MSYS_TTY \
2: 07415393e5 = 2: 76469029ff ci(windows): build with Rust
Signature · 1 line
gitgitgadget
PATCH v3 1/2 rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
From: Johannes Schindelin <[email protected]>
When Git is built under MSYS2/MinGW with Rust support enabled, the Makefile expects cargo build to drop a target/release/libgitcore.a that is linkable by the same MinGW GCC used for every other object. With Rust installed via rustup (the way it ships on the GitHub-hosted windows-2022 and windows-11-arm runners that build git/git and its forks), the default toolchain targets the MSVC ABI; cargo then writes target/release/gitcore.lib instead, which the MinGW ld.exe cannot consume:
LINK git-shell.exe
D:\git-sdk-64-minimal\mingw64\bin/ld.exe: cannot find target/release/libgitcore.a: No such file or directory collect2.exe: error: ld returned 1 exit status
See https://github.com/microsoft/git/actions/runs/27341625000 for a full example log.
Let's define the correct target, using the CARGO_BUILD_TARGET variable that will be picked up by Rust, see
https://dirname.github.io/rust-std-doc/cargo/reference/environment-variables.html#:~:text=CARGO%5FBUILD%5FTARGET
Re-use (and fix) the existing HOST_CPU variable to determine the correct value. Avoid relying on environment variables that are simply not defined in Git for Windows' minimal SDK that Git uses in its CI runs.
Note that this _still_ requires an explicit --target option to be picked up in the way Git's build process calls cargo.
--- Makefile | 2 +- config.mak.uname | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-)
Makefile +1 -1
@@ -959,7 +959,7 @@ RUST_LIB_NAME = gitcore.lib else RUST_LIB_NAME = libgitcore.a endif -RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) +RUST_LIB = target$(if $(CARGO_BUILD_TARGET),/$(CARGO_BUILD_TARGET))/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) endif GITLIBS = common-main.o $(LIB_FILE)
config.mak.uname +24 -1
@@ -758,7 +758,30 @@ ifeq ($(uname_S),MINGW) MINGW_PREFIX := /$(shell echo '$(MSYSTEM)' | tr A-Z a-z) endif prefix = $(MINGW_PREFIX) - HOST_CPU = $(patsubst %-w64-mingw32,%,$(MINGW_CHOST)) + + # A rustup-managed Rust on Windows defaults to the MSVC ABI and + # produces a `gitcore.lib` that the MinGW `ld.exe` cannot link. + # Pick a GCC-compatible Rust target triple matching the MSYS2 + # subsystem instead: `*-pc-windows-gnullvm` for the Clang/LLVM + # subsystems (which on Windows is also the only choice for + # ARM64, where no MinGW-GCC port exists) and `*-pc-windows-gnu` + # for the MSVCRT-based MinGW subsystems. For a `staticlib` + # crate-type Cargo does not invoke an external linker, so + # `rustup target add <triple>` is sufficient. + ifneq (,$(filter %ARM64, $(MSYSTEM))) + HOST_CPU = aarch64 + else ifneq (,$(filter %32, $(MSYSTEM))) + HOST_CPU = i686 + else + HOST_CPU = x86_64 + endif + ifneq (,$(filter CLANG%, $(MSYSTEM))) + CARGO_BUILD_TARGET = $(HOST_CPU)-pc-windows-gnullvm + else + CARGO_BUILD_TARGET = $(HOST_CPU)-pc-windows-gnu + endif + export CARGO_BUILD_TARGET + BASIC_LDFLAGS += -Wl,--pic-executable COMPAT_CFLAGS += -DDETECT_MSYS_TTY \ -DENSURE_MSYSTEM_IS_SET="\"$(MSYSTEM)\"" \
Signature · 1 line
gitgitgadget
PATCH v3 2/2 ci(windows): build with Rust
In reply to Johannes Schindelin via GitGitGadgetFrom: Johannes Schindelin <[email protected]>
The Windows runners used by Git's GitHub workflow's windows-build job ship rustup plus a *-pc-windows-msvc default toolchain (see
https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md
and
https://github.com/actions/partner-runner-images/blob/main/images/arm-windows-11-image.md),
but no precompiled std for *-pc-windows-gnu or *-pc-windows-gnullvm. With the Makefile now picking a GCC-compatible target triple based on $(MSYSTEM), the build step needs that precompiled std to be installed before invoking make, otherwise cargo build --target <triple> fails to find a usable std for the chosen target.
Add a step between the SDK setup and the make invocation that selects the matching triple from $MSYSTEM (which git-for-windows/setup-git-for-windows-sdk exports for every subsequent step) and runs rustup target add for it. The mapping mirrors what config.mak.uname derives from $(MSYSTEM) and $(HOST_CPU), just enumerated explicitly here since CI has direct knowledge of which MSYS2 subsystems the matrix actually exercises (CLANGARM64 for the ARM64 runner, MINGW64 for the x86_64 runner). Technically, we only need to handle MINGW64 at present, but the switch to UCRT64 is imminent, and the other case arms serve as a very fine documentation of what people should do for other MSYSTEM values.
For a staticlib crate-type cargo build does not invoke an external linker, so no further toolchain components (e.g. the gnullvm LLVM linker) need to be installed; rustup target add alone is sufficient.
--- .github/workflows/main.yml | 24 ++++++++++++++++++++++++ ci/lib.sh | 3 --- 2 files changed, 24 insertions(+), 3 deletions(-)
.github/workflows/main.yml +24 -0
@@ -114,6 +114,30 @@ jobs: steps: - uses: actions/checkout@v6 - uses: git-for-windows/setup-git-for-windows-sdk@v2 + - name: Install GCC-compatible Rust target + shell: bash + run: | + # The hosted Windows runners ship a rustup-managed Rust whose + # default toolchain targets the MSVC ABI. That produces a + # `gitcore.lib` which the MinGW GCC used by the rest of the + # build cannot link. Install the precompiled `std` for a + # GCC-compatible target triple matching the MSYS2 subsystem; + # the Makefile selects the same triple via $(MSYSTEM) and + # passes it to `cargo build --target`. + case "$MSYSTEM" in + CLANGARM64) target=aarch64-pc-windows-gnullvm ;; + CLANG64) target=x86_64-pc-windows-gnullvm ;; + CLANG32) target=i686-pc-windows-gnullvm ;; + UCRT64) target=x86_64-pc-windows-gnu ;; + MINGW64) target=x86_64-pc-windows-gnu ;; + MINGW32) target=i686-pc-windows-gnu ;; + *) echo "::error::Unsupported MSYSTEM: $MSYSTEM"; exit 1 ;; + esac && + rustup target add "$target" && + + # Ensure that cargo.exe is found even with the minimal SDK's restricted PATH + CARGO="$(type -p cargo.exe)" && + echo "export PATH=\$PATH:${CARGO%/cargo.exe}" >>/etc/profile - name: build shell: bash env:
ci/lib.sh +0 -3
@@ -391,9 +391,6 @@ linux-asan-ubsan) osx-meson) MESONFLAGS="$MESONFLAGS -Dcredential_helpers=osxkeychain" ;; -windows-*) - export NO_RUST=UnfortunatelyYes - ;; esac MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}"
Signature · 1 line
gitgitgadget
v4 cover Use Rust in the Windows CI jobs
In reply to Johannes Schindelin via GitGitGadgetWith v2.55.0, Git requires Rust by default, with an opt-out that is intended to be dropped in one of the next versions.
Due to the special circumstances in the Windows part of the CI builds, each Windows build job first downloads a "minimal Git for Windows SDK" that contains the GCC toolchain required to build and test Git. As a consequence, brian m. carlson opted out of Rust in Git's CI definition in 32d5b905909e (Enable Rust by default, 2026-04-09).
So: How could we stop opting out? Notably, Rust is not part of that minimal Git for Windows SDK, and including it would more than double that payload, which I consider prohibitive. Yet including Rust in the minimal Git for Windows SDK is not actually necessary, at least not for the GitHub workflow:
The runners on which this workflow is defined to run come with Rust pre-installed.
Granted, this Rust installation is configured to target the Windows-native C compiler, Visual C. To accommodate for the Windows CI job building with GCC, this patch series adds a step to the workflow that ensures that the needed Rust bits are installed and configured.
GitLab peeps, I still would love to ask for your help: I haven't been able to confirm that GitLab's Windows runners come with Rust preinstalled,
https://docs.gitlab.com/ci/runners/hosted_runners/windows/#available-runtimes
did not clarify that for me. Patrick (or anyone else with access to GitLab CI), could you see whether this patch series builds on saas-windows-medium-amd64 without need for further changes?
Changes since v3:
* Now including the "Changes since v2"... (I thought I had edited the PR comment, but either I forgot to press the "Update comment" button, or I missed one of the many issues I had today with PR comments, caused by many a 500).
* Removed the now-incorrect paragraph from the commit message that still talks about --target.
* Sending my humblest apologies for such a quick succession (but I really think that v3 is ready for next).
Changes since v2:
* Now using CARGO_BUILD_TARGET; Reworded the commit message accordingly.
* Dropped the now-unnecessary --target option.
Changes since v1:
* The inconsistency pointed out by Junio, that UCRT64 was once marked as using clang and once as using gcc was fixed by clarifying that UCRT64 uses GCC.
Johannes Schindelin (2):
rust: pick a GCC-compatible Cargo target under MSYS2/MinGW ci(windows): build with Rust
.github/workflows/main.yml | 24 ++++++++++++++++++++++++ Makefile | 2 +- ci/lib.sh | 3 --- config.mak.uname | 25 ++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 5 deletions(-)
base-commit: f4742f3165d096130c39a71feb26374da37620f2
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2213%2Fdscho%2Fuse-rust-in-windows-ci-builds-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2213/dscho/use-rust-in-windows-ci-builds-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/2213
Range-diff vs v3:
1: b70b001f62 ! 1: 6e8648b21c rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
@@ Commit message
not defined in Git for Windows' minimal SDK that Git uses in its CI runs.
- Note that this _still_ requires an explicit --target option to be
- picked up in the way Git's build process calls cargo.
-
2: 76469029ff = 2: f6c2f52fb3 ci(windows): build with Rust
Signature · 1 line
gitgitgadget
PATCH v4 1/2 rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
From: Johannes Schindelin <[email protected]>
When Git is built under MSYS2/MinGW with Rust support enabled, the Makefile expects cargo build to drop a target/release/libgitcore.a that is linkable by the same MinGW GCC used for every other object. With Rust installed via rustup (the way it ships on the GitHub-hosted windows-2022 and windows-11-arm runners that build git/git and its forks), the default toolchain targets the MSVC ABI; cargo then writes target/release/gitcore.lib instead, which the MinGW ld.exe cannot consume:
LINK git-shell.exe
D:\git-sdk-64-minimal\mingw64\bin/ld.exe: cannot find target/release/libgitcore.a: No such file or directory collect2.exe: error: ld returned 1 exit status
See https://github.com/microsoft/git/actions/runs/27341625000 for a full example log.
Let's define the correct target, using the CARGO_BUILD_TARGET variable that will be picked up by Rust, see
https://dirname.github.io/rust-std-doc/cargo/reference/environment-variables.html#:~:text=CARGO%5FBUILD%5FTARGET
Re-use (and fix) the existing HOST_CPU variable to determine the correct value. Avoid relying on environment variables that are simply not defined in Git for Windows' minimal SDK that Git uses in its CI runs.
--- Makefile | 2 +- config.mak.uname | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-)
Makefile +1 -1
@@ -959,7 +959,7 @@ RUST_LIB_NAME = gitcore.lib else RUST_LIB_NAME = libgitcore.a endif -RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) +RUST_LIB = target$(if $(CARGO_BUILD_TARGET),/$(CARGO_BUILD_TARGET))/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME) endif GITLIBS = common-main.o $(LIB_FILE)
config.mak.uname +24 -1
@@ -758,7 +758,30 @@ ifeq ($(uname_S),MINGW) MINGW_PREFIX := /$(shell echo '$(MSYSTEM)' | tr A-Z a-z) endif prefix = $(MINGW_PREFIX) - HOST_CPU = $(patsubst %-w64-mingw32,%,$(MINGW_CHOST)) + + # A rustup-managed Rust on Windows defaults to the MSVC ABI and + # produces a `gitcore.lib` that the MinGW `ld.exe` cannot link. + # Pick a GCC-compatible Rust target triple matching the MSYS2 + # subsystem instead: `*-pc-windows-gnullvm` for the Clang/LLVM + # subsystems (which on Windows is also the only choice for + # ARM64, where no MinGW-GCC port exists) and `*-pc-windows-gnu` + # for the MSVCRT-based MinGW subsystems. For a `staticlib` + # crate-type Cargo does not invoke an external linker, so + # `rustup target add <triple>` is sufficient. + ifneq (,$(filter %ARM64, $(MSYSTEM))) + HOST_CPU = aarch64 + else ifneq (,$(filter %32, $(MSYSTEM))) + HOST_CPU = i686 + else + HOST_CPU = x86_64 + endif + ifneq (,$(filter CLANG%, $(MSYSTEM))) + CARGO_BUILD_TARGET = $(HOST_CPU)-pc-windows-gnullvm + else + CARGO_BUILD_TARGET = $(HOST_CPU)-pc-windows-gnu + endif + export CARGO_BUILD_TARGET + BASIC_LDFLAGS += -Wl,--pic-executable COMPAT_CFLAGS += -DDETECT_MSYS_TTY \ -DENSURE_MSYSTEM_IS_SET="\"$(MSYSTEM)\"" \
Signature · 1 line
gitgitgadget
PATCH v4 2/2 ci(windows): build with Rust
In reply to Johannes Schindelin via GitGitGadgetFrom: Johannes Schindelin <[email protected]>
The Windows runners used by Git's GitHub workflow's windows-build job ship rustup plus a *-pc-windows-msvc default toolchain (see
https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md
and
https://github.com/actions/partner-runner-images/blob/main/images/arm-windows-11-image.md),
but no precompiled std for *-pc-windows-gnu or *-pc-windows-gnullvm. With the Makefile now picking a GCC-compatible target triple based on $(MSYSTEM), the build step needs that precompiled std to be installed before invoking make, otherwise cargo build --target <triple> fails to find a usable std for the chosen target.
Add a step between the SDK setup and the make invocation that selects the matching triple from $MSYSTEM (which git-for-windows/setup-git-for-windows-sdk exports for every subsequent step) and runs rustup target add for it. The mapping mirrors what config.mak.uname derives from $(MSYSTEM) and $(HOST_CPU), just enumerated explicitly here since CI has direct knowledge of which MSYS2 subsystems the matrix actually exercises (CLANGARM64 for the ARM64 runner, MINGW64 for the x86_64 runner). Technically, we only need to handle MINGW64 at present, but the switch to UCRT64 is imminent, and the other case arms serve as a very fine documentation of what people should do for other MSYSTEM values.
For a staticlib crate-type cargo build does not invoke an external linker, so no further toolchain components (e.g. the gnullvm LLVM linker) need to be installed; rustup target add alone is sufficient.
--- .github/workflows/main.yml | 24 ++++++++++++++++++++++++ ci/lib.sh | 3 --- 2 files changed, 24 insertions(+), 3 deletions(-)
.github/workflows/main.yml +24 -0
@@ -114,6 +114,30 @@ jobs: steps: - uses: actions/checkout@v6 - uses: git-for-windows/setup-git-for-windows-sdk@v2 + - name: Install GCC-compatible Rust target + shell: bash + run: | + # The hosted Windows runners ship a rustup-managed Rust whose + # default toolchain targets the MSVC ABI. That produces a + # `gitcore.lib` which the MinGW GCC used by the rest of the + # build cannot link. Install the precompiled `std` for a + # GCC-compatible target triple matching the MSYS2 subsystem; + # the Makefile selects the same triple via $(MSYSTEM) and + # passes it to `cargo build --target`. + case "$MSYSTEM" in + CLANGARM64) target=aarch64-pc-windows-gnullvm ;; + CLANG64) target=x86_64-pc-windows-gnullvm ;; + CLANG32) target=i686-pc-windows-gnullvm ;; + UCRT64) target=x86_64-pc-windows-gnu ;; + MINGW64) target=x86_64-pc-windows-gnu ;; + MINGW32) target=i686-pc-windows-gnu ;; + *) echo "::error::Unsupported MSYSTEM: $MSYSTEM"; exit 1 ;; + esac && + rustup target add "$target" && + + # Ensure that cargo.exe is found even with the minimal SDK's restricted PATH + CARGO="$(type -p cargo.exe)" && + echo "export PATH=\$PATH:${CARGO%/cargo.exe}" >>/etc/profile - name: build shell: bash env:
ci/lib.sh +0 -3
@@ -391,9 +391,6 @@ linux-asan-ubsan) osx-meson) MESONFLAGS="$MESONFLAGS -Dcredential_helpers=osxkeychain" ;; -windows-*) - export NO_RUST=UnfortunatelyYes - ;; esac MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}"
Signature · 1 line
gitgitgadget
"Johannes Schindelin via GitGitGadget" <[email protected]>
Quoted 9 lines · writes:
GitLab peeps, I still would love to ask for your help: I haven't been able to confirm that GitLab's Windows runners come with Rust preinstalled,
https://docs.gitlab.com/ci/runners/hosted_runners/windows/#available-runtimes
did not clarify that for me. Patrick (or anyone else with access to GitLab CI), could you see whether this patch series builds on saas-windows-medium-amd64 without need for further changes?Changes since v3:
Quoted 8 lines
* Now including the "Changes since v2"... (I thought I had edited the PR comment, but either I forgot to press the "Update comment" button, or I missed one of the many issues I had today with PR comments, caused by many a 500).
* Removed the now-incorrect paragraph from the commit message that still talks about --target.
* Sending my humblest apologies for such a quick succession (but I really think that v3 is ready for next).
Yup, and this one also is.
It is our practice to cook new patches that people involved in their development agree to be good stil in 'next' for a week just in case, but as I assume that Windows have unusually higher ratio of binary users relative to those who build from the source, it would not benefit as much as other platforms from such a practice, so let's merge it in 'next' and fast track down to 'master' immediately.
"Johannes Schindelin via GitGitGadget" <[email protected]>
Quoted 6 lines · writes:
GitLab peeps, I still would love to ask for your help: I haven't been able to confirm that GitLab's Windows runners come with Rust preinstalled,
https://docs.gitlab.com/ci/runners/hosted_runners/windows/#available-runtimes
did not clarify that for me. Patrick (or anyone else with access to GitLab CI), could you see whether this patch series builds on saas-windows-medium-amd64 without need for further changes?
I rarely look at failures in individual tasks there, but noticed that a recent run:
https://gitlab.com/git-scm/git/-/jobs/16576450182#L784
failed with "cargo: command not found".
Hi Junio (and lurkers),
Quoted 10 lines · Junio C Hamano
"Johannes Schindelin via GitGitGadget" <[email protected]>
Quoted 6 lines · writes:
GitLab peeps, I still would love to ask for your help: I haven't been able to confirm that GitLab's Windows runners come with Rust preinstalled,
https://docs.gitlab.com/ci/runners/hosted_runners/windows/#available-runtimes
did not clarify that for me. Patrick (or anyone else with access to GitLab CI), could you see whether this patch series builds on saas-windows-medium-amd64 without need for further changes?
Quoted 6 lines
I rarely look at failures in individual tasks there, but noticed that a recent run:
https://gitlab.com/git-scm/git/-/jobs/16576450182#L784
failed with "cargo: command not found".
To close the loop: I am trying to address this in this thread:
https://lore.kernel.org/git/[email protected]
Ciao,
Johannes
Quoted 17 lines · Johannes Schindelin
Hi Junio (and lurkers),
Quoted 13 lines · Junio C Hamano
"Johannes Schindelin via GitGitGadget" <[email protected]>
Quoted 6 lines · writes:
GitLab peeps, I still would love to ask for your help: I haven't been able to confirm that GitLab's Windows runners come with Rust preinstalled,
https://docs.gitlab.com/ci/runners/hosted_runners/windows/#available-runtimes
did not clarify that for me. Patrick (or anyone else with access to GitLab CI), could you see whether this patch series builds on saas-windows-medium-amd64 without need for further changes?I rarely look at failures in individual tasks there, but noticed that a recent run:
Quoted 7 lines
Quoted 3 lines
https://gitlab.com/git-scm/git/-/jobs/16576450182#L784
failed with "cargo: command not found".
To close the loop: I am trying to address this in this thread:
Yup. I saw Karthik's response as well and consider the issue is now in good hands ;-).
Thanks.