Files
Keith Smiley 76a44e46d4 [cmake] Build libxml from source in release (#221365)
With 23.x we started linking a static libxml in release builds to avoid
requiring that to be installed, and the varying names of that library on
different linux distros. That broke more than it fixed because the
static libxml in our docker images are built targeting ICU, and ICU's
shared library version changes quickly, so even between 2 ubuntu
versions the binaries will not work.

With this change we now build from source in the release build, which is
already what windows does, and we disable ICU / iconv since those don't
seem vital for the windows manifest use case. This seems easier than
building a libxml out of band in our CI images that do the release
builds.

Fixes https://github.com/llvm/llvm-project/issues/215764

Assisted-By: codex
(cherry picked from commit 5ae71ec799917c67e9e72510e68831602fc60699)
2026-10-05 17:33:07 +02:00

455 lines
18 KiB
YAML

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
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: Checkout LLVM
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- 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 }}
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@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: '3.14.6'
# 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: |
echo "LIB=$env:LIB;C:\hostedtoolcache\windows\Python\3.14.6\$($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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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)
if: runner.os == 'Windows' && runner.arch == 'ARM64'
run: |
choco install wixtoolset --version 3.14.1.20250415
# Add wix install directory to PATH.
Split-Path (Get-ChildItem -Path "C:\" -Filter candle.exe -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1).FullName >> $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 }}
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
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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
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-24.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 }}