[PATCH v3 1/2] rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
From: Johannes Schindelin via GitGitGadget <hidden>
Date: 2026-09-13 10:31:21
Subsystem:
kernel build + files below scripts/ (unless maintained elsewhere), the rest · Maintainers:
Nathan Chancellor, Nicolas Schier, Linus Torvalds
From: Johannes Schindelin <redacted>
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.
Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
---
Makefile | 2 +-
config.mak.uname | 25 ++++++++++++++++++++++++-
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index fac3e8879c..ad1ba26f91 100644
--- a/Makefile
+++ b/Makefile@@ -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)
diff --git a/config.mak.uname b/config.mak.uname
index 0b63be10b7..f3f3bcc4ef 100644
--- a/config.mak.uname
+++ b/config.mak.uname@@ -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)\"" \
--
gitgitgadget