Skip to content

conan packages

conan packages #1094

name: conan packages
on:
workflow_dispatch:
inputs:
conan_major_version:
description: 'Conan major version to build'
required: true
default: '1'
type: choice
options:
- '1'
- '2'
publish_dry_run:
description: 'Validate publish workflow without uploading packages'
required: true
default: true
type: boolean
schedule:
- cron: '25 6 * * 4' # 6:25am UTC every Thursday
- cron: '25 8 * * 4' # 8:25am UTC every Thursday, Conan 2
env:
conan1_version: 1.66.0
conan2_version: '>=2,<3'
# Pin the macOS/iOS toolchain so published binaries (and their LTO bitcode)
# stay linkable by downstream consumers instead of drifting with the runner
# image's default Xcode. Must match a version installed on the runner.
xcode_version: '16.4'
jobs:
generate-matrix:
name: generate build matrix
runs-on: ubuntu-latest
outputs:
matrix-json: ${{ steps.generate-matrix.outputs.matrix }}
conan_major_version: ${{ steps.select-conan-version.outputs.conan_major_version }}
steps:
- name: Select Conan version
id: select-conan-version
shell: pwsh
run: |
$ConanMajorVersion = '${{ inputs.conan_major_version }}'
if ([string]::IsNullOrWhiteSpace($ConanMajorVersion)) {
if ('${{ github.event_name }}' -eq 'schedule' -and '${{ github.event.schedule }}' -eq '25 8 * * 4') {
$ConanMajorVersion = '2'
} else {
$ConanMajorVersion = '1'
}
}
echo "conan_major_version=$ConanMajorVersion" >> $Env:GITHUB_OUTPUT
- name: create build matrix
id: generate-matrix
shell: pwsh
env:
CONAN_MAJOR_VERSION: ${{ steps.select-conan-version.outputs.conan_major_version }}
run: |
$Jobs = @()
if ($Env:CONAN_MAJOR_VERSION -eq '2') {
@('windows', 'macos', 'linux', 'ios', 'iossimulator', 'android') | Foreach-Object {
$Platform = $_
$Architectures = if ($Platform -Eq 'iossimulator') { @('arm64') } else { @('x86_64', 'aarch64') }
if ($Platform -Eq 'android') {
$Architectures += 'arm'
$Architectures += 'x86'
}
$Architectures | ForEach-Object {
$Architecture = $_
$BuildTypes = @('Debug', 'Release')
if ($Platform -Eq 'windows' -Or $Platform -Eq 'macos' -Or $Platform -Eq 'android') {
$BuildTypes += 'RelWithDebInfo'
}
$BuildTypes | ForEach-Object {
$BuildType = $_
$Job = @{
name = "[conan2-$Platform-$Architecture-$BuildType]"
arch = $Architecture
build_type = $BuildType
os = $Platform
runner = switch ($Platform) {
'windows' { 'windows-2022' }
{ @('macos', 'ios', 'iossimulator') -contains $_ } { 'macos-15' }
{ @('linux', 'android') -contains $_ } { 'ubuntu-22.04' }
}
}
if ($Platform -Eq 'macos' -And $Architecture -Eq 'x86_64') {
$Job.runner = 'macos-15-intel'
}
if ($Platform -Eq 'linux') {
@('ubuntu-20.04', 'ubuntu-18.04', 'ubuntu-22.04') | ForEach-Object {
$LinuxJob = $Job.Clone()
$LinuxJob['distro'] = $_
$LinuxJob['name'] = "[conan2-$($LinuxJob['distro'])-$Architecture-$BuildType]"
$Jobs += $LinuxJob
}
} else {
$Jobs += $Job
}
}
}
}
echo "matrix=$(ConvertTo-JSON -Compress -InputObject @($Jobs))" >> $Env:GITHUB_OUTPUT
return
}
@('windows', 'macos', 'linux', 'ios', 'iossimulator', 'android') | Foreach-Object {
$Platform = $_
$Architectures = if ($Platform -Eq 'iossimulator') { @('arm64') } else { @('x86_64', 'aarch64') }
if($Platform -Eq 'android') {
$Architectures += 'arm'
$Architectures += 'x86'
}
$Architectures | ForEach-Object {
$Architecture = $_
$BuildTypes = @('Debug', 'Release')
if ($Platform -Eq "windows" -Or $Platform -Eq "macos" -Or $Platform -Eq "Android") {
$BuildTypes += "RelWithDebInfo"
}
$BuildTypes | ForEach-Object {
$BuildType = $_
$Job = @{
name = "[$Platform-$Architecture-$BuildType]"
arch = $Architecture
build_type = $BuildType
os = $Platform
runner = switch ($Platform) {
"windows" { "windows-2022" }
{ @("macos", "ios", "iossimulator") -contains $_ } { "macos-15" }
{ @("linux", "android") -contains $_ } { "ubuntu-22.04" }
}
}
if ($Platform -Eq "macos" -And $Architecture -Eq "x86_64") {
$Job.runner = "macos-15-intel"
}
$Jobs += $Job
if ($Platform -Eq "linux") {
# default distro target
$Job["distro"] = "ubuntu-20.04"
$Job["name"] = "[$($Job["distro"])-$Architecture-$BuildType]"
$Job = $Job.Clone()
$Job["distro"] = "ubuntu-18.04"
$Job["name"] = "[$($Job["distro"])-$Architecture-$BuildType]"
$Jobs += $Job
$Job = $Job.Clone()
$Job["distro"] = "ubuntu-22.04"
$Job["name"] = "[$($Job["distro"])-$Architecture-$BuildType]"
$Jobs += $Job
}
}
}
}
echo "matrix=$(ConvertTo-JSON -Compress -InputObject @($Jobs))" >> $Env:GITHUB_OUTPUT
build:
name: ${{matrix.name}}
runs-on: ${{matrix.runner}}
needs: [generate-matrix]
concurrency:
group: conan-${{ needs.generate-matrix.outputs.conan_major_version }}-${{ github.ref }}-${{matrix.name}}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.generate-matrix.outputs.matrix-json) }}
steps:
- name: Check out ${{ github.repository }}
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
with:
image: tonistiigi/binfmt:qemu-v7.0.0-28 # https://github.com/docker/setup-qemu-action/issues/198
if: runner.os == 'Linux'
- name: Set up docker buildx
uses: docker/setup-buildx-action@v4
if: runner.os == 'Linux'
- name: Configure Windows runner
if: runner.os == 'Windows'
shell: pwsh
run: |
choco install --no-progress ninja
choco install --no-progress 7zip
choco install --no-progress python
choco install --no-progress vswhere
choco install --no-progress nasm
# https://github.com/actions/runner-images/issues/11926
choco install cmake --version 3.31.6 --force
echo "${Env:ProgramFiles}\NASM" | Out-File -FilePath $Env:GITHUB_PATH -Encoding UTF8 -Append
Invoke-WebRequest -Uri 'https://www.tortall.net/projects/yasm/releases/yasm-1.2.0-win64.exe' -OutFile 'yasm.exe'
Move-Item .\yasm.exe "${Env:ProgramFiles}\NASM\yasm.exe"
$SetupArgs = @{
VenvRoot = "$Env:RUNNER_TEMP\conan-venvs"
ShimDir = "$Env:RUNNER_TEMP\conan-bin"
NoUserPathUpdate = $true
}
if ('${{ needs.generate-matrix.outputs.conan_major_version }}' -eq '2') {
.\scripts\setup-conan-venvs.ps1 @SetupArgs -Conan2Version "${{ env.conan2_version }}" -SkipConan1
echo "CONAN_HOME=C:/tmp/.conan2" >> $Env:GITHUB_ENV
} else {
.\scripts\setup-conan-venvs.ps1 @SetupArgs -Conan1Version "${{ env.conan1_version }}" -SkipConan2
echo "CONAN_USER_HOME=C:/tmp" >> $Env:GITHUB_ENV
}
echo $PSVersionTable
- name: Configure macOS runner
if: runner.os == 'macOS'
uses: actions/setup-python@v6
with:
python-version: '3.10'
# Pin Xcode for every macOS job (device, simulator and x86_64) so the
# toolchain is deterministic. Silently falling back to the runner's
# default Xcode lets newer toolchains ship bitcode/SDKs that older
# consumers can't link (e.g. RelWithDebInfo LTO across mismatched
# Xcode versions), so fail loudly if the pinned version is missing.
- name: Select Xcode
if: runner.os == 'macOS'
run: |
XCODE_APP="/Applications/Xcode_${{ env.xcode_version }}.app"
if [ ! -d "$XCODE_APP" ]; then
echo "::error::$XCODE_APP is not installed on this runner. Installed Xcodes:"
ls -d /Applications/Xcode_*.app 2>/dev/null || true
exit 1
fi
sudo xcode-select --switch "$XCODE_APP"
xcodebuild -version
- name: Configure macOS runner
if: runner.os == 'macOS'
env:
CMAKE_OSX_DEPLOYMENT_TARGET: "10.12"
run: |
if brew help trust >/dev/null 2>&1; then
brew trust aws/tap azure/bicep || true
fi
brew install nasm yasm
if [ "${{ needs.generate-matrix.outputs.conan_major_version }}" = "2" ]; then
pwsh ./scripts/setup-conan-venvs.ps1 -Conan2Version "${{ env.conan2_version }}" -SkipConan1 -VenvRoot "$RUNNER_TEMP/conan-venvs" -ShimDir "$RUNNER_TEMP/conan-bin" -NoUserPathUpdate
echo "CONAN_HOME=/tmp/.conan2" >> $GITHUB_ENV
else
pwsh ./scripts/setup-conan-venvs.ps1 -Conan1Version "${{ env.conan1_version }}" -SkipConan2 -VenvRoot "$RUNNER_TEMP/conan-venvs" -ShimDir "$RUNNER_TEMP/conan-bin" -NoUserPathUpdate
echo "CONAN_USER_HOME=/tmp" >> $GITHUB_ENV
fi
sudo rm -rf /Library/Developer/CommandLineTools
- name: Configure Linux runner
if: runner.os == 'Linux'
run: |
sudo apt-get -o Acquire::Retries=3 update
sudo apt-get install ninja-build xz-utils nasm yasm python3 python3-pip python3-venv python3-wget python3-setuptools
# https://github.com/actions/runner-images/issues/11926
sudo apt-get update
sudo apt-get install cmake=3.22.1-1ubuntu1.22.04.2
sudo ln -sf /usr/bin/cmake /usr/local/bin/cmake
if [ "${{ needs.generate-matrix.outputs.conan_major_version }}" = "2" ]; then
pwsh ./scripts/setup-conan-venvs.ps1 -Conan2Version "${{ env.conan2_version }}" -SkipConan1 -VenvRoot "$RUNNER_TEMP/conan-venvs" -ShimDir "$RUNNER_TEMP/conan-bin" -NoUserPathUpdate
echo "CONAN_HOME=/tmp/.conan2" >> $GITHUB_ENV
else
pwsh ./scripts/setup-conan-venvs.ps1 -Conan1Version "${{ env.conan1_version }}" -SkipConan2 -VenvRoot "$RUNNER_TEMP/conan-venvs" -ShimDir "$RUNNER_TEMP/conan-bin" -NoUserPathUpdate
echo "CONAN_USER_HOME=/tmp" >> $GITHUB_ENV
fi
- name: Setup LLVM
uses: Devolutions/actions-public/setup-llvm@v1
if: runner.os == 'linux'
with:
version: "18.1.8"
- name: Configure Android NDK
if: matrix.os == 'android'
run: |
## Pin the cmake version for now, libpng builds are failing on Android x86-64
## Probably related to cmake 3.25 setting LINUX
## https://gitlab.kitware.com/cmake/cmake/-/issues/24196
## https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7963
pip3 install cmake==3.24.2
cmake --version
- name: Configure conan environment
shell: pwsh
run: |
if ('${{ needs.generate-matrix.outputs.conan_major_version }}' -eq '2') {
conan2 profile detect --force
} else {
conan1 config init
conan1 config install ./settings
conan1 remote disable conancenter
}
$ConanManifestTime = $(git log -1 --pretty=format:%ct)
echo "CONAN_MANIFEST_TIME=$ConanManifestTime" >> $Env:GITHUB_ENV
- name: Build conan packages
shell: pwsh
run: |
if ('${{ needs.generate-matrix.outputs.conan_major_version }}' -eq '2') {
if ("${{ matrix.distro }}") {
./scripts/build-conan2.ps1 -Platform ${{ matrix.os }} -Architecture ${{ matrix.arch }} -BuildType ${{ matrix.build_type }} -Distribution ${{ matrix.distro }}
} else {
./scripts/build-conan2.ps1 -Platform ${{ matrix.os }} -Architecture ${{ matrix.arch }} -BuildType ${{ matrix.build_type }}
}
} else {
if ("${{ matrix.distro }}") {
./build.ps1 -Platform ${{ matrix.os }} -Architecture ${{ matrix.arch }} -BuildType ${{ matrix.build_type }} -Distribution ${{ matrix.distro }}
} else {
./build.ps1 -Platform ${{ matrix.os }} -Architecture ${{ matrix.arch }} -BuildType ${{ matrix.build_type }}
}
}
- name: Package conan cache
id: package-conan-cache
shell: pwsh
run: |
if ("${{ matrix.distro }}") {
$PACKAGE_NAME="conan${{ needs.generate-matrix.outputs.conan_major_version }}-${{ matrix.arch }}-${{ matrix.distro }}-${{ matrix.build_type }}"
} else {
$PACKAGE_NAME="conan${{ needs.generate-matrix.outputs.conan_major_version }}-${{ matrix.arch }}-${{ matrix.os }}-${{ matrix.build_type }}"
}
if ('${{ needs.generate-matrix.outputs.conan_major_version }}' -eq '2') {
conan2 cache clean '*' --source --build --download --temp --backup-sources
$ConanHome = $Env:CONAN_HOME
if ([string]::IsNullOrWhiteSpace($ConanHome)) {
$ConanHome = Join-Path $HOME ".conan2"
}
$ConanHomeParent = Split-Path $ConanHome -Parent
$ConanHomeName = Split-Path $ConanHome -Leaf
tar -czf "${PACKAGE_NAME}.tar.gz" -C "$ConanHomeParent" "$ConanHomeName"
} else {
conan1 remove --locks
$CONAN_DATA = Join-Path $Env:CONAN_USER_HOME ".conan" "data"
$RemoveList = Get-ChildItem "${CONAN_DATA}" -Include @("build","source") -Directory -Depth 4 -Recurse -Name
$RemoveList | ForEach-Object { Remove-Item -Path "$CONAN_DATA/$_" -Recurse -Force }
$ConanManifests = Get-ChildItem $CONAN_DATA -Recurse -Include "conanmanifest.txt"
$ConanManifestTime = $Env:CONAN_MANIFEST_TIME
foreach ($ManifestFile in $ConanManifests) {
$Manifest = Get-Content $ManifestFile
$Manifest[0] = $ConanManifestTime
$Manifest | Out-File $ManifestFile
}
tar -czf "${PACKAGE_NAME}.tar.gz" -C "$Env:CONAN_USER_HOME" ".conan"
}
echo "package_name=$PACKAGE_NAME" >> $Env:GITHUB_OUTPUT
- name: Upload conan cache
uses: actions/upload-artifact@v7
with:
name: ${{ steps.package-conan-cache.outputs.package_name }}
path: ${{ steps.package-conan-cache.outputs.package_name }}.tar.gz
publish:
needs:
- generate-matrix
- build
if: github.event_name != 'schedule'
uses: ./.github/workflows/conan-publish.yml
with:
conan_major_version: ${{ needs.generate-matrix.outputs.conan_major_version }}
dry_run: ${{ inputs.publish_dry_run }}
secrets: inherit
notify:
name: Notify failure
runs-on: ubuntu-latest
if: ${{ always() && contains(needs.*.result, 'failure') && github.event_name == 'schedule' }}
needs:
- generate-matrix
- build
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_ARCHITECTURE }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
steps:
- name: Send slack notification
id: slack
uses: slackapi/slack-github-action@v1.26.0
with:
payload: |
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*${{ github.repository }}* :fire::fire::fire::fire::fire: \n The scheduled build for *${{ github.repository }}* is <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|broken>"
}
}
]
}