Skip to content
Draft
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
227 changes: 25 additions & 202 deletions .github/actions/tket-c-api/action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: "Install tket-c-api C++ library"
description: "Retrieve cached tket-c-api C++ library or build if needed."
description: "Download pre-built tket-c-api library from Artifactory."

inputs:
install-path:
Expand All @@ -12,221 +12,44 @@ inputs:
runs:
using: composite
steps:
- name: Attempt to retrieve cached tket-c-api
uses: actions/cache/restore@v4
id: cache
with:
path: ${{ inputs.install-path }}
key: ${{ runner.os }}-${{ inputs.target }}-${{ hashFiles('tket1-passes/conanfile.txt') }}-${{ hashFiles('tket1-passes/conan-profiles/**') }}-${{ hashFiles('.github/actions/tket-c-api/action.yml') }}

- name: Install conan
if: steps.cache.outputs.cache-hit != 'true'
uses: conan-io/setup-conan@v1
with:
cache_packages: true

- name: Set up conan remote
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: |
conan remote add tket-libs https://quantinuumsw.jfrog.io/artifactory/api/conan/tket1-libs --index 0

- name: Install cross-compilation toolchains
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: |
TARGET="${{ inputs.target }}"

# Install cross-compilation toolchains based on target
case "$TARGET" in
aarch64-unknown-linux-gnu|aarch64-unknown-linux-musl)
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
;;
armv7-unknown-linux-gnueabihf|armv7-unknown-linux-musleabihf)
sudo apt-get update
sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
;;
i686-unknown-linux-gnu|i686-unknown-linux-musl)
sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib
;;
x86_64-unknown-linux-gnu|x86_64-unknown-linux-musl)
# Native compilation, no cross-compiler needed
;;
*)
# For other targets, check if cross-compilation is needed
if [[ "$TARGET" == *"linux"* ]] && [[ "$TARGET" != *"x86_64"* ]]; then
echo "Warning: Unknown Linux target $TARGET, cross-compilation may fail"
fi
;;
esac
conan profile detect --force || true
conan remote add tket-libs https://quantinuumsw.jfrog.io/artifactory/api/conan/tket1-libs --index 0 || true

- name: Determine conan profile
if: steps.cache.outputs.cache-hit != 'true'
id: conan-profile
- name: Download and install tket-c-api from Artifactory
shell: bash
run: |
TARGET="${{ inputs.target }}"
PROFILE=""

case "$TARGET" in
aarch64-unknown-linux-gnu)
PROFILE="linux-armv8-gcc14"
;;
aarch64-unknown-linux-musl)
PROFILE="linux-armv8-gcc14"
;;
armv7-unknown-linux-gnueabihf)
PROFILE="linux-armv7-gcc14"
;;
armv7-unknown-linux-musleabihf)
PROFILE="linux-armv7-gcc14"
;;
i686-unknown-linux-gnu)
PROFILE="linux-i686-gcc14"
;;
i686-unknown-linux-musl)
PROFILE="linux-i686-gcc14"
;;
x86_64-unknown-linux-gnu)
PROFILE="linux-x86_64-gcc13"
;;
x86_64-unknown-linux-musl)
PROFILE="linux-x86_64-gcc13"
;;
x86_64-pc-windows-msvc)
PROFILE="windows-2025"
;;
*)
# For non-Linux targets or if no match, let conan generate a default profile
if [[ "$TARGET" == *"apple"* ]] && [[ "$TARGET" == *"aarch64"* ]]; then
PROFILE="macos-15"
elif [[ "$TARGET" == *"apple"* ]] && [[ "$TARGET" == *"x86_64"* ]]; then
PROFILE="macos-15-intel"
elif [[ "$TARGET" == *"windows"* ]] && [[ "$TARGET" == *"msvc"* ]]; then
PROFILE="windows-2025"
elif [[ "$TARGET" == *"armv8"* ]] || [[ "$TARGET" == *"aarch64"* ]]; then
PROFILE="linux-armv8-gcc14"
elif [[ "$TARGET" == *"x86_64"* ]]; then
PROFILE="linux-x86_64-gcc13"
else
PROFILE=""
fi
;;
esac

