From 7ded880b2939e282e7ae5d0568a794f4b4e974b7 Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Wed, 9 Oct 2024 19:09:32 -0400 Subject: [PATCH 1/3] Use lld to reduce macOS release binary size --- .bazelrc | 11 +++++++++++ .github/workflows/release.yml | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/.bazelrc b/.bazelrc index c75186b55b5..4fd01e3dda0 100644 --- a/.bazelrc +++ b/.bazelrc @@ -318,6 +318,17 @@ build:release_macos --config=release_unix build:release_macos --linkopt="-Wl,-no_data_in_code_info" build:release_macos --linkopt="-Wl,-no_function_starts" +# On macOS, optionally compile using LLD (19 or higher is compatible with the default flags added by +# apple_support). Requires Homebrew's lld package to be installed. This is less CPU intensive than +# the system linker, but also slightly slower in terms of wall time since it is less parallel. More +# importantly, it allows us to enable LLD's ICF pass, which significantly decreases binary sizes. +# We could use Xcode 16's -Wl,-deduplicate option instead, but LLD's ICF appears to be superior. +# We also want to enable ICF for Linux, but there it causes warnings when dynamically linking with +# libc++. +build:macos_lld --linkopt="-fuse-ld=/opt/homebrew/bin/ld64.lld" +build:macos_lld_icf --config=macos_lld +build:macos_lld_icf --linkopt="-Wl,--icf=safe" + build:release_windows --config=release # Windows uses /O2 as its preferred optimization setting and enabled by bazel in the opt # configuration, but for clang-cl this is equivalent to only -O2 and a few other things. -O3 is diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 99063ace919..2dd4378054a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,6 +96,10 @@ jobs: if: runner.os == 'macOS' run: | sudo xcode-select -s "/Applications/Xcode_15.1.app" + # Install lld + brew install lld + # Enable lld identical code folding to significantly reduce binary size. + echo "build:macos --config=macos_lld_icf" >> .bazelrc - name: Setup Windows if: runner.os == 'Windows' run: | From 5ca5b4a56ce6bf0fff7d4d0ef07391fea532fa55 Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Wed, 9 Oct 2024 19:32:18 -0400 Subject: [PATCH 2/3] [CI] Use macos-15 image for test job, implicitly transitioning to Apple Silicon To mitigate our problems with macOS runner rate limiting, switch to the macos-15 runner image. This means we are implicitly transitioning the test job to Apple Silicon (macos-13 is x86, macos-15 is Apple Silicon with no x86 option available outside of paid runners). This allows us to take advantage of the latest compiler features available in Xcode 16 (based on LLVM 17), which is not available for macOS 13. Xcode has good backwards compatibility; based on the macos_minimum_os flag we will continue to support macOS 13 and later. Interestingly, the macos-15 build is much faster (~2x based on limited testing), so this will help avoid having stalled macOS build jobs. This is likely due to the Apple Silicon CPUs being more performant, although the new compiler version could also be helping. The release job continues to use the macos-13/x86 image, so we continue to have coverage for x86. If this proves to be stable, we can also add an Apple Silicon release build and decommission the internal arm64 macOS build. --- .github/workflows/test.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fecddeb1ea3..5284188acbd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,16 +19,16 @@ jobs: fixup: if: github.event_name == 'pull_request' uses: ./.github/workflows/fixup.yml - labels: + labels: if: github.event_name == 'pull_request' - uses: ./.github/workflows/labels.yml + uses: ./.github/workflows/labels.yml test: strategy: matrix: os: [ { name : linux, image : ubuntu-20.04 }, - { name : macOS, image : macos-13 }, + { name : macOS, image : macos-15 }, { name : windows, image : windows-2022 } ] config: @@ -62,7 +62,7 @@ jobs: config: { suffix: -debug, bazel-args: --config=debug } # due to resource constraints, exclude the macOS-debug runner for now. linux-debug and # linux-asan should provide sufficient coverage for building in the debug configuration. - - os: { name : macOS, image : macos-13 } + - os: { name : macOS, image : macos-15 } config: { suffix: -debug, bazel-args: --config=debug } fail-fast: false runs-on: ${{ matrix.os.image }} @@ -103,17 +103,15 @@ jobs: sed -i -e "s%llvm-symbolizer%/usr/lib/llvm-16/bin/llvm-symbolizer%" .bazelrc - name: Setup macOS if: matrix.os.name == 'macOS' - # TODO: We want to symbolize stacks for crashes on CI. Xcode is currently based on LLVM 16 - # but the macos-13 image has llvm@15 installed: - # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md + # TODO: We want to symbolize stacks for crashes on CI. Xcode is currently based on LLVM 17 + # but the macos-15 image has llvm@18 installed: + # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md # # Not enabled because symbolication does not work on workerd macOS builds yet and running # llvm-symbolizer in the currently broken state causes some tests to time out on the # runner. - # Use latest available Xcode version – runner still defaults to 15.0.1. run: | - sudo xcode-select -s "/Applications/Xcode_15.1.app" - # export LLVM_SYMBOLIZER=$(brew --prefix llvm@15)/bin/llvm-symbolizer + # export LLVM_SYMBOLIZER=$(brew --prefix llvm@18)/bin/llvm-symbolizer # sed -i -e "s%llvm-symbolizer%${LLVM_SYMBOLIZER}%" .bazelrc - name: Setup Windows if: matrix.os.name == 'windows' From a9f950b82e249fbae528a9c97a2affeb59bf7625 Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Thu, 10 Oct 2024 08:55:01 -0400 Subject: [PATCH 3/3] [nfc] Drop duplicated macOS experimental_objc_fastbuild_options flag --- .bazelrc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.bazelrc b/.bazelrc index 4fd01e3dda0..f3b086bf580 100644 --- a/.bazelrc +++ b/.bazelrc @@ -219,12 +219,7 @@ build:macos --copt='-femit-dwarf-unwind=no-compact-unwind' # an effect. On macOS we build some ObjC as part of Dawn, set this flag to an empty string so we # can set the right configuration flags. # TODO(soon): File a bazel issue for the flag so we can drop this. -build:macos --experimental_objc_fastbuild_options='' - -# Unfortunately experimental_objc_fastbuild_options does not respect options set before and -# overwrites them. This causes mysterious binary size bloat for fastbuild-based configurations on -# macOS when enabling some optimizations. Turn it in into a no-op. -build:mac --experimental_objc_fastbuild_options="" +build:macos --experimental_objc_fastbuild_options="" # On Linux, always link libc++ statically to avoid compatibility issues with different OS versions. # macOS links with dynamic libc++ by default, which has good backwards compatibility.