Skip to content

Commit 21dedb9

Browse files
author
Shardul Natu
committed
Makefile: support universal macOS builds via RUST_TARGETS
On macOS, Universal Binaries contain native executable code for multiple architectures (such as Intel x86_64 and Apple Silicon arm64) bundled into a single file. This is standard practice for macOS distribution and CI packaging (such as internal distribution packages or tooling like Burrito/Homebrew), allowing a single build artifact to run natively across all Macs without Rosetta emulation or maintaining separate packages. When building Git C code for multiple architectures on macOS, the Apple toolchain (clang) natively supports universal builds via CFLAGS/LDFLAGS. When "-arch x86_64 -arch arm64" is passed, clang automatically compiles and links universal binaries for all C object files and executables out of the box. Cargo and rustc, however, do not support multiple "-arch" flags or emitting universal binaries in a single invocation. Instead, Cargo requires invoking each target triple independently (e.g., passing "--target x86_64-apple-darwin" and "--target aarch64-apple-darwin"). To bridge this gap when Rust is enabled: 1. Allow specifying space-separated target triples in RUST_TARGETS. 2. Introduce declarative pattern rules (target/%/...) to compile each target-specific library slice via Cargo. 3. On macOS, if multiple targets are specified, use "lipo" (part of the mandatory Xcode Command Line Tools) to combine the resulting static libraries into target/release/libgitcore.a. Once $(RUST_LIB) is compiled into a universal static archive, the standard C linker seamlessly links it with the C object files to produce universal Git executables. Signed-off-by: Shardul Natu <snatu@google.com>
1 parent 0d21513 commit 21dedb9

1 file changed

Lines changed: 35 additions & 4 deletions

File tree

Makefile

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,14 @@ include shared.mak
500500
#
501501
# Building Rust code requires Cargo.
502502
#
503+
# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses
504+
# the default Rust target on the system.
505+
#
506+
# On macOS, this supports specifying multiple targets, separated by a space.
507+
# This will produce a Universal static library using `lipo`.
508+
#
509+
# Example: RUST_TARGETS="aarch64-apple-darwin x86_64-apple-darwin"
510+
#
503511
# == SHA-1 and SHA-256 defines ==
504512
#
505513
# === SHA-1 backend ===
@@ -941,16 +949,17 @@ LIB_FILE = libgit.a
941949

942950
ifndef NO_RUST
943951
ifdef DEBUG
944-
RUST_TARGET_DIR = target/debug
952+
RUST_BUILD_CONFIG = debug
945953
else
946-
RUST_TARGET_DIR = target/release
954+
RUST_BUILD_CONFIG = release
947955
endif
948956

949957
ifeq ($(uname_S),Windows)
950-
RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib
958+
RUST_LIB_NAME = gitcore.lib
951959
else
952-
RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a
960+
RUST_LIB_NAME = libgitcore.a
953961
endif
962+
RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)
954963
endif
955964

956965
GITLIBS = common-main.o $(LIB_FILE)
@@ -3022,8 +3031,30 @@ $(LIB_FILE): $(LIB_OBJS)
30223031
$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
30233032

30243033
ifndef NO_RUST
3034+
ifeq ($(RUST_TARGETS),)
30253035
$(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)
30263036
$(QUIET_CARGO)cargo build $(CARGO_ARGS)
3037+
else
3038+
ifneq ($(words $(RUST_TARGETS)),1)
3039+
ifneq ($(uname_S),Darwin)
3040+
$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))
3041+
endif
3042+
endif
3043+
3044+
RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))
3045+
$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)
3046+
$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*
3047+
3048+
$(RUST_LIB): $(RUST_MEMBER_LIBS)
3049+
$(call mkdir_p_parent_template)
3050+
$(QUIET_GEN)\
3051+
if test $(words $(RUST_TARGETS)) -gt 1; \
3052+
then \
3053+
lipo -create $^ -output $@; \
3054+
else \
3055+
cp $< $@; \
3056+
fi
3057+
endif
30273058

30283059
.PHONY: rust
30293060
rust: $(RUST_LIB)

0 commit comments

Comments
 (0)