From 732daa9015d8a35e6839fbd6b322d3e0aca3f135 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:13:28 +0000 Subject: [PATCH] build: add arm64 cross-compilation for macOS runner - Updated `build-native-mac.yaml` to fetch arm64 Homebrew bottles using anonymous GHCR tokens via Python, extracting headers and libraries to a temp dir. - Extended Azure CLI steps to upload `osx-arm64` libraries. - Modified `build-rocksdb.sh` to compile `x86_64` and `arm64` consecutively when running on Darwin. - Supplied paths to the extracted arm64 dependencies using `EXTRA_CFLAGS`, `EXTRA_CXXFLAGS`, and `EXTRA_LDFLAGS`. Co-authored-by: theolivenbaum <8791811+theolivenbaum@users.noreply.github.com> --- .azure-devops/build-native-mac.yaml | 92 +++++++++++++++++++++++++++++ build-native/build-rocksdb.sh | 41 ++++++++++++- 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/.azure-devops/build-native-mac.yaml b/.azure-devops/build-native-mac.yaml index 988a914..61dec4c 100644 --- a/.azure-devops/build-native-mac.yaml +++ b/.azure-devops/build-native-mac.yaml @@ -28,6 +28,47 @@ steps: inputs: script: 'ls -hR /usr/local/' +- task: Bash@3 + displayName: 'Download arm64 dependencies' + inputs: + targetType: 'inline' + script: | + cat << 'EOF' > test_fetch_bottle.py + import urllib.request + import json + import os + import tarfile + + packages = ["snappy", "zstd", "lz4", "zlib"] + os.makedirs("/tmp/arm64_deps", exist_ok=True) + + for pkg in packages: + url = f"https://formulae.brew.sh/api/formula/{pkg}.json" + req = urllib.request.urlopen(url) + data = json.loads(req.read()) + + bottle_key = next((k for k in data['bottle']['stable']['files'] if 'arm64_' in k), None) + if not bottle_key: + print(f"No arm64 bottle for {pkg}") + continue + + bottle_url = data['bottle']['stable']['files'][bottle_key]['url'] + print(f"Downloading {pkg} from {bottle_url}") + + token_url = f"https://ghcr.io/token?scope=repository:homebrew/core/{pkg}:pull" + token_req = urllib.request.urlopen(token_url) + token = json.loads(token_req.read())['token'] + + req = urllib.request.Request(bottle_url, headers={'Authorization': f'Bearer {token}'}) + tar_path = f"/tmp/arm64_deps/{pkg}.tar.gz" + with urllib.request.urlopen(req) as response, open(tar_path, 'wb') as out_file: + out_file.write(response.read()) + + with tarfile.open(tar_path, "r:gz") as tar: + tar.extractall(path="/tmp/arm64_deps") + EOF + python3 test_fetch_bottle.py + - task: Bash@3 inputs: filePath: '$(Build.SourcesDirectory)/build-native/build-rocksdb.sh' @@ -46,6 +87,28 @@ steps: otool -L librocksdb.dylib # install_name_tool -change /usr/lib/libbz2.1.0.dylib "@loader_path/libbz.dylib" librocksdb.dylib +- task: Bash@3 + displayName: 'Adjust dyld links for arm64' + inputs: + targetType: 'inline' + workingDirectory: '$(Build.SourcesDirectory)/build-native/runtimes/osx-arm64/native/' + script: | + otool -L librocksdb.dylib + + SNAPPY_PATH=$(otool -L librocksdb.dylib | grep libsnappy | awk '{print $1}') + if [ ! -z "$SNAPPY_PATH" ]; then install_name_tool -change "$SNAPPY_PATH" "@loader_path/libsnappy.dylib" librocksdb.dylib; fi + + ZSTD_PATH=$(otool -L librocksdb.dylib | grep libzstd | awk '{print $1}') + if [ ! -z "$ZSTD_PATH" ]; then install_name_tool -change "$ZSTD_PATH" "@loader_path/libzstd.dylib" librocksdb.dylib; fi + + Z_PATH=$(otool -L librocksdb.dylib | grep libz.1 | awk '{print $1}') + if [ ! -z "$Z_PATH" ]; then install_name_tool -change "$Z_PATH" "@loader_path/libz.dylib" librocksdb.dylib; fi + + LZ4_PATH=$(otool -L librocksdb.dylib | grep liblz4 | awk '{print $1}') + if [ ! -z "$LZ4_PATH" ]; then install_name_tool -change "$LZ4_PATH" "@loader_path/liblz4.dylib" librocksdb.dylib; fi + + otool -L librocksdb.dylib + - task: CmdLine@2 displayName: 'list /usr/lib folder after' inputs: @@ -73,6 +136,11 @@ steps: scriptLocation: 'inlineScript' inlineScript: 'az storage blob upload -f $(Build.SourcesDirectory)/build-native/runtimes/osx-x64/native/librocksdb.dylib --account-name curiosityreleases -c rocksdb -n librocksdb-v$(ROCKSDBVERSION).dylib --overwrite true' +- task: AzureCLI@1 + inputs: + azureSubscription: 'Curiosity GmbH Azure' + scriptLocation: 'inlineScript' + inlineScript: 'az storage blob upload -f $(Build.SourcesDirectory)/build-native/runtimes/osx-arm64/native/librocksdb.dylib --account-name curiosityreleases -c rocksdb -n librocksdb-arm64-v$(ROCKSDBVERSION).dylib --overwrite true' - task: AzureCLI@1 inputs: @@ -105,4 +173,28 @@ steps: azureSubscription: 'Curiosity GmbH Azure' scriptLocation: 'inlineScript' inlineScript: 'az storage blob upload -f "$(HOMEBREW_CELLAR)/zstd/1.5.7/lib/libzstd.dylib" --account-name curiosityreleases -c rocksdb -n libzstd-v$(ROCKSDBVERSION).dylib --overwrite true' + +- task: AzureCLI@1 + inputs: + azureSubscription: 'Curiosity GmbH Azure' + scriptLocation: 'inlineScript' + inlineScript: 'az storage blob upload -f `find /tmp/arm64_deps -name "libz.1.dylib" -print -quit` --account-name curiosityreleases -c rocksdb -n libz-arm64-v$(ROCKSDBVERSION).dylib --overwrite true' + +- task: AzureCLI@1 + inputs: + azureSubscription: 'Curiosity GmbH Azure' + scriptLocation: 'inlineScript' + inlineScript: 'az storage blob upload -f `find /tmp/arm64_deps -name "liblz4.dylib" -print -quit` --account-name curiosityreleases -c rocksdb -n liblz4-arm64-v$(ROCKSDBVERSION).dylib --overwrite true' + +- task: AzureCLI@1 + inputs: + azureSubscription: 'Curiosity GmbH Azure' + scriptLocation: 'inlineScript' + inlineScript: 'az storage blob upload -f `find /tmp/arm64_deps -name "libsnappy.dylib" -print -quit` --account-name curiosityreleases -c rocksdb -n libsnappy-arm64-v$(ROCKSDBVERSION).dylib --overwrite true' + +- task: AzureCLI@1 + inputs: + azureSubscription: 'Curiosity GmbH Azure' + scriptLocation: 'inlineScript' + inlineScript: 'az storage blob upload -f `find /tmp/arm64_deps -name "libzstd.dylib" -print -quit` --account-name curiosityreleases -c rocksdb -n libzstd-arm64-v$(ROCKSDBVERSION).dylib --overwrite true' diff --git a/build-native/build-rocksdb.sh b/build-native/build-rocksdb.sh index 47b4a5d..2a8235c 100644 --- a/build-native/build-rocksdb.sh +++ b/build-native/build-rocksdb.sh @@ -219,11 +219,50 @@ else echo "----- Build 64 bit --------------------------------------------------" make clean - CFLAGS="${CFLAGS}" PORTABLE=1 make -j$CONCURRENCY shared_lib || fail "64-bit build failed" + + if [ "$(uname)" == "Darwin" ]; then + ORIGINAL_CFLAGS="${CFLAGS}" + ORIGINAL_LDFLAGS="${LDFLAGS}" + + CFLAGS="${ORIGINAL_CFLAGS} -arch x86_64" + LDFLAGS="${ORIGINAL_LDFLAGS} -arch x86_64" + fi + + CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" PORTABLE=1 make -j$CONCURRENCY shared_lib || fail "64-bit build failed" strip librocksdb${LIBEXT} mkdir -p ../runtimes/${RUNTIME}/native && cp -vL ./librocksdb${LIBEXT} ../runtimes/${RUNTIME}/native/librocksdb${LIBEXT} mkdir -p ../rocksdb-${ROCKSDBVERSION}/${RUNTIME}/native && cp -vL ./librocksdb${LIBEXT} ../rocksdb-${ROCKSDBVERSION}/${RUNTIME}/native/librocksdb${LIBEXT} + if [ "$(uname)" == "Darwin" ]; then + echo "----- Build arm64 --------------------------------------------------" + make clean + + export ZLIB_INCLUDE=$(find /tmp/arm64_deps -type d -name "include" | grep zlib | head -n 1) + export ZLIB_LIB_RELEASE=$(find /tmp/arm64_deps -type f -name "libz.a" | grep zlib | head -n 1) + + export LZ4_INCLUDE=$(find /tmp/arm64_deps -type d -name "include" | grep lz4 | head -n 1) + export LZ4_LIB_RELEASE=$(find /tmp/arm64_deps -type f -name "liblz4.a" | grep lz4 | head -n 1) + + export SNAPPY_INCLUDE=$(find /tmp/arm64_deps -type d -name "include" | grep snappy | head -n 1) + export SNAPPY_LIB_RELEASE=$(find /tmp/arm64_deps -type f -name "libsnappy.a" | grep snappy | head -n 1) + + export ZSTD_INCLUDE=$(find /tmp/arm64_deps -type d -name "include" | grep zstd | head -n 1) + export ZSTD_LIB_RELEASE=$(find /tmp/arm64_deps -type f -name "libzstd.a" | grep zstd | head -n 1) + + RUNTIME=osx-arm64 + export EXTRA_CFLAGS="-I${ZLIB_INCLUDE} -I${LZ4_INCLUDE} -I${SNAPPY_INCLUDE} -I${ZSTD_INCLUDE} -arch arm64" + export EXTRA_CXXFLAGS="-I${ZLIB_INCLUDE} -I${LZ4_INCLUDE} -I${SNAPPY_INCLUDE} -I${ZSTD_INCLUDE} -arch arm64" + export EXTRA_LDFLAGS="-L$(dirname ${ZLIB_LIB_RELEASE}) -L$(dirname ${LZ4_LIB_RELEASE}) -L$(dirname ${SNAPPY_LIB_RELEASE}) -L$(dirname ${ZSTD_LIB_RELEASE}) -arch arm64" + + CFLAGS="${ORIGINAL_CFLAGS} -arch arm64" + LDFLAGS="${ORIGINAL_LDFLAGS} -arch arm64" + + CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" PORTABLE=1 make -j$CONCURRENCY shared_lib || fail "arm64 build failed" + strip librocksdb${LIBEXT} + mkdir -p ../runtimes/${RUNTIME}/native && cp -vL ./librocksdb${LIBEXT} ../runtimes/${RUNTIME}/native/librocksdb${LIBEXT} + mkdir -p ../rocksdb-${ROCKSDBVERSION}/${RUNTIME}/native && cp -vL ./librocksdb${LIBEXT} ../rocksdb-${ROCKSDBVERSION}/${RUNTIME}/native/librocksdb${LIBEXT} + fi + }) || fail "rocksdb build failed" fi