rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
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.
Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/Makefile b/Makefile
index fac3e88..ad1ba26 100644
--- a/Makefile
+++ b/Makefile
@@ -959,7 +959,7 @@
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 0b63be1..f3f3bcc 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -758,7 +758,30 @@
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)\"" \