Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions .github/actions/boost/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
name: Build Boost
description: Download and build Boost C++ libraries (Windows/MSVC).
inputs:
version:
description: Boost version to build (e.g. 1.86.0)
required: true
architecture:
description: Target architecture (x86, x64 or arm64)
required: true
toolset:
description: |
MSVC toolset version passed to b2 (e.g. 14.1 for v141, 14.3 for v143).
required: true
libraries:
description: Space-separated list of Boost libraries (without the `--with-` prefix).
required: true
link:
description: shared or static
required: false
default: shared
runtime-link:
description: shared or static
required: false
default: shared
target_folder:
description: |
Directory (relative to workspace) used as both the unpacked Boost source
tree and the cache key. Defaults to `tmp/boost`. Use a unique value for
each independent build (e.g. `tmp/static_boost`).
required: false
default: tmp/boost
python-version:
description: |
Python major.minor (e.g. `3.11`). Required if `python` is in `libraries`
*and* you want to override the auto-detected interpreter (e.g. when
cross-compiling). Combined with `python-include` / `python-libs` it
writes a `user-config.jam` so b2 picks up the right headers/libs.
required: false
default: ''
python-include:
description: Python include directory for boost.python (cross-compile).
required: false
default: ''
python-libs:
description: Python import library directory for boost.python (cross-compile).
required: false
default: ''

outputs:
root:
description: Root Boost directory (Windows path).
value: ${{ steps.path.outputs.root }}
root_unix:
description: Root Boost directory (forward-slash path).
value: ${{ steps.path.outputs.root_unix }}
librarydir:
description: Directory containing built Boost libraries (Windows path).
value: ${{ steps.path.outputs.librarydir }}
librarydir_unix:
description: Directory containing built Boost libraries (forward-slash path).
value: ${{ steps.path.outputs.librarydir_unix }}

runs:
using: composite
steps:

- id: cache
uses: actions/cache@v3
with:
key: ${{ runner.os }}-boost-${{ inputs.version }}-${{ inputs.architecture }}-${{ inputs.toolset }}-${{ inputs.link }}-${{ inputs.runtime-link }}-py${{ inputs.python-version }}-${{ hashFiles('.github/actions/boost/action.yaml') }}-${{ inputs.libraries }}
path: |
${{ inputs.target_folder }}

- id: setup
shell: pwsh
run: |
$arch = '${{ inputs.architecture }}'
switch ($arch) {
'x86' { $b2_arch = @('address-model=32'); $stage = 'x86' }
'x64' { $b2_arch = @('address-model=64'); $stage = 'x64' }
'arm64' { $b2_arch = @('architecture=arm', 'address-model=64'); $stage = 'arm64' }
default { Write-Error "Unsupported architecture '$arch'"; exit 1 }
}

$version = '${{ inputs.version }}'
$underscore = $version.Replace('.', '_')
$stagedir = "stage/$stage/Release"

echo "b2_arch=$($b2_arch -join ' ')" >> $env:GITHUB_OUTPUT
echo "stage=$stage" >> $env:GITHUB_OUTPUT
echo "stagedir=$stagedir" >> $env:GITHUB_OUTPUT
echo "version_underscore=$underscore" >> $env:GITHUB_OUTPUT

- name: Download Boost
if: steps.cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$version = '${{ inputs.version }}'
$underscore = '${{ steps.setup.outputs.version_underscore }}'
$target = '${{ inputs.target_folder }}'
$parent = Split-Path $target
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Force -Path $parent | Out-Null }
if (Test-Path $target) { Remove-Item -Recurse -Force $target }

$archive = Join-Path $env:RUNNER_TEMP "boost_$underscore.tar.gz"
if (-not (Test-Path $archive)) {
$url = "https://archives.boost.io/release/$version/source/boost_$underscore.tar.gz"
Write-Host "Downloading $url"
Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $archive
}

Write-Host "Extracting $archive to $parent"
tar -xzf $archive -C $parent
Move-Item (Join-Path $parent "boost_$underscore") $target

- name: Bootstrap b2
if: steps.cache.outputs.cache-hit != 'true'
shell: cmd
working-directory: ${{ inputs.target_folder }}
run: |
if not exist b2.exe call bootstrap.bat

