diff --git a/.github/workflows/_bazel.yml b/.github/workflows/_bazel.yml index 30b03d5e7b..9a1101901a 100644 --- a/.github/workflows/_bazel.yml +++ b/.github/workflows/_bazel.yml @@ -180,6 +180,95 @@ jobs: //compile/test:cross_compile_aarch64_no_unwind_test working-directory: ${{ inputs.bazel-path }} + package-macos-cross-libs: + if: inputs.action == 'build' && inputs.upload + runs-on: ubuntu-24.04 + name: Package macOS cross-compilation libs + env: + LLVM_VERSION: "18.1.8" + LLVM_MAJOR: "18" + SDK_PKG_URL: >- + https://swcdn.apple.com/content/downloads/52/01/082-41241-A_0747ZN8FHV/dectd075r63pppkkzsb75qk61s0lfee22j/CLTools_macOSNMOS_SDK.pkg + SDK_PKG_SHA256: "ba3453d62b3d2babf67f3a4a44e8073d6555c85f114856f4390a1f53bd76e24a" + PKGUTIL_URL: "https://github.com/cerisier/pkgutil/releases/download/v1.2.0/pkgutil_linux_amd64" + PKGUTIL_SHA256: "3bcf79dbec6b7858ca0c1b6db03952ac122501a74073bac186c8080fcfb391fd" + SDK_PREFIX: "Payload/Library/Developer/CommandLineTools/SDKs/MacOSX15.5.sdk" + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Extract macOS arm64 sysroot + run: | + set -euo pipefail + + # Download pkgutil (extracts macOS .pkg on Linux) + wget "$PKGUTIL_URL" -O pkgutil + echo "${PKGUTIL_SHA256} pkgutil" | sha256sum -c - + chmod +x pkgutil + + # Download Apple CLTools SDK package + wget --user-agent="Mozilla/5.0" "$SDK_PKG_URL" -O CLTools_macOSNMOS_SDK.pkg + echo "${SDK_PKG_SHA256} CLTools_macOSNMOS_SDK.pkg" | sha256sum -c - + + # Extract only the files we need from the SDK package + mkdir -p out/macos_arm64 + includes=() + while IFS=$'\n' read -r line; do + includes+=("--include" "${SDK_PREFIX}/${line}") + done < bazel/sysroot/manifests/sysroot-macos.txt + ./pkgutil "${includes[@]}" --strip-components 6 --expand-full CLTools_macOSNMOS_SDK.pkg out/macos_arm64 + + tar -cf sysroot-macos-arm64.tar -C out/ macos_arm64 + zstd -T0 --long -10 --rm sysroot-macos-arm64.tar + # Also create .tar.xz for compatibility with existing toolshed patterns + tar -cJf sysroot-macos-arm64.tar.xz -C out/ macos_arm64 + + echo "Sysroot size: $(du -sh sysroot-macos-arm64.tar.xz | cut -f1)" + sha256sum sysroot-macos-arm64.tar.xz + - name: Extract darwin libcxx from LLVM release + run: | + set -euo pipefail + + # Extract cxx-cross-libs from official LLVM macOS release (no cmake build needed) + # LLVM 18.x uses "clang+llvm-VER-arm64-apple-macosNN" naming + LLVM_TARBALL="clang+llvm-${LLVM_VERSION}-arm64-apple-macos11.tar.xz" + LLVM_PREFIX="clang+llvm-${LLVM_VERSION}-arm64-apple-macos11" + + wget "https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${LLVM_TARBALL}" \ + -O llvm-macos.tar.xz + + # Extract only the files we need + tar -xf llvm-macos.tar.xz \ + "${LLVM_PREFIX}/include/c++/v1/__config_site" \ + "${LLVM_PREFIX}/lib/libc++.1.0.dylib" \ + "${LLVM_PREFIX}/lib/libc++.1.dylib" \ + "${LLVM_PREFIX}/lib/libc++.dylib" \ + "${LLVM_PREFIX}/lib/libc++abi.1.0.dylib" \ + "${LLVM_PREFIX}/lib/libc++abi.1.dylib" \ + "${LLVM_PREFIX}/lib/libc++abi.dylib" + + mkdir -p libcxx-darwin/{include,lib} + cp "${LLVM_PREFIX}/include/c++/v1/__config_site" libcxx-darwin/include/ + cp -a "${LLVM_PREFIX}/lib/libc++"*.dylib libcxx-darwin/lib/ + + # Patch install names: @rpath/ -> /usr/lib/ so binaries use system libc++ at runtime. + # Use llvm-objcopy from the system (Ubuntu 24.04 has llvm-18 available). + sudo apt-get -qq update && sudo apt-get -qq install -y llvm-18 + llvm-install-name-tool-18 -id /usr/lib/libc++.1.dylib libcxx-darwin/lib/libc++.1.dylib + llvm-install-name-tool-18 -id /usr/lib/libc++abi.dylib libcxx-darwin/lib/libc++abi.1.dylib + + tar -cJf "libcxx-llvm${LLVM_VERSION}-darwin-aarch64.tar.xz" -C libcxx-darwin . + + echo "Libcxx size: $(du -sh "libcxx-llvm${LLVM_VERSION}-darwin-aarch64.tar.xz" | cut -f1)" + sha256sum "libcxx-llvm${LLVM_VERSION}-darwin-aarch64.tar.xz" + - name: Upload artifacts + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: macos-sysroot-artifacts + path: | + sysroot-macos-arm64.tar.xz + libcxx-llvm*-darwin-aarch64.tar.xz + retention-days: 30 + xcompile-arm-to-x86: if: inputs.action == 'test' runs-on: ubuntu-24.04-arm diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml index 98f5632519..eec660a7b0 100644 --- a/.github/workflows/_release.yml +++ b/.github/workflows/_release.yml @@ -246,7 +246,33 @@ jobs: "sed -i s/\($current_sha)/\($new_sha)/g \($versions_file)" else "" end] as $sysroot_updates | $glint_updates + $sysroot_updates] as $arch_updates - | $bins_update + $san_updates + $arch_updates + | [ + # macOS sysroot hash + ($shas["sysroot-macos-arm64.tar.xz"] // null) as $sha_entry + | if $sha_entry then + ($sha_entry | split(":") | .[1]) as $new_sha + | $current.macos_sysroot_sha256.arm64 as $cur + | if $cur == $new_sha then "" + elif ($cur | length) > 0 then + "sed -i s/\($cur)/\($new_sha)/g \($versions_file)" + else + "sed -i '0,/\"arm64\": \"\"/s//\"arm64\": \"\($new_sha)\"/' \($versions_file)" + end + else "" end, + # darwin libcxx hash + ($shas["libcxx-llvm18.1.8-darwin-aarch64.tar.xz"] // null) as $sha_entry + | if $sha_entry then + ($sha_entry | split(":") | .[1]) as $new_sha + | $current.libcxx_libs_darwin_sha256.aarch64 as $cur + | if $cur == $new_sha then "" + elif ($cur | length) > 0 then + "sed -i s/\($cur)/\($new_sha)/g \($versions_file)" + else + "sed -i '0,/\"aarch64\": \"\"/s//\"aarch64\": \"\($new_sha)\"/' \($versions_file)" + end + else "" end + ] as $macos_updates + | $bins_update + $san_updates + $arch_updates + $macos_updates | [flatten[] | select(. != "")] | join("\n") diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 1d81d386df..01389d1759 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -77,6 +77,8 @@ jobs: compile/msan-llvm18.1.8-x86_64.tar.xz compile/tsan-llvm18.1.8-x86_64.tar.xz sysroot/sysroot-*.tar.xz + # Note: macOS sysroot + darwin libcxx are packaged separately + # in the package-macos-cross-libs job (runs on Linux) bazel-args: >- --config=ci ${{ matrix.mode == 'bzlmod' diff --git a/bazel/compile/libcxx_libs.bzl b/bazel/compile/libcxx_libs.bzl index 859332cbf3..3f984761f5 100644 --- a/bazel/compile/libcxx_libs.bzl +++ b/bazel/compile/libcxx_libs.bzl @@ -55,6 +55,82 @@ libcxx_libs = repository_rule( doc = "Downloads prebuilt libcxx bundles for cross-compilation with toolchains_llvm", ) +def _libcxx_libs_darwin_impl(ctx): + """Implementation for darwin libcxx libs repository rule.""" + arch = ctx.attr.arch + + sha256 = ctx.attr.sha256 + if sha256: + ctx.download_and_extract( + url = "https://github.com/envoyproxy/toolshed/releases/download/bins-v{version}/libcxx-llvm{llvm_version}-darwin-{arch}.tar.xz".format( + arch = arch, + version = ctx.attr.version, + llvm_version = VERSIONS["llvm"], + ), + sha256 = sha256, + ) + else: + # No hash available yet — generate __config_site from the Linux version. + ctx.execute(["mkdir", "-p", "include", "lib"]) + linux_config_site = ctx.path(Label("@llvm_toolchain_llvm//:include/x86_64-unknown-linux-gnu/c++/v1/__config_site")) + ctx.execute(["cp", str(linux_config_site), "include/__config_site"]) + + ctx.file("BUILD.bazel", """ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "libcxx_libs_darwin_{arch}", + srcs = glob(["include/**", "lib/**"]), +) + +filegroup( + name = "headers", + srcs = glob(["include/**"]), +) + +filegroup( + name = "libs", + srcs = glob(["lib/**"]), +) + +""".format(arch = arch)) + +libcxx_libs_darwin = repository_rule( + implementation = _libcxx_libs_darwin_impl, + attrs = { + "version": attr.string( + mandatory = True, + doc = "Release version to download", + ), + "sha256": attr.string( + default = "", + doc = "SHA256 hash of the darwin libcxx archive. Empty string generates a fallback __config_site.", + ), + "arch": attr.string( + mandatory = True, + doc = "Architecture (aarch64)", + values = ["aarch64"], + ), + }, + doc = "Downloads prebuilt darwin libcxx for cross-compilation with toolchains_llvm", +) + +def setup_libcxx_libs_darwin( + aarch64_version = None, + aarch64_sha256 = None): + """Setup function for WORKSPACE. + + Creates @libcxx_libs_darwin_aarch64 repository. + """ + sha256 = aarch64_sha256 or VERSIONS.get("libcxx_libs_darwin_sha256", {}).get("aarch64", "") + if "libcxx_libs_darwin_aarch64" not in native.existing_rules(): + libcxx_libs_darwin( + name = "libcxx_libs_darwin_aarch64", + version = aarch64_version or VERSIONS["bins_release"], + sha256 = sha256, + arch = "aarch64", + ) + def setup_libcxx_libs( aarch64_version = None, aarch64_sha256 = None, diff --git a/bazel/sysroot/manifests/sysroot-macos.txt b/bazel/sysroot/manifests/sysroot-macos.txt new file mode 100644 index 0000000000..efebd71398 --- /dev/null +++ b/bazel/sysroot/manifests/sysroot-macos.txt @@ -0,0 +1,22 @@ +usr/include/* +usr/lib/libc.tbd +usr/lib/libcharset* +usr/lib/libdl* +usr/lib/libiconv* +usr/lib/libm.tbd +usr/lib/libobjc* +usr/lib/libresolv* +usr/lib/libpthread.tbd +usr/lib/libSystem* +System/Library/Frameworks/CoreFoundation.framework/* +System/Library/PrivateFrameworks/CoreFoundation.framework/* +System/Library/Frameworks/Foundation.framework/* +System/Library/PrivateFrameworks/Foundation.framework/* +System/Library/Frameworks/Kernel.framework/* +System/Library/PrivateFrameworks/Kernel.framework/* +System/Library/Frameworks/OSLog.framework/* +System/Library/PrivateFrameworks/OSLog.framework/* +System/Library/Frameworks/Security.framework/* +System/Library/PrivateFrameworks/Security.framework/* +System/Library/Frameworks/SystemConfiguration.framework/* +System/Library/PrivateFrameworks/SystemConfiguration.framework/* diff --git a/bazel/sysroot/sysroot.bzl b/bazel/sysroot/sysroot.bzl index 545bf27b66..051e7cd5d2 100644 --- a/bazel/sysroot/sysroot.bzl +++ b/bazel/sysroot/sysroot.bzl @@ -156,6 +156,74 @@ def _get_sysroot_hash(glibc_version, stdcc_version, arch): return sha256 +_MACOS_SYSROOT_BUILD = """\ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "sysroot", + srcs = glob( + ["**"], + exclude = ["**/*:*"], + ), +) +""" + +def _macos_sysroot_impl(ctx): + """Implementation for macOS SDK sysroot repository rule.""" + if ctx.os.name.startswith("mac"): + # On macOS, no cross-compilation sysroot needed. + ctx.file("BUILD.bazel", _MACOS_SYSROOT_BUILD) + return + + sha256 = ctx.attr.sha256 + if sha256: + url = "https://github.com/envoyproxy/toolshed/releases/download/bins-v{version}/sysroot-macos-{arch}.tar.xz".format( + version = ctx.attr.version, + arch = ctx.attr.arch, + ) + ctx.download_and_extract( + url, + sha256 = sha256, + ) + else: + # No hash available yet — create an empty sysroot. + ctx.execute(["mkdir", "-p", "usr/include"]) + + ctx.file("BUILD.bazel", _MACOS_SYSROOT_BUILD) + +macos_sysroot = repository_rule( + implementation = _macos_sysroot_impl, + attrs = { + "version": attr.string( + mandatory = True, + doc = "Release version to download", + ), + "sha256": attr.string( + default = "", + doc = "SHA256 hash of the macOS sysroot archive. Empty string skips download.", + ), + "arch": attr.string( + default = "arm64", + doc = "Architecture (arm64)", + ), + }, + doc = "Downloads macOS SDK sysroot for cross-compilation from Linux", +) + +def setup_macos_sysroot(version = None): + """Set up macOS arm64 sysroot for cross-compilation. + + Creates @sysroot_macos_arm64 repository. + """ + sha256 = VERSIONS.get("macos_sysroot_sha256", {}).get("arm64", "") + if "sysroot_macos_arm64" not in native.existing_rules(): + macos_sysroot( + name = "sysroot_macos_arm64", + version = version or VERSIONS["bins_release"], + sha256 = sha256, + arch = "arm64", + ) + def setup_sysroots( version = None, glibc_version = "2.31", diff --git a/bazel/versions.bzl b/bazel/versions.bzl index 4df6126dbf..1b59cc04d6 100644 --- a/bazel/versions.bzl +++ b/bazel/versions.bzl @@ -39,6 +39,16 @@ VERSIONS = { "x86_64": "50c7385dd1c17fd3606fa8850cfb1c7d0166ab109e404964f55abd6b508560eb", }, + # Darwin libc++ for cross-compilation (extracted from LLVM macOS release) + "libcxx_libs_darwin_sha256": { + "aarch64": "", + }, + + # macOS SDK sysroot for cross-compilation (extracted from Apple CLTools) + "macos_sysroot_sha256": { + "arm64": "", + }, + # Glint binary hashes by architecture "glint_sha256": { "amd64": "a9389398ba5719197f7c81e6a8127262095a1a5f1ea3a509f16c32bf4ee65719",