| name: Release Binaries | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release-version: | |
| description: 'Release Version' | |
| required: false | |
| type: string | |
| upload: | |
| description: 'Upload binaries to the release page' | |
| required: true | |
| default: false | |
| type: boolean | |
| runs-on: | |
| description: "Runner to use for the build" | |
| required: true | |
| type: choice | |
| # We use ubuntu-22.04 rather than the latest version to make the built | |
| # binaries more portable (eg functional aginast older glibc). | |
| options: | |
| - ubuntu-22.04 | |
| - ubuntu-22.04-arm | |
| - macos-14 | |
| - windows-2022 | |
| - windows-11-arm | |
| workflow_call: | |
| inputs: | |
| release-version: | |
| description: 'Release Version' | |
| required: false | |
| type: string | |
| upload: | |
| description: 'Upload binaries to the release page' | |
| required: true | |
| default: false | |
| type: boolean | |
| runs-on: | |
| description: "Runner to use for the build" | |
| required: true | |
| type: string | |
| secrets: | |
| LLVM_TOKEN_GENERATOR_CLIENT_ID: | |
| description: "Client ID for our GitHub App we use for generating access tokens." | |
| required: true | |
| LLVM_TOKEN_GENERATOR_PRIVATE_KEY: | |
| description: "Private key for our GitHub App we use for generating access tokens." | |
| required: true | |
| permissions: | |
| contents: read # Default everything to read-only | |
| jobs: | |
| prepare: | |
| name: Prepare to build binaries | |
| runs-on: ${{ inputs.runs-on }} | |
| if: github.repository_owner == 'llvm' | |
| outputs: | |
| release-version: ${{ steps.vars.outputs.release-version }} | |
| ref: ${{ steps.vars.outputs.ref }} | |
| upload: ${{ steps.vars.outputs.upload }} | |
| target-cmake-flags: ${{ steps.vars.outputs.target-cmake-flags }} | |
| build-flang: ${{ steps.vars.outputs.build-flang }} | |
| release-binary-basename: ${{ steps.vars.outputs.release-binary-basename }} | |
| release-binary-filename: ${{ steps.vars.outputs.release-binary-filename }} | |
| release-binary-filename-zstd: ${{ steps.vars.outputs.release-binary-filename-zstd }} | |
| build-runs-on: ${{ steps.vars.outputs.build-runs-on }} | |
| test-runs-on: ${{ steps.vars.outputs.build-runs-on }} | |
| attestation-name: ${{ steps.vars.outputs.attestation-name }} | |
| steps: | |
| - name: Validate Release Version | |
| if: inputs.release-version != '' | |
| uses: $/.github/workflows/validate-release-version | |
| with: | |
| release-version: ${{ inputs.release-version }} | |
| # The name of the Windows binaries uses the version from source, so we need | |
| # to fetch it here. | |
| - id: version-from-source | |
| if: runner.os == 'Windows' | |
| uses: $/.github/workflows/get-llvm-version | |
| - name: Collect Variables | |
| id: vars | |
| env: | |
| LLVM_VERSION_FROM_SOURCE: ${{ steps.version-from-source.outputs.full-no-suffix }} | |
| LLVM_VERSION_MAJOR: ${{ steps.version-from-source.outputs.major }} | |
| INPUTS_RUNS_ON: ${{ inputs.runs-on }} | |
| INPUTS_RELEASE_VERSION: ${{ inputs.release-version }} | |
| shell: bash | |
| # In order for the test-release.sh script to run correctly, the LLVM | |
| # source needs to be at the following location relative to the build dir: | |
| # | X.Y.Z-rcN | ./rcN/llvm-project | |
| # | X.Y.Z | ./final/llvm-project | |
| # | |
| # We also need to set divergent flags based on the release version: | |
| # | X.Y.Z-rcN | -rc N -test-asserts | |
| # | X.Y.Z | -final | |
| run: | | |
| trimmed=$(echo "$INPUTS_RELEASE_VERSION" | xargs) | |
| if [ -n "$trimmed" ]; then | |
| release_version="$trimmed" | |
| ref="llvmorg-$release_version" | |
| else | |
| if [ "$RUNNER_OS" = "Windows" ]; then | |
| release_version="$LLVM_VERSION_FROM_SOURCE" | |
| else | |
| release_version="${{ (github.event_name == 'pull_request' && format('PR{0}', github.event.pull_request.number)) || 'CI'}}-$GITHUB_SHA" | |
| fi | |
| ref="$GITHUB_SHA" | |
| fi | |
| if [ "$RUNNER_OS" = "Windows" ] && grep -q 'rc' <<< "$release_version"; then | |
| # The Wix installer generator does not support strings in the version number, | |
| # so we need to fixup the version number for release candidates. | |
| # For Example: 23.1.0-rc2 will become 23.0.0.2 | |
| release_version="$LLVM_VERSION_MAJOR.0.0.$(cut -d c -f2 <<< $release_version)" | |
| fi | |
| if [ -n "${{ inputs.upload }}" ]; then | |
| upload="${{ inputs.upload }}" | |
| else | |
| upload="false" | |
| fi | |
| echo "release-version=$release_version">> $GITHUB_OUTPUT | |
| echo "ref=$ref" >> $GITHUB_OUTPUT | |
| echo "upload=$upload" >> $GITHUB_OUTPUT | |
| if [ "$RUNNER_OS" = "Windows" ]; then | |
| case $RUNNER_ARCH in | |
| "X64" ) | |
| tar_arch="x86_64" | |
| ;; | |
| "ARM64" ) | |
| tar_arch="aarch64" | |
| ;; | |
| esac | |
| release_binary_basename="clang+llvm-$release_version-$tar_arch-pc-windows-msvc" | |
| else | |
| release_binary_basename="LLVM-$release_version-$RUNNER_OS-$RUNNER_ARCH" | |
| fi | |
| echo "release-binary-basename=$release_binary_basename" >> $GITHUB_OUTPUT | |
| echo "release-binary-filename=$release_binary_basename.tar.xz" >> $GITHUB_OUTPUT | |
| echo "release-binary-filename-zstd=$release_binary_basename.tar.zst" >> $GITHUB_OUTPUT | |
| target="$RUNNER_OS-$RUNNER_ARCH" | |
| # The macOS builds try to cross compile some libraries so we need to | |
| # add extra CMake args to disable them. | |
| # See https://github.com/llvm/llvm-project/issues/99767 | |
| if [ "$RUNNER_OS" = "macOS" ]; then | |
| target_cmake_flags="$target_cmake_flags -DBOOTSTRAP_BOOTSTRAP_COMPILER_RT_ENABLE_IOS=OFF" | |
| if [ "$RUNNER_ARCH" = "ARM64" ]; then | |
| arches=arm64 | |
| fi | |
| target_cmake_flags="$target_cmake_flags -DBOOTSTRAP_BOOTSTRAP_DARWIN_osx_ARCHS=$arches -DBOOTSTRAP_BOOTSTRAP_DARWIN_osx_BUILTIN_ARCHS=$arches" | |
| fi | |
| if [ "$RUNNER_OS" = "Windows" ]; then | |
| # The build times out on Windows, so we need to disable LTO. | |
| target_cmake_flags="$target_cmake_flags -DLLVM_RELEASE_ENABLE_LTO=OFF" | |
| fi | |
| case "$INPUTS_RUNS_ON" in | |
| ubuntu-22.04* | windows-2022) | |
| build_runs_on="depot-$INPUTS_RUNS_ON-16" | |
| test_runs_on=$build_runs_on | |
| ;; | |
| windows-11-arm) | |
| if [ "$GITHUB_EVENT_NAME" = "pull_request" ] || [ "$GITHUB_EVENT_NAME" = "schedule" ]; then | |
| build_runs_on="$INPUTS_RUNS_ON" | |
| else | |
| build_runs_on="windows-11-arm-16core" | |
| fi | |
| test_runs_on=$build_runs_on | |
| ;; | |
| macos-14) | |
| if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then | |
| build_runs_on="$INPUTS_RUNS_ON" | |
| else | |
| build_runs_on="depot-macos-14" | |
| fi | |
| test_runs_on="$INPUTS_RUNS_ON" | |
| ;; | |
| *) | |
| test_runs_on="$INPUTS_RUNS_ON" | |
| build_runs_on=$test_runs_on | |
| ;; | |
| esac | |
| case "$build_runs_on" in | |
| # These runners cannot build the full release package faster than | |
| # the 6 hours timeout limit, so we need to use a configuration | |
| # that builds more quickly. | |
| macos-14) | |
| bootstrap_prefix="BOOTSTRAP" | |
| target_cmake_flags="$target_cmake_flags -DLLVM_RELEASE_ENABLE_LTO=OFF -DLLVM_RELEASE_ENABLE_PGO=OFF" | |
| ;; | |
| *) | |
| bootstrap_prefix="BOOTSTRAP_BOOTSTRAP" | |
| ;; | |
| esac | |
| target_cmake_flags="$target_cmake_flags -D${bootstrap_prefix}_CPACK_PACKAGE_FILE_NAME=$release_binary_basename" | |
| echo "target-cmake-flags=$target_cmake_flags" >> $GITHUB_OUTPUT | |
| echo "build-runs-on=$build_runs_on" >> $GITHUB_OUTPUT | |
| echo "test-runs-on=$test_runs_on" >> $GITHUB_OUTPUT | |
| echo "attestation-name=$RUNNER_OS-$RUNNER_ARCH-release-binary-attestation" >> $GITHUB_OUTPUT | |
| build-release-package: | |
| name: "Build Release Package" | |
| needs: prepare | |
| if: github.repository_owner == 'llvm' | |
| runs-on: ${{ needs.prepare.outputs.build-runs-on }} | |
| outputs: | |
| digest: ${{ steps.digest.outputs.digest }} | |
| artifact-id: ${{ steps.artifact-upload.outputs.artifact-id }} | |
| steps: | |
| # We need to hard code the python library path for Windows, so in order | |
| # to do that we need to specify a specific python version. It's also | |
| # good practice to do this on other OSes so the version of python doesn't | |
| # get changed unexpectedly. | |
| - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: '3.14.8' | |
| # For some reason this is needed on Windows or else the build system can't find python3.lib. | |
| - name: Setup Python library path | |
| if: runner.os == 'Windows' | |
| run: | | |
| $python_version = (python -c "import platform; print(platform.python_version())").Trim() | |
| echo "LIB=$env:LIB;C:\hostedtoolcache\windows\Python\$python_version\$($env:RUNNER_ARCH.ToLower())\libs" >> $env:GITHUB_ENV | |
| - name: Setup crlf | |
| if: runner.os == 'Windows' | |
| run: | | |
| git config --global core.autocrlf false | |
| - name: Checkout LLVM | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| ref: ${{ needs.prepare.outputs.ref }} | |
| - name: Set Build Prefix | |
| id: setup-stage | |
| shell: bash | |
| run: | | |
| build_prefix=`pwd` | |
| if [ "${{ runner.os }}" = "Linux" ]; then | |
| sudo chown $USER:$USER /mnt/ | |
| build_prefix=/mnt/ | |
| fi | |
| echo "build-prefix=$build_prefix" >> $GITHUB_OUTPUT | |
| - name: Build libxml2 (Linux) | |
| if: runner.os == 'Linux' | |
| env: | |
| BUILD_PREFIX: ${{ steps.setup-stage.outputs.build-prefix }} | |
| shell: bash | |
| run: | | |
| libxml2_prefix="$BUILD_PREFIX/libxml2-install" | |
| libxml2_build_dir="$BUILD_PREFIX/libxml2-build" | |
| libxml2_version=2.15.1 | |
| libxml2_archive="libxml2-$libxml2_version.tar.xz" | |
| libxml2_checksum=c008bac08fd5c7b4a87f7b8a71f283fa581d80d80ff8d2efd3b26224c39bc54c | |
| mkdir -p "$libxml2_build_dir" "$libxml2_prefix" | |
| cd "$libxml2_build_dir" || exit | |
| curl --fail --location --retry 3 \ | |
| "https://download.gnome.org/sources/libxml2/2.15/$libxml2_archive" -o "$libxml2_archive" | |
| echo "$libxml2_checksum $libxml2_archive" | sha256sum --check | |
| tar -xf "$libxml2_archive" | |
| cmake -G Ninja -S "libxml2-$libxml2_version" -B build \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_INSTALL_PREFIX="$libxml2_prefix" \ | |
| -DCMAKE_INSTALL_LIBDIR=lib \ | |
| -DBUILD_SHARED_LIBS=OFF \ | |
| -DLIBXML2_WITH_ICU=OFF \ | |
| -DLIBXML2_WITH_ICONV=OFF \ | |
| -DLIBXML2_WITH_MODULES=OFF \ | |
| -DLIBXML2_WITH_PROGRAMS=OFF \ | |
| -DLIBXML2_WITH_TESTS=OFF \ | |
| -DLIBXML2_WITH_ZLIB=ON | |
| cmake --build build --parallel | |
| cmake --install build --component development | |
| echo "PKG_CONFIG_PATH=$libxml2_prefix/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" >> "$GITHUB_ENV" | |
| - name: Configure Linux/MacOS | |
| id: build | |
| if: runner.os != 'Windows' | |
| env: | |
| BUILD_PREFIX: ${{ steps.setup-stage.outputs.build-prefix }} | |
| TARGET_CMAKE_FLAGS: ${{ needs.prepare.outputs.target-cmake-flags }} | |
| shell: bash | |
| run: | | |
| libxml2_cmake_flags=() | |
| if [ "$RUNNER_OS" = "Linux" ]; then | |
| libxml2_prefix="$BUILD_PREFIX/libxml2-install" | |
| for stage in "" BOOTSTRAP_ BOOTSTRAP_BOOTSTRAP_; do | |
| libxml2_cmake_flags+=( | |
| "-D${stage}LIBXML2_INCLUDE_DIR=$libxml2_prefix/include/libxml2" | |
| "-D${stage}LIBXML2_LIBRARY=$libxml2_prefix/lib/libxml2.a" | |
| "-D${stage}LIBXML2_STATIC_LIBRARY=$libxml2_prefix/lib/libxml2.a" | |
| ) | |
| done | |
| fi | |
| # There were some issues on the ARM64 MacOS runners with trying to build x86 object, | |
| # so we need to set some extra cmake flags to disable this. | |
| cmake -G Ninja -S llvm -B "$BUILD_PREFIX/build" \ | |
| $TARGET_CMAKE_FLAGS \ | |
| "${libxml2_cmake_flags[@]}" \ | |
| -C clang/cmake/caches/Release.cmake | |
| - name: Build Linux/MacOS | |
| if: runner.os != 'Windows' | |
| shell: bash | |
| env: | |
| BUILD_PREFIX: ${{ steps.setup-stage.outputs.build-prefix }} | |
| RELEASE_BINARY_FILENAME: ${{ needs.prepare.outputs.release-binary-filename }} | |
| run: | | |
| ninja -v -C "$BUILD_PREFIX/build" stage2-package | |
| release_dir=`find "$BUILD_PREFIX/build" -iname 'stage2-bins'` | |
| mv "$release_dir/$RELEASE_BINARY_FILENAME" . | |
| # Wix is not installed by default on Windows ARM64 | |
| - name: Install Wix (Windows ARM64) | |
| env: | |
| WIX_VERSION: 3.14 | |
| if: runner.os == 'Windows' && runner.arch == 'ARM64' | |
| run: | | |
| choco install wixtoolset --version "$($env:WIX_VERSION).1.20250415" | |
| # Add wix install directory to PATH. | |
| echo "C:\Program Files (x86)\WiX Toolset v$($env:WIX_VERSION)\bin" >> $env:GITHUB_PATH | |
| - name: Build Windows | |
| id: build-windows | |
| if: runner.os == 'Windows' | |
| env: | |
| INPUTS_RUNS_ON: ${{ inputs.runs-on }} | |
| LLVM_VERSION: ${{ needs.prepare.outputs.release-version }} | |
| EXTRA_ARGS: ${{ case(needs.prepare.outputs.build-runs-on == 'windows-11-arm', '--fast-build', '--fast-build') }} | |
| run: | | |
| subst S: ${{ github.workspace }} | |
| cd S:\llvm\utils\release\ | |
| .\build_llvm_release.bat "--$($env:RUNNER_ARCH.ToLower())" --version $env:LLVM_VERSION --local-python --skip-checkout $env:EXTRA_ARGS | |
| if ($env:INPUTS_RUNS_ON -eq "windows-11-arm") { | |
| $zstd = (Get-ChildItem -Recurse -Filter "zstd.exe" | Select-Object -First 1).fullName | |
| mv $zstd $env:GITHUB_WORKSPACE | |
| } | |
| $installer = (Get-ChildItem -Recurse -Filter "LLVM-*.msi" | Select-Object -First 1).fullName | |
| $tarball = (Get-ChildItem -Recurse -Filter "*.tar.xz" | Select-Object -First 1).fullName | |
| # Move installer to top-level directory so it is easier to upload. | |
| mv $installer $env:GITHUB_WORKSPACE | |
| mv $tarball $env:GITHUB_WORKSPACE | |
| echo "windows-installer-filename=$(Split-Path -Path $installer -Leaf)" >> $env:GITHUB_OUTPUT | |
| - name: Dump Wix logs | |
| if: runner.os == 'Windows' && failure() | |
| env: | |
| LLVM_VERSION: ${{ needs.prepare.outputs.release-version }} | |
| BUILD_DIR_SUFFIX: ${{ case(runner.arch == 'ARM64', 'arm64', 'amd64') }} | |
| run: | | |
| cat S:/llvm/utils/release/llvm_package_$($env:LLVM_VERSION)/build_$($env:BUILD_DIR_SUFFIX)/_CPack_Packages/win64/WIX/wix.log | |
| - name: Create zstd compressed tarball | |
| shell: bash | |
| env: | |
| RELEASE_BINARY_FILENAME: ${{ needs.prepare.outputs.release-binary-filename }} | |
| RELEASE_BINARY_FILENAME_ZSTD: ${{ needs.prepare.outputs.release-binary-filename-zstd }} | |
| ZSTD: ${{ inputs.runs-on == 'windows-11-arm' && './zstd.exe' || 'zstd' }} | |
| run: | | |
| # A 1 GiB window captures duplicate code across the large statically | |
| # linked tools. Four workers keep memory use within runner limits. | |
| xz -dc "$RELEASE_BINARY_FILENAME" | \ | |
| "$ZSTD" --ultra -21 --long=30 -T4 -B1024M \ | |
| -o "$RELEASE_BINARY_FILENAME_ZSTD" | |
| - name: Generate sha256 digest for binaries | |
| id: digest | |
| shell: bash | |
| env: | |
| RELEASE_BINARY_FILENAME: ${{ needs.prepare.outputs.release-binary-filename }} | |
| # This will be empty on non-Windows builds. | |
| WINDOWS_INSTALLER_FILENAME: ${{ steps.build-windows.outputs.windows-installer-filename }} | |
| RELEASE_BINARY_FILENAME_ZSTD: ${{ needs.prepare.outputs.release-binary-filename-zstd }} | |
| run: | | |
| if [ "$RUNNER_OS" = "macOS" ]; then | |
| # Mac runners don't have sha256sum. | |
| sha256sum="shasum -a 256" | |
| else | |
| sha256sum="sha256sum" | |
| fi | |
| echo "digest=$(cat $WINDOWS_INSTALLER_FILENAME $RELEASE_BINARY_FILENAME $RELEASE_BINARY_FILENAME_ZSTD | $sha256sum | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT | |
| - name: Install LLDB test Python dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| python -m pip install -r lldb/test/requirements.txt | |
| - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 | |
| id: artifact-upload | |
| with: | |
| name: ${{ runner.os }}-${{ runner.arch }}-release-binary | |
| # Due to path differences on Windows when running in bash vs running on node, | |
| # we need to search for files in the current workspace. | |
| # The steps.build-windows.* variables will be empty on Linux/MacOS. | |
| path: | | |
| ${{ needs.prepare.outputs.release-binary-filename }} | |
| ${{ needs.prepare.outputs.release-binary-filename-zstd }} | |
| ${{ steps.build-windows.outputs.windows-installer-filename }} | |
| - name: Run Tests | |
| # These almost always fail so don't let them fail the build and prevent the uploads. | |
| if : runner.os != 'Windows' | |
| continue-on-error: true | |
| env: | |
| BUILD_PREFIX: ${{ steps.setup-stage.outputs.build-prefix }} | |
| run: | | |
| ninja -C "$BUILD_PREFIX/build" stage2-check-all | |
| upload-release-binaries: | |
| name: "Upload Release Binaries" | |
| environment: | |
| deployment: false | |
| name: release | |
| needs: | |
| - prepare | |
| - build-release-package | |
| if: >- | |
| github.event_name != 'pull_request' | |
| runs-on: ubuntu-26.04 | |
| permissions: | |
| contents: write # For release uploads | |
| id-token: write # For artifact attestations | |
| attestations: write # For artifact attestations | |
| steps: | |
| - name: Upload Artifacts | |
| uses: $/.github/workflows/upload-release-artifact | |
| with: | |
| # We need to use the inputs.release-version here, because on Windows we | |
| # need to fixup the rc version that's stored in needs.prepare.outputs.release-version | |
| release-version: ${{ inputs.release-version || needs.prepare.outputs.release-version }} | |
| artifact-id: ${{ needs.build-release-package.outputs.artifact-id }} | |
| attestation-name: ${{ needs.prepare.outputs.attestation-name }} | |
| digest: ${{ needs.build-release-package.outputs.digest }} | |
| upload: ${{ needs.prepare.outputs.upload }} | |
| LLVM_TOKEN_GENERATOR_CLIENT_ID: ${{ secrets.LLVM_TOKEN_GENERATOR_CLIENT_ID }} | |
| LLVM_TOKEN_GENERATOR_PRIVATE_KEY: ${{ secrets.LLVM_TOKEN_GENERATOR_PRIVATE_KEY }} |