- name: Build Boost
if: steps.cache.outputs.cache-hit != 'true'
shell: pwsh
working-directory: ${{ inputs.target_folder }}
run: |
$ErrorActionPreference = 'Stop'
$libs = '${{ inputs.libraries }}'.Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries) |
ForEach-Object { "--with-$_" }
$arch = '${{ steps.setup.outputs.b2_arch }}'.Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)
$b2args = @("toolset=msvc-${{ inputs.toolset }}") + $arch + @(
'variant=release',
"link=${{ inputs.link }}",
"runtime-link=${{ inputs.runtime-link }}",
'threading=multi',
'--layout=system',
"--stagedir=${{ steps.setup.outputs.stagedir }}"
)

# Optional: user-config.jam for cross-compiled boost.python.
$py_version = '${{ inputs.python-version }}'
$py_include = '${{ inputs.python-include }}'
$py_libs = '${{ inputs.python-libs }}'
if ($py_version -and $py_include -and $py_libs) {
$inc_fwd = $py_include.Replace('\','/')
$lib_fwd = $py_libs.Replace('\','/')
$jam = "using python : $py_version : python : `"$inc_fwd`" : `"$lib_fwd`" ;`n"
$jam_path = Join-Path (Resolve-Path '.').Path 'user-config.jam'
Set-Content -Path $jam_path -Value $jam -Encoding ASCII
Write-Host "Wrote $jam_path :"
Get-Content $jam_path
$b2args += "--user-config=$jam_path"
}

$b2args += $libs + @('-d0', 'warnings=off', 'stage')
Write-Host "Running: b2 $($b2args -join ' ')"
& .\b2.exe @b2args
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- id: path
shell: pwsh
run: |
$root = (Resolve-Path '${{ inputs.target_folder }}').Path
$lib = Join-Path $root '${{ steps.setup.outputs.stagedir }}/lib'
echo "root=$root" >> $env:GITHUB_OUTPUT
echo "root_unix=$($root.Replace('\','/'))" >> $env:GITHUB_OUTPUT
echo "librarydir=$lib" >> $env:GITHUB_OUTPUT
echo "librarydir_unix=$($lib.Replace('\','/'))" >> $env:GITHUB_OUTPUT


21 changes: 21 additions & 0 deletions .github/workflows/build-feature.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@ jobs:
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
build-client-arm64:
needs: get-version
uses: ./.github/workflows/build-rust.yml
with:
os: windows-latest
arch: arm64
version: ${{ needs.get-version.outputs.version }}
secrets:
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
build-server-arm64:
needs: [get-version, build-client-arm64, create-test-bundle]
uses: ./.github/workflows/build-windows.yml
with:
architecture: arm64
version: ${{ needs.get-version.outputs.version }}
secrets:
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
build-client-ubuntu-x64:
needs: get-version
uses: ./.github/workflows/build-rust.yml
Expand Down
111 changes: 85 additions & 26 deletions .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ on:

env:
PYTHON_VERSION: 3.11
# Exact ARM64 Python version pulled from the python.org NuGet feed when
# cross-compiling for arm64 (we need the matching python311.lib + headers).
PYTHON_ARM64_VERSION: 3.11.9
OPENSSL_VERSION: 3.5.4
PROTOBUF_VERSION: 21.12
BOOST_VERSION: 1.86.0
Expand Down Expand Up @@ -178,40 +181,96 @@ jobs:
with:
version: ${{ ENV.MINIZ_VERSION }}

# ----- Boost build -----
# Built locally via .github/actions/boost (no external action) so that
# ARM64 cross-compilation, toolset selection and caching are all under
# our control.
#
# For arm64 we install the official `pythonarm64` NuGet package and
# point boost.python at its headers and import library so the resulting
# boost_python311.dll links against ARM64 python311.lib. The interpreter
# itself is never executed during the build - host x64 Python is still
# used for everything that runs locally (mk_pyzip.py, etc.).
- name: Install ARM64 Python (cross-compile target)
id: arm64_python
if: inputs.architecture == 'arm64'
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$version = '${{ env.PYTHON_ARM64_VERSION }}'
$dest = Join-Path $env:GITHUB_WORKSPACE 'tmp/python-arm64'
New-Item -ItemType Directory -Force -Path $dest | Out-Null
nuget install pythonarm64 -Version $version -OutputDirectory $dest -ExcludeVersion -DependencyVersion Ignore
$root = Join-Path $dest 'pythonarm64\tools'
$include = Join-Path $root 'include'
$libs = Join-Path $root 'libs'
if (-not (Test-Path $include)) { Write-Error "ARM64 Python include not found at $include"; exit 1 }
if (-not (Test-Path $libs)) { Write-Error "ARM64 Python libs not found at $libs"; exit 1 }
$major_minor = ($version -split '\.')[0..1] -join '.'
echo "root=$root" >> $env:GITHUB_OUTPUT
echo "include=$include" >> $env:GITHUB_OUTPUT
echo "libs=$libs" >> $env:GITHUB_OUTPUT
echo "root_unix=$($root.Replace('\','/'))" >> $env:GITHUB_OUTPUT
echo "major_minor=$major_minor" >> $env:GITHUB_OUTPUT

- name: Build Boost (static)
id: static_boost
uses: mickem/build-boost@v1
uses: ./.github/actions/boost
with:
version: ${{ ENV.BOOST_VERSION }}
version: ${{ env.BOOST_VERSION }}
architecture: ${{ inputs.architecture }}
toolset: ${{ steps.setup.outputs.vs_toolset }}
libraries: system filesystem
platform: ${{ inputs.architecture }}
configuration: Release
static: 1
static-runtime: 1
directory: ${{ runner.workspace }}/static_boost

- name: Build Boost (regular)
id: boost
uses: mickem/build-boost@v1
link: static
runtime-link: static
target_folder: tmp/static_boost

- name: Build Boost (regular, x86/x64)
id: boost_xx
if: inputs.architecture != 'arm64'
uses: ./.github/actions/boost
with:
version: ${{ env.BOOST_VERSION }}
architecture: ${{ inputs.architecture }}
toolset: ${{ steps.setup.outputs.vs_toolset }}
libraries: system filesystem thread regex date_time program_options python chrono json
link: shared
runtime-link: shared
target_folder: tmp/boost

- name: Build Boost (regular, arm64)
id: boost_arm64
if: inputs.architecture == 'arm64'
uses: ./.github/actions/boost
with:
version: ${{ ENV.BOOST_VERSION }}
version: ${{ env.BOOST_VERSION }}
architecture: ${{ inputs.architecture }}
toolset: ${{ steps.setup.outputs.vs_toolset }}
libraries: system filesystem thread regex date_time program_options python chrono json
platform: ${{ inputs.architecture }}
configuration: Release

link: shared
runtime-link: shared
target_folder: tmp/boost
python-version: ${{ steps.arm64_python.outputs.major_minor }}
python-include: ${{ steps.arm64_python.outputs.include }}
python-libs: ${{ steps.arm64_python.outputs.libs }}

- id: paths
run: |
$path_unix="${{ steps.boost.outputs.root }}".replace('\','/')
echo "boost_root=$path_unix" >> $env:GITHUB_OUTPUT
$path_unix="${{ steps.boost.outputs.librarydir }}".replace('\','/')
echo "boost_librarydir=$path_unix" >> $env:GITHUB_OUTPUT
$path_unix="${{ steps.static_boost.outputs.root }}".replace('\','/')
echo "static_boost_root=$path_unix" >> $env:GITHUB_OUTPUT
$path_unix="${{ steps.static_boost.outputs.librarydir }}".replace('\','/')
echo "static_boost_librarydir=$path_unix" >> $env:GITHUB_OUTPUT
$path_unix="${{ env.Python_ROOT_DIR }}".replace('\','/')
echo "python_path=$path_unix" >> $env:GITHUB_OUTPUT
shell: pwsh
run: |
if ('${{ inputs.architecture }}' -eq 'arm64') {
$boost_root_unix = '${{ steps.boost_arm64.outputs.root_unix }}'
$boost_librarydir_unix = '${{ steps.boost_arm64.outputs.librarydir_unix }}'
$python_path = '${{ steps.arm64_python.outputs.root_unix }}'
} else {
$boost_root_unix = '${{ steps.boost_xx.outputs.root_unix }}'
$boost_librarydir_unix = '${{ steps.boost_xx.outputs.librarydir_unix }}'
$python_path = '${{ env.Python_ROOT_DIR }}'.Replace('\','/')
}
echo "boost_root=$boost_root_unix" >> $env:GITHUB_OUTPUT
echo "boost_librarydir=$boost_librarydir_unix" >> $env:GITHUB_OUTPUT
echo "static_boost_root=${{ steps.static_boost.outputs.root_unix }}" >> $env:GITHUB_OUTPUT
echo "static_boost_librarydir=${{ steps.static_boost.outputs.librarydir_unix }}" >> $env:GITHUB_OUTPUT
echo "python_path=$python_path" >> $env:GITHUB_OUTPUT

- uses: DamianReeves/write-file-action@master
name: Write NSClient++ cmake config
Expand Down
Loading