if [ -z "$PROFILE" ]; then
echo "No profile found for target: $TARGET, using default"
echo "profile=" >> $GITHUB_OUTPUT
echo "use_profile=false" >> $GITHUB_OUTPUT
else
# Check if profile exists in tket1-passes/conan-profiles directory
if [ -f "tket1-passes/conan-profiles/$PROFILE" ]; then
PROFILE_PATH="tket1-passes/conan-profiles/$PROFILE"
echo "profile=$PROFILE_PATH" >> $GITHUB_OUTPUT
echo "use_profile=true" >> $GITHUB_OUTPUT
echo "Selected profile: $PROFILE_PATH"
else
echo "Profile $PROFILE not found in tket1-passes/conan-profiles/, using default"
echo "profile=" >> $GITHUB_OUTPUT
echo "use_profile=false" >> $GITHUB_OUTPUT
fi
fi

- name: Build and install tket-c-api
if: steps.cache.outputs.cache-hit != 'true' && runner.os != 'Windows'
shell: bash
run: |
cd tket1-passes
mkdir -p ${{ inputs.install-path }}

# Set up cross-compilation environment variables if needed
TARGET="${{ inputs.target }}"
export CC=""
export CXX=""

case "$TARGET" in
aarch64-unknown-linux-gnu|aarch64-unknown-linux-musl)
export CC="aarch64-linux-gnu-gcc"
export CXX="aarch64-linux-gnu-g++"
;;
armv7-unknown-linux-gnueabihf|armv7-unknown-linux-musleabihf)
export CC="arm-linux-gnueabihf-gcc"
export CXX="arm-linux-gnueabihf-g++"
;;
i686-unknown-linux-gnu|i686-unknown-linux-musl)
# For i686, conan profile with arch=x86 should handle -m32 automatically
# No need to set CC/CXX explicitly
;;
esac

if [ -n "$CC" ]; then
echo "Using cross-compiler: CC=$CC, CXX=$CXX"
# Verify cross-compiler is available and working
$CC --version || echo "Warning: Failed to get $CC version"
# Read the version from conanfile.txt
TKET_C_API_VERSION=$(grep "tket-c-api/" tket1-passes/conanfile.txt | cut -d'/' -f2 | cut -d'@' -f1)
echo "Installing tket-c-api version: $TKET_C_API_VERSION"

# Install the pre-built tket-c-api package from Artifactory
conan install --requires="tket-c-api/${TKET_C_API_VERSION}@tket/stable" \
-o "tket-c-api/*:shared=True" \
--build=missing \
--format=json > conan_install.json

# Extract the package folder path from the conan output
PACKAGE_FOLDER=$(cat conan_install.json | python3 -c "import sys, json; nodes = json.load(sys.stdin)['graph']['nodes']; print(next((v['package_folder'] for k, v in nodes.items() if 'tket-c-api' in v.get('ref', '')), ''))")
echo "Package folder: $PACKAGE_FOLDER"

if [ -z "$PACKAGE_FOLDER" ] || [ "$PACKAGE_FOLDER" = "null" ]; then
echo "Error: Could not find tket-c-api package folder"
exit 1
fi

# Build conan install command
CONAN_CMD="conan install . --build=missing --options=\"tket-c-api/*:shared=True\""
# Copy the library files to the expected location
mkdir -p "${{ inputs.install-path }}"
cp -r "$PACKAGE_FOLDER/"* "${{ inputs.install-path }}/"

