Skip to content

Commit dc61fa0

Browse files
Create universal builds on macos (#612)
Update config.mak.uname and GitHub workflow to create a DMG and PKG containing universal binaries rather than separate single-platform packages. Also, remove dashed versions of commands from the package to save space.
2 parents d8a31ac + 58e14eb commit dc61fa0

File tree

3 files changed

+85
-48
lines changed

3 files changed

+85
-48
lines changed

.github/macos-installer/Makefile

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,17 @@ TARGET_FLAGS := -mmacosx-version-min=$(OSX_VERSION) -DMACOSX_DEPLOYMENT_TARGET=$
99

1010
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
1111

12-
ifeq ($(uname_M),x86_64)
13-
ARCH := x86_64
14-
ARCH_CODE := x86_64
15-
ARCH_FLAGS_x86_64 := -arch x86_64
16-
CPU_VENDOR := Intel
17-
endif
18-
ifeq ($(uname_M),arm64)
19-
ARCH := arm64
20-
ARCH_CODE := arm64
21-
ARCH_FLAGS_arm64 := -arch arm64
22-
CPU_VENDOR := Apple Silicon
23-
endif
12+
ARCH_UNIV := universal
13+
ARCH_FLAGS := -arch x86_64 -arch arm64
2414

25-
CFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS_${ARCH_CODE})
26-
LDFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS_${ARCH_CODE})
15+
CFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS)
16+
LDFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS)
2717

2818
PREFIX := /usr/local
2919
GIT_PREFIX := $(PREFIX)/git
3020

31-
BUILD_CODE := $(ARCH_CODE)
3221
BUILD_DIR := $(GITHUB_WORKSPACE)/payload
33-
DESTDIR := $(PWD)/stage/git-$(BUILD_CODE)-$(VERSION)
22+
DESTDIR := $(PWD)/stage/git-$(ARCH_UNIV)-$(VERSION)
3423
ARTIFACTDIR := build-artifacts
3524
SUBMAKE := $(MAKE) C_INCLUDE_PATH="$(C_INCLUDE_PATH)" CPLUS_INCLUDE_PATH="$(CPLUS_INCLUDE_PATH)" LD_LIBRARY_PATH="$(LD_LIBRARY_PATH)" TARGET_FLAGS="$(TARGET_FLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" NO_GETTEXT=1 NO_DARWIN_PORTS=1 prefix=$(GIT_PREFIX) GIT_BUILT_FROM_COMMIT="$(GIT_BUILT_FROM_COMMIT)" DESTDIR=$(DESTDIR)
3625
CORES := $(shell bash -c "sysctl hw.ncpu | awk '{print \$$2}'")
@@ -44,7 +33,7 @@ APPLE_KEYCHAIN_PROFILE =
4433

4534
.SECONDARY:
4635

