Skip to content

Commit 95277c3

Browse files
committed
Build gettext/libsodium universal binary properly in CI
When Apple Silicon came out, we needed to get universal binaries of gettext/libsodium to link against, and solved it in a somewhat hacky temporary solution by just downloading the bottles from Homebrew and patching them with the x86_64 version. However, Homebrew only maintains bottles for 3 recent OSes, and with macOS 14's release, they no longer have bottles for macOS 11, which we still want to support as it's a recent OS. As such, we need to build the arm64 version of the packages in CI as well instead of just downloading. When installing from source, Homebrew uses a custom "clang" script that injects compiler flags including "-march" which will cause clang to fail to work when building universal binaries (since it doesn't make sense to specify Intel architectures when specifying `-arch arm64`). Just force it to use system clang instead to avoid inject unwanted flags.
1 parent 76cc4e2 commit 95277c3

File tree

2 files changed

+28
-43
lines changed

2 files changed

+28
-43
lines changed
Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
name: Universal package
22
description: Create universal Homebrew package which contains x86_64 and arm64
3+
4+
# Instead of using the default binary installed by Homebrew, we need to build our own because third-party libraries are
5+
# statically linked in MacVim, and need to be built against MACOSX_DEPLOYMENT_TARGET to ensure the built binary will
6+
# work on supported macOS versions. Another reason for building our own custom package is to build a unviersal binary
7+
# that has both x86_64 and arm64 arch, as Homebrew's distributed bottles are thin binaries with only one arch.
8+
#
9+
# We still use Homebrew to manage the library because their formulas are up to date and have correct build instructions
10+
# that will work. This way we don't have to manually configuring and building and updating the package info.
11+
312
inputs:
413
formula:
514
description: Formura name
@@ -18,9 +27,18 @@ runs:
1827
set -o pipefail
1928
formula=${{ inputs.formula }}
2029
21-
# Patch the official Homebrew formula to explicitly build for min deployment target
30+
# Need to make sure we get the latest before patching. Otherwise Homebrew may later try to get the latest
31+
# version and stomp what we have here.
32+
brew update
33+
34+
# Patch the official Homebrew formula to explicitly build for min deployment target and a universal binary. We
35+
# also need to explicitly use system Clang because Homebrew's bundled clang script tries to inject -march
36+
# compiler flags that will cause universal builds to fail as Clang does not like that.
2237
brew cat ${formula} | \
23-
sed '/^[[:blank:]]*def install$/a\'$'\n ENV["MACOSX_DEPLOYMENT_TARGET"] = "'${MACOSX_DEPLOYMENT_TARGET}$'"\n' >${formula}.rb
38+
sed '/^[[:blank:]]*def install$/a\'$'\n ENV["MACOSX_DEPLOYMENT_TARGET"] = "'${MACOSX_DEPLOYMENT_TARGET}$'"\n' | \
39+
sed '/^[[:blank:]]*def install$/a\'$'\n ENV["CC"] = "/usr/bin/clang"\n' | \
40+
sed '/^[[:blank:]]*def install$/a\'$'\n ENV["CFLAGS"] = "-arch x86_64 -arch arm64"\n' | \
41+
sed '/^[[:blank:]]*def install$/a\'$'\n ENV["LDFLAGS"] = "-arch x86_64 -arch arm64"\n' >${formula}.rb
2442
2543
# Uninstall the already installed formula because we want to build our own
2644
brew uninstall --ignore-dependencies ${formula} || true
@@ -36,7 +54,7 @@ runs:
3654
uses: actions/cache@v3
3755
with:
3856
path: /usr/local/Cellar/${{ inputs.formula }}
39-
key: ${{ inputs.formula }}-homebrew-cache-patched-unified-xcode${{ steps.setup-formula.outputs.xcode_version }}-${{ hashFiles(format('{0}.rb', inputs.formula)) }}
57+
key: ${{ inputs.formula }}-homebrew-cache-custom-unified-xcode${{ steps.setup-formula.outputs.xcode_version }}-${{ hashFiles(format('{0}.rb', inputs.formula)) }}
4058

4159
- name: Install formula
4260
shell: bash
@@ -51,38 +69,16 @@ runs:
5169
brew unlink ${formula} && brew link ${formula}
5270
echo '::endgroup::'
5371
54-
- name: Create universal binaries with arm64 bottle
55-
if: steps.cache-keg.outputs.cache-hit != 'true'
56-
shell: bash
57-
run: |
58-
echo '::group::Create universal binaries with arm64 bottle'
59-
set -o verbose
60-
formula=${{ inputs.formula }}
72+
echo '::group::Verify built version'
6173
contents=($(IFS=,; for x in ${{ inputs.contents }}; do echo ${x}; done))
6274
63-
# Manually download and extract a bottle for arm64
64-
source /dev/stdin <<<"$(brew info --json ${formula} | \
65-
jq -r '.[0] | "bottle_url=\(.bottle.stable.files.arm64_big_sur.url)", "formula_ver=\(.versions.stable)", "formula_rev=\(.revision)"')"
66-
if [[ ${formula_rev} -ne 0 ]]; then
67-
formula_ver=${formula_ver}_${formula_rev}
68-
fi
69-
70-
workdir=${formula}_download
71-
mkdir ${workdir}
72-
cd ${workdir}
73-
wget --no-verbose --header 'Authorization: Bearer QQ==' -O ${formula}.tar.gz ${bottle_url}
74-
tar xf ${formula}.tar.gz
75-
7675
for content in "${contents[@]}"; do
77-
# Just for diagnostics, print out the old archs. This should be a thin binary (x86_64)
78-
lipo -info /usr/local/${content}
79-
80-
# Create a universal binary by patching the custom built x86_64 one with the downloaded arm64 one.
81-
# Modify the actual binaries in /usr/local/Cellar instead of the symlinks to allow caching to work.
82-
lipo -create -output /usr/local/Cellar/${formula}/${formula_ver}/${content} \
83-
/usr/local/Cellar/${formula}/${formula_ver}/${content} ./${formula}/${formula_ver}/${content}
84-
85-
# Print out the new archs and verify they are universal with 2 archs.
76+
# Print out the archs and verify they are universal fat binary.
8677
lipo -info /usr/local/${content} | grep 'x86_64 arm64'
78+
79+
# Make sure deployment target is correct. Later macOS versions have a different binary format (just search for
80+
# "minos") but for 10.13 we need to look for LC_VERSION_MIN_MACOSX.
81+
otool -l /usr/local/${content} | grep -A 2 LC_VERSION_MIN_MACOSX | tail -1 | grep "${MACOSX_DEPLOYMENT_TARGET}"
8782
done
83+
8884
echo '::endgroup::'

.github/workflows/ci-macvim.yaml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,6 @@ jobs:
9494
9595
# Set up, install, and cache gettext library for localization.
9696
#
97-
# Instead of using the default binary installed by Homebrew, need to build our own because gettext is statically
98-
# linked in MacVim, and need to be built against MACOSX_DEPLOYMENT_TARGET to ensure the built binary will work on
99-
# supported macOS versions.
100-
#
101-
# In addition, to support building a universal MacVim, we need an arm64 version of gettext as well in order to
102-
# create a universal gettext binary to link against (Homebrew only distributes thin binaries and therefore this
103-
# has to be done manually). To do that, we will just pull the bottle directly from Homebrew and patch it in using
104-
# lipo. We can't use normal brew commands to get the bottle because brew doesn't natively support cross-compiling
105-
# and we are running CI on x86_64 Macs. We also don't need to worry about the min deployment target fix on arm64
106-
# because all Apple Silicon Macs have to run on macOS 11+.
107-
10897
- name: Set up gettext
10998
if: matrix.publish
11099
uses: ./.github/actions/universal-package

0 commit comments

Comments
 (0)