if [ "${{ steps.conan-profile.outputs.use_profile }}" == "true" ]; then
CONAN_CMD="$CONAN_CMD --profile=${{ github.workspace }}/${{ steps.conan-profile.outputs.profile }}"
echo "Using profile: ${{ steps.conan-profile.outputs.profile }}"
else
echo "Using default conan profile"
fi

CONAN_CMD="$CONAN_CMD --format=json"
echo "Running: $CONAN_CMD"

CONAN_OUTPUT=$(eval $CONAN_CMD)
CONAN_LIB_FOLDER=$(echo "$CONAN_OUTPUT" | jq -r ".graph.nodes.\"1\".package_folder")
echo "CONAN_LIB_FOLDER: $CONAN_LIB_FOLDER"
cp -r "$CONAN_LIB_FOLDER/"* "${{ inputs.install-path }}/"

- name: Build and install tket-c-api (Windows)
if: steps.cache.outputs.cache-hit != 'true' && runner.os == 'Windows'
shell: pwsh
run: |
Set-Location tket1-passes
New-Item -ItemType Directory -Force -Path "${{ inputs.install-path }}" | Out-Null

# Build conan install command
$conanCmd = "conan install . --build=missing --options=`"tket-c-api/*:shared=True`""

if ("${{ steps.conan-profile.outputs.use_profile }}" -eq "true") {
$profilePath = "${{ github.workspace }}/${{ steps.conan-profile.outputs.profile }}"
$conanCmd = "$conanCmd --profile=$profilePath"
Write-Host "Using profile: $profilePath"
} else {
Write-Host "Using default conan profile"
}

Write-Host "CMake option CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=ON will be passed to the build"

$conanCmd = "$conanCmd --format=json"
Write-Host "Running: $conanCmd"

$conanOutput = Invoke-Expression $conanCmd
$conanJson = $conanOutput | ConvertFrom-Json
$conanLibFolder = $conanJson.graph.nodes.'1'.package_folder

Write-Host "CONAN_LIB_FOLDER: $conanLibFolder"
Write-Host "Files in CONAN_LIB_FOLDER:"

# Copy the built library files to the install path
Get-ChildItem -Path "$conanLibFolder" -Recurse -File | ForEach-Object { Write-Output $_.FullName }
Copy-Item -Recurse -Force -Path "$conanLibFolder\*" -Destination "${{ inputs.install-path }}"
Write-Host "tket-c-api library files:"
Get-ChildItem -Path "${{ inputs.install-path }}" -Recurse -File | ForEach-Object { Write-Output $_.FullName }

- name: Upload compiled library to cache
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: ${{ inputs.install-path }}
key: ${{ steps.cache.outputs.cache-primary-key }}
echo "tket-c-api installed to ${{ inputs.install-path }}"

- name: List tket-c-api library files
shell: bash
Expand Down
16 changes: 7 additions & 9 deletions .github/workflows/build_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ permissions:
env:
UV_VERSION: "0.9.7"
UV_FROZEN: 1
# Path to the cached tket-c-api library
# When this envvar is set, the `./.github/actions/tket-c-api` action **must** be run to fetch the artifacts
# This config is not required, but speeds up the build by caching the tket-c-api library
# The alternative is to install conan and remove the env var
TKET_C_API_PATH: "${{ github.workspace }}/tket-c-api"
LD_LIBRARY_PATH: ${{ github.workspace }}/tket-c-api/lib

jobs:
# Check if changes were made to the relevant files.
Expand All @@ -48,13 +42,17 @@ jobs:
with:
submodules: true

- name: Install conan
uses: conan-io/setup-conan@v1
with:
cache_packages: true
- uses: extractions/setup-just@v3
with:
just-version: "1.40.0"
- name: Install tket-c-api library
uses: ./.github/actions/tket-c-api
- name: Install conan
uses: conan-io/setup-conan@v1
with:
install-path: ${{ env.TKET_C_API_PATH }}
cache_packages: true

- name: Install uv
uses: astral-sh/setup-uv@v7
Expand Down
Loading
Loading