47-
$(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(BUILD_CODE):
36+
$(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(ARCH_UNIV):
4837
rm -f $(BUILD_DIR)/git-$(VERSION)/osx-installed*
4938
mkdir -p $(DESTDIR)$(GIT_PREFIX)
5039
touch $@
@@ -97,22 +86,17 @@ symlinks:
9786
ruby ../scripts/symlink-git-hardlinks.rb $(ARTIFACTDIR)
9887
touch $@
9988

100-
$(BUILD_DIR)/git-$(VERSION)/osx-installed: $(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(BUILD_CODE) $(BUILD_DIR)/git-$(VERSION)/osx-installed-man $(BUILD_DIR)/git-$(VERSION)/osx-installed-assets $(BUILD_DIR)/git-$(VERSION)/osx-installed-subtree
89+
$(BUILD_DIR)/git-$(VERSION)/osx-installed: $(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(ARCH_UNIV) $(BUILD_DIR)/git-$(VERSION)/osx-installed-man $(BUILD_DIR)/git-$(VERSION)/osx-installed-assets $(BUILD_DIR)/git-$(VERSION)/osx-installed-subtree
10190
find $(DESTDIR)$(GIT_PREFIX) -type d -exec chmod ugo+rx {} \;
10291
find $(DESTDIR)$(GIT_PREFIX) -type f -exec chmod ugo+r {} \;
10392
touch $@
10493

105-
$(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_CODE): $(BUILD_DIR)/git-$(VERSION)/osx-built
106-
ifeq ("$(ARCH_CODE)", "universal")
94+
$(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV): $(BUILD_DIR)/git-$(VERSION)/osx-built
10795
File $(BUILD_DIR)/git-$(VERSION)/git
10896
File $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain
109-
else
110-
[ "$$(File $(BUILD_DIR)/git-$(VERSION)/git | cut -f 5 -d' ')" == "$(ARCH_CODE)" ]
111-
[ "$$(File $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain | cut -f 5 -d' ')" == "$(ARCH_CODE)" ]
112-
endif
11397
touch $@
11498

115-
disk-image/VERSION-$(VERSION)-$(ARCH_CODE):
99+
disk-image/VERSION-$(VERSION)-$(ARCH_UNIV):
116100
rm -f disk-image/*.pkg disk-image/VERSION-* disk-image/.DS_Store
117101
mkdir disk-image
118102
touch "$@"
@@ -125,20 +109,23 @@ ifdef APPLE_INSTALLER_IDENTITY
125109
pkg_cmd += --sign "$(APPLE_INSTALLER_IDENTITY)"
126110
endif
127111

128-
pkg_cmd += disk-image/git-$(VERSION)-$(BUILD_CODE).pkg
129-
disk-image/git-$(VERSION)-$(BUILD_CODE).pkg: disk-image/VERSION-$(VERSION)-$(ARCH_CODE) symlinks
112+
pkg_cmd += disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg
113+
disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg: disk-image/VERSION-$(VERSION)-$(ARCH_UNIV) symlinks
130114
$(pkg_cmd)
131115

132-
git-%-$(BUILD_CODE).dmg:
133-
hdiutil create git-$(VERSION)-$(BUILD_CODE).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(VERSION) $(CPU_VENDOR) $(ARCH)" -ov
134-
hdiutil convert -format UDZO -o $@ git-$(VERSION)-$(BUILD_CODE).uncompressed.dmg
135-
rm -f git-$(VERSION)-$(BUILD_CODE).uncompressed.dmg
116+
git-%-$(ARCH_UNIV).dmg:
117+
hdiutil create git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(VERSION) $(ARCH_UNIV)" -ov 2>&1 | tee err || { \
118+
grep "Resource busy" err && \
119+
sleep 5 && \
120+
hdiutil create git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(VERSION) $(ARCH_UNIV)" -ov; }
121+
hdiutil convert -format UDZO -o $@ git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg
122+
rm -f git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg
136123

137-
payload: $(BUILD_DIR)/git-$(VERSION)/osx-installed $(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_CODE)
124+
payload: $(BUILD_DIR)/git-$(VERSION)/osx-installed $(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV)
138125

139-
pkg: disk-image/git-$(VERSION)-$(BUILD_CODE).pkg
126+
pkg: disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg
140127

141-
image: git-$(VERSION)-$(BUILD_CODE).dmg
128+
image: git-$(VERSION)-$(ARCH_UNIV).dmg
142129

143130
ifdef APPLE_APP_IDENTITY
144131
codesign:
@@ -151,6 +138,6 @@ endif
151138
ifdef APPLE_KEYCHAIN_PROFILE
152139
notarize:
153140
@$(CURDIR)/../scripts/notarize.sh \
154-
--package="disk-image/git-$(VERSION)-$(BUILD_CODE).pkg" \
141+
--package="disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg" \
155142
--keychain-profile="$(APPLE_KEYCHAIN_PROFILE)"
156143
endif

.github/workflows/build-git-installers.yml

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,6 @@ jobs:
306306
strategy:
307307
matrix:
308308
arch:
309-
- name: x86_64
310-
runner: macos-latest
311309
- name: arm64
312310
runner: macos-latest-xl-arm64
313311
runs-on: ${{ matrix.arch.runner }}
@@ -323,10 +321,20 @@ jobs:
323321

324322
- name: Install Git dependencies
325323
run: |
326-
set -x
324+
set -ex
325+
326+
# Install x86_64 packages
327+
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
328+
arch -x86_64 /usr/local/bin/brew install gettext curl
329+
330+
# Install arm64 packages
327331
brew install automake asciidoc xmlto docbook
328332
brew link --force gettext
329333
334+
# Make universal gettext and curl library
335+
lipo -create -output libintl.a /usr/local/opt/gettext/lib/libintl.a /opt/homebrew/opt/gettext/lib/libintl.a
336+
lipo -create -output libcurl.dylib /opt/homebrew/opt/curl/lib/libcurl.4.dylib /usr/local/opt/curl/lib/libcurl.4.dylib
337+
330338
- name: Set up signing/notarization infrastructure
331339
env:
332340
A1: ${{ secrets.APPLICATION_CERTIFICATE_BASE64 }}
@@ -383,24 +391,37 @@ jobs:
383391
exit 1
384392
}
385393
386-
# Configure the environment
394+
# Trace execution, stop on error
387395
set -ex
388-
PATH=/usr/local/bin:$PATH
389-
export CURL_LDFLAGS=$(curl-config --libs)
390396
391397
# Write to "version" file to force match with trigger payload version
392398
echo "${{ needs.prereqs.outputs.tag_version }}" >>git/version
393399
400+
# Configure universal build
401+
cat >git/config.mak <<EOF
402+
# Create universal binaries. HOST_CPU is a bit of a lie and only
403+
# used in 'git version --build-options'. We'll fix that in code.
404+
HOST_CPU = universal
405+
BASIC_CFLAGS += -arch arm64 -arch x86_64
406+
EOF
407+
394408
# Configure the Git build to pick up gettext
395409
homebrew_prefix="$(brew --prefix)"
396-
cat >git/config.mak <<EOF
397-
LDFLAGS = -L$homebrew_prefix/lib -L/usr/local/opt/gettext/lib
410+
cat >>git/config.mak <<EOF
398411
CFLAGS = -I$homebrew_prefix/include -I/usr/local/opt/gettext/include
412+
LDFLAGS = -L"$(pwd)"
399413
EOF
400414
401-
# On Apple Silicon, homebrew apparently does not install a `gcc` symlink
402-
test x86_64 = '${{ matrix.arch.name }}' ||
403-
echo 'CC = gcc-13' >>config.mak
415+
# Configure the Git build to pick up the universal `libcurl.dylib`
416+
cat >>git/config.mak <<EOF
417+
CURL_LDFLAGS := -L"$(pwd)" -lcurl
418+
CURL_CONFIG := /usr/bin/true
419+
EOF
420+
421+
# Avoid even building the dashed built-ins; Those should be hard-linked
422+
# copies of the `git` executable but would end up as actual copies instead,
423+
# bloating the size of the `.dmg` indecently.
424+
echo 'SKIP_DASHED_BUILT_INS = YabbaDabbaDoo' >>git/config.mak
404425
405426
# To make use of the catalogs...
406427
export XML_CATALOG_FILES=$homebrew_prefix/etc/xml/catalog
@@ -416,10 +437,11 @@ jobs:
416437
tar -xvf git/git-manpages-$VERSION.tar.gz -C manpages
417438
418439
# Lay out payload
440+
cp git/config.mak payload/git-$VERSION/config.mak
419441
make -C git/.github/macos-installer V=1 payload
420442
421443
# Codesign payload
422-
cp -R stage/git-${{ matrix.arch.name }}-$VERSION/ \
444+
cp -R stage/git-universal-$VERSION/ \
423445
git/.github/macos-installer/build-artifacts
424446
make -C git/.github/macos-installer V=1 codesign \
425447
APPLE_APP_IDENTITY="$A3" || die "Creating signed payload failed"
@@ -584,6 +606,9 @@ jobs:
584606
- os: macos-latest
585607
artifact: macos-artifacts
586608
command: git
609+
- os: macos-latest-xl-arm64
610+
artifact: macos-artifacts
611+
command: git
587612
- os: windows-latest
588613
artifact: win-installer-x86_64
589614
command: $PROGRAMFILES\Git\cmd\git.exe
@@ -616,7 +641,7 @@ jobs:
616641
test arm64 != "$arch" ||
617642
brew uninstall git
618643
619-
pkgpath=$(find ./*$arch*.pkg)
644+
pkgpath=$(find ./*universal*.pkg)
620645
sudo installer -pkg $pkgpath -target /
621646
622647
- name: Validate
@@ -625,6 +650,15 @@ jobs:
625650
"${{ matrix.component.command }}" --version | sed 's/git version //' >actual
626651
echo ${{ needs.prereqs.outputs.tag_version }} >expect
627652
cmp expect actual || exit 1
653+
654+
- name: Validate universal binary CPU architecture
655+
if: contains(matrix.component.os, 'macos')
656+
shell: bash
657+
run: |
658+
set -ex
659+
git version --build-options >actual
660+
cat actual
661+
grep "cpu: $(uname -m)" actual
628662
# End validate installers
629663

630664
create-github-release:

help.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,22 @@ const char *help_unknown_cmd(const char *cmd)
730730
exit(1);
731731
}
732732

733+
#if defined(__APPLE__)
734+
static const char *git_host_cpu(void) {
735+
if (!strcmp(GIT_HOST_CPU, "universal")) {
736+
#if defined(__x86_64__)
737+
return "x86_64";
738+
#elif defined(__aarch64__)
739+
return "arm64";
740+
#endif
741+
}
742+
743+
return GIT_HOST_CPU;
744+
}
745+
#undef GIT_HOST_CPU
746+
#define GIT_HOST_CPU git_host_cpu()
747+
#endif
748+
733749
void get_version_info(struct strbuf *buf, int show_build_options)
734750
{
735751
/*

0 commit comments

Comments
 (0)