diff --git a/.github/actions/tket-c-api/action.yml b/.github/actions/tket-c-api/action.yml index 4be30167d..c37646463 100644 --- a/.github/actions/tket-c-api/action.yml +++ b/.github/actions/tket-c-api/action.yml @@ -6,9 +6,13 @@ inputs: description: "Path where the tket-c-api library will be installed" required: true target: - description: "Target platform, used for caching" + description: "Target platform" required: false default: ${{ runner.arch }} + compatibility: + description: "Generic compatibility, e.g. 'manylinux_2_28' on linux or '11.0' on macos." + required: false + default: 'N/A' runs: using: composite steps: @@ -17,211 +21,18 @@ runs: 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') }} + key: ${{ runner.os }}-${{ inputs.target }}-${{ hashFiles('tket1-passes/conanfile.txt') }} - - name: Install conan + - name: Run install script 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 - - - name: Determine conan profile - if: steps.cache.outputs.cache-hit != 'true' - id: conan-profile - 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-gcc14" - ;; - x86_64-unknown-linux-musl) - PROFILE="linux-x86_64-gcc14" - ;; - 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-gcc14" - 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" - fi - - # Build conan install command - CONAN_CMD="conan install . --build=missing --options=\"tket-c-api/*:shared=True\"" - - 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 } + tket1-passes/scripts/build.sh \ + "${{ inputs.target }}" \ + "${{ inputs.compatibility }}" \ + "${{ inputs.install-path }}" - - name: Upload compiled library to cache + - name: Save the cached tket-c-api if: steps.cache.outputs.cache-hit != 'true' uses: actions/cache/save@v4 with: diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml index 86cc23d25..1c49b1ebd 100644 --- a/.github/workflows/build_docs.yml +++ b/.github/workflows/build_docs.yml @@ -55,6 +55,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - name: Install uv uses: astral-sh/setup-uv@v7 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21f792c62..0fbde7845 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - name: Check formatting run: cargo fmt -- --check - name: Install LLVM and Clang @@ -103,6 +105,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - name: Install Python ${{ env.PYTHON_HIGHEST }} run: uv python install ${{ env.PYTHON_HIGHEST }} - name: Setup dependencies @@ -130,6 +134,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - uses: cargo-bins/cargo-binstall@main - name: Install cargo-codspeed run: cargo binstall cargo-codspeed --force @@ -163,6 +169,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - uses: taiki-e/install-action@nextest - name: Build with no features run: cargo nextest r --verbose -p tket -p tket-py -p tket-qsystem --no-default-features --no-run @@ -192,6 +200,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - uses: taiki-e/install-action@nextest - name: Build with all features run: cargo nextest r --verbose --workspace --all-features --no-run @@ -226,6 +236,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - name: Configure default rust toolchain run: rustup override set ${{steps.toolchain.outputs.name}} - uses: taiki-e/install-action@nextest @@ -260,6 +272,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - name: Install cargo-llvm-cov uses: taiki-e/install-action@cargo-llvm-cov - name: Run tests with coverage instrumentation @@ -307,6 +321,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - uses: cargo-bins/cargo-binstall@main - name: Install cargo-minimal-versions run: | @@ -348,6 +364,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - name: Install Python ${{ env.PYTHON_LOWEST }} run: uv python install ${{ env.PYTHON_LOWEST }} - name: Setup dependencies diff --git a/.github/workflows/python-wheels.yml b/.github/workflows/python-wheels.yml index a5028a276..fd1531ee9 100644 --- a/.github/workflows/python-wheels.yml +++ b/.github/workflows/python-wheels.yml @@ -65,45 +65,36 @@ jobs: # Each entry defines: # - runner: The github runner to use for the build. # - target: The target platform used when building the rust code. - # - manylinux: (optional) If doing manylinux-compatible wheels, - # the manylinux version to use. Setting this option causes the wheels - # to be built with zig. - # - test-wheels: Whether to test installing the wheels. - # This is only done when the target platform matches the runner platform. - # - # Note that platform support is limited by the pytket wheels' availability. - # Since we have it as a dependency, wheels built for other platforms will be unusable. + # - compatibility: target-specific compatibility option, e.g.: + # - manylinux/musllinux for ubuntu + # - MACOSX_DEPLOYMENT_TARGET for macos + # - c library target for windows (currently only msvc supported) platform: # ---------------- Linux - # aarch64 cross-compilation with maturin was causing linking issues - # (it doesn't seem to be using zig even though we set --zig) - # so it's temporarily disabled - #- runner: ubuntu-24.04 - # target: aarch64-unknown-linux-gnu - # manylinux: "manylinux2014" - #- runner: ubuntu-24.04 - # target: aarch64-unknown-linux-musl - # manylinux: "musllinux_1_2" + - runner: ubuntu-24.04-arm + target: aarch64-unknown-linux-gnu + compatibility: manylinux_2_28 + - runner: ubuntu-24.04-arm + target: aarch64-unknown-linux-musl + compatibility: musllinux_1_2 - runner: ubuntu-24.04 target: x86_64-unknown-linux-gnu - manylinux: "manylinux2014" - test-wheels: true + compatibility: manylinux_2_28 - runner: ubuntu-24.04 target: x86_64-unknown-linux-musl - manylinux: "musllinux_1_2" + compatibility: musllinux_1_2 # ---------------- Mac - runner: macos-14 target: aarch64-apple-darwin - test-wheels: true - macos-compatibility: "13.0" + compatibility: "13.0" - runner: macos-15-intel target: x86_64-apple-darwin - test-wheels: true - macos-compatibility: "15.0" + compatibility: "15.0" # ---------------- Windows - runner: windows-2025 target: x86_64-pc-windows-msvc - test-wheels: true + compatibility: msvc + steps: - uses: actions/checkout@v5 - uses: mozilla-actions/sccache-action@v0.0.9 @@ -115,7 +106,9 @@ jobs: uses: astral-sh/setup-uv@v7 with: version: ${{ env.UV_VERSION }} + python-version: ${{ env.PYTHON_VERSION }} enable-cache: true + - name: Install LLVM and Clang uses: KyleMayes/install-llvm-action@v2 with: @@ -145,7 +138,7 @@ jobs: echo "TKET_C_API_PATH=$WORKSPACE/tket-c-api" >> $GITHUB_ENV echo "$WORKSPACE/tket-c-api/lib" >> $GITHUB_PATH echo "DYLD_LIBRARY_PATH=$WORKSPACE/tket-c-api/lib" >> $GITHUB_ENV - echo "MACOSX_DEPLOYMENT_TARGET=${{ matrix.platform.macos-compatibility }}" >> $GITHUB_ENV + echo "MACOSX_DEPLOYMENT_TARGET=${{ matrix.platform.compatibility }}" >> $GITHUB_ENV ;; Linux) echo "tket_c_api_path=$WORKSPACE/tket-c-api" >> $GITHUB_OUTPUT @@ -159,55 +152,9 @@ jobs: with: install-path: ${{ steps.tket-paths.outputs.tket_c_api_path }} target: ${{ matrix.platform.target }} + compatibility: ${{ matrix.platform.compatibility }} - - uses: mlugg/setup-zig@v2 - if: ${{ matrix.platform.manylinux }} - - - name: Set compatibility flag - id: compatibility-flag - shell: bash - run: | - if [ -n "${{ matrix.platform.manylinux }}" ]; then - WITH_ZIG_FLAG="--with ziglang --with maturin[zig]" - COMPATIBILITY_FLAG="--compatibility ${{ matrix.platform.manylinux }} --zig" - else - WITH_ZIG_FLAG="" - COMPATIBILITY_FLAG="" - fi - echo "COMPATIBILITY_FLAG: $COMPATIBILITY_FLAG" - echo "WITH_ZIG_FLAG: $WITH_ZIG_FLAG" - echo "COMPATIBILITY_FLAG=$COMPATIBILITY_FLAG" >> "$GITHUB_OUTPUT" - echo "WITH_ZIG_FLAG=$WITH_ZIG_FLAG" >> "$GITHUB_OUTPUT" - - - name: Check tket-c-api shared library - shell: bash - run: | - echo "tket-c-api files:" - find $TKET_C_API_PATH -type f - find $TKET_C_API_PATH -type f -name "*.so" | while IFS= read -r sofile; do - echo "======= objdump -f $sofile =======" - objdump -f "$sofile" || echo "objdump failed for $sofile" - echo "======= readelf -h $sofile =======" - readelf -h "$sofile" 2>/dev/null | head -20 || echo "readelf failed for $sofile" - echo "======= file $sofile =======" - file "$sofile" || echo "file failed for $sofile" - echo - done - find $TKET_C_API_PATH -type f -name "*.dylib" | while IFS= read -r dylibfile; do - echo "======= otool -L $dylibfile =======" - otool -L "$dylibfile" || echo "otool failed for $dylibfile" - echo "======= file $dylibfile =======" - file "$dylibfile" || echo "file failed for $dylibfile" - echo - done - find $TKET_C_API_PATH -type f -name "*.lib" | while IFS= read -r libfile; do - echo "======= Checking Windows library: $libfile =======" - echo "======= file $libfile =======" - file "$libfile" || echo "file failed for $libfile" - echo - done - - - name: Copy DLL to package directory (Windows) + - name: Copy tket-c-api DLL to package directory (Windows) if: runner.os == 'Windows' shell: bash run: | @@ -222,31 +169,33 @@ jobs: fi - name: Build wheels - shell: bash - run: | - cd ${{ env.MODULE_DIR }} - uv run --python ${{ env.PYTHON_VERSION }} \ - ${{ steps.compatibility-flag.outputs.WITH_ZIG_FLAG }} \ - maturin build ${{ steps.compatibility-flag.outputs.COMPATIBILITY_FLAG }} \ - --release \ - --out ../dist \ - --target ${{ matrix.platform.target }} \ - --strip + uses: PyO3/maturin-action@v1 + with: + working-directory: ${{ env.MODULE_DIR }} + target: ${{ matrix.platform.target }} + manylinux: ${{ matrix.platform.compatibility }} + args: --release --out ../dist --strip -i ${{ env.PYTHON_VERSION }} + docker-options: -e TKET_C_API_PATH + before-script-linux: + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$TKET_C_API_PATH/lib:/home/runner/work/tket2/tket2/llvm/lib"; + sccache: true - - name: Build free-threaded wheels - # TODO: pytket is a required dependency of tket-py, but it doesn't build free-threaded wheels yet - if: false - shell: bash - run: | - cd ${{ env.MODULE_DIR }} - uv run --python ${{ env.PYTHON_VERSION }}+freethreaded \ - ${{ steps.compatibility-flag.outputs.WITH_ZIG_FLAG }} \ - maturin build \ - ${{ steps.compatibility-flag.outputs.COMPATIBILITY_FLAG }} \ - --release \ - --out ../dist \ - --target ${{ matrix.platform.target }} \ - --strip + + #- name: Build free-threaded wheels + # # TODO: pytket is a required dependency of tket-py, but it doesn't build free-threaded wheels yet + # if: false + # shell: bash + # run: | + # cd ${{ env.MODULE_DIR }} + # uv run --python ${{ env.PYTHON_VERSION }}+freethreaded \ + # ${{ steps.compatibility-flag.outputs.WITH_ZIG_FLAG }} \ + # maturin build \ + # ${{ steps.compatibility-flag.outputs.COMPATIBILITY_FLAG }} \ + # --auditwheel=repair + # --release \ + # --out ../dist \ + # --target ${{ matrix.platform.target }} \ + # --strip - name: Repair macOS wheels with delocate if: runner.os == 'macOS' @@ -278,12 +227,10 @@ jobs: shell: bash run: | echo "Testing the newly built ${{ matrix.platform.target }} wheels..." - if [ "$TEST_INSTALL" = "true" ]; then - # Make sure we only use the tket lib from the wheel itself - rm -rf $WORKSPACE\tket-c-api\lib - rm -rf $WORKSPACE\tket-c-api\bin - uv run -f dist --with tket --refresh-package tket --no-project -- python -c "import tket" - fi + # Make sure we only use the tket lib from the wheel itself + rm -rf $WORKSPACE\tket-c-api\lib + rm -rf $WORKSPACE\tket-c-api\bin + uv run -f dist --with tket --refresh-package tket --no-project -- python -c "import tket" uvx twine check --strict dist/* env: WORKSPACE: ${{ github.workspace }} diff --git a/.github/workflows/release-checks.yml b/.github/workflows/release-checks.yml index 74a7a6689..00d8dcb9c 100644 --- a/.github/workflows/release-checks.yml +++ b/.github/workflows/release-checks.yml @@ -47,6 +47,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - name: Set up uv uses: astral-sh/setup-uv@v7 with: diff --git a/.github/workflows/semver-checks.yml b/.github/workflows/semver-checks.yml index cdd4f1786..6bd503f7e 100644 --- a/.github/workflows/semver-checks.yml +++ b/.github/workflows/semver-checks.yml @@ -38,6 +38,8 @@ jobs: uses: ./.github/actions/tket-c-api with: install-path: ${{ env.TKET_C_API_PATH }} + target: x86_64-unknown-linux-gnu + compatibility: manylinux_2_28 - name: Install LLVM from apt run: | echo "Installing apt dependencies: llvm-14" diff --git a/tket1-passes/scripts/build.sh b/tket1-passes/scripts/build.sh new file mode 100755 index 000000000..17450d89a --- /dev/null +++ b/tket1-passes/scripts/build.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -eou pipefail +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Examples:" + echo " $0 x86_64-unknown-linux-gnu manylinux_2_28_x86_64 ./out" + echo " $0 aarch64-apple-darwin 14.0 ./out" + echo " $0 x86_64-pc-windows-msvc msvc ./out" + exit 1 +fi + +target="$1" +compatibility="$2" +output_dir="$3" + +if [ ! -d "${output_dir}" ]; then + echo "Output directory ${output_dir} does not exist. Creating it." + mkdir -p "${output_dir}" +fi +output_abs="$(realpath "${output_dir}")" + +# For linux builds use docker containers for compatibility +case "${target}" in + *"linux"*) + echo "Building tket-c-api in a ${compatibility} container..." + # We mount the tket1-passes directory as read-only to prevent + # temporary files from being written to it by conan. + # + # The output directory is mounted to /out in the container, + # and is writable. + docker run -i \ + -v "$(realpath $(dirname "$0")/../)":/tket1-passes:ro \ + -v "${output_abs}":/out \ + quay.io/pypa/${compatibility}:latest \ + /bin/bash /tket1-passes/scripts/build/linux.sh /out + ;; + *"apple-darwin") + echo "Building tket-c-api with MACOSX_DEPLOYMENT_TARGET=${compatibility}..." + MACOSX_DEPLOYMENT_TARGET="${compatibility}" \ + bash -c "$(dirname "$0")/build/macos.sh ${output_abs}" + ;; + *"windows-msvc") + echo "Building tket-c-api for Windows with MSVC..." + pwsh -File "$(dirname "$0")"/build/windows.ps1 ${output_abs} + ;; + *) + echo "Unsupported target: ${target}" + exit 1 + ;; +esac diff --git a/tket1-passes/scripts/build/linux.sh b/tket1-passes/scripts/build/linux.sh new file mode 100755 index 000000000..a1305f03e --- /dev/null +++ b/tket1-passes/scripts/build/linux.sh @@ -0,0 +1,63 @@ +#!/bin/bash +set -eou pipefail + +# Build script for linux targets, designed specifically for +# use within manylinux_2_28 and musllinux_1_2 containers on +# x86_64 and aarch64 architectures. +# +# Note that different container images may have access to +# different tooling, package managers, etc. We assume +# pipx is available. jq is installed from github releases +# if not already present. + +output_dir="$1" +if [ -z "${output_dir}" ]; then + echo "Usage: $0 " + exit 1 +fi; + +if ! command -v jq &> /dev/null; then + # if uname -m is x86_64, download arm64 version of jq and use the corresponding hash + # if uname -m is aarch64, download aarch64 version of jq and use the corresponding hash + case "$(uname -m)" in + "aarch64") + jq_filename="jq-linux-arm64"; + jq_sha256="6bc62f25981328edd3cfcfe6fe51b073f2d7e7710d7ef7fcdac28d4e384fc3d4"; + ;; + "x86_64") + jq_filename="jq-linux-amd64"; + jq_sha256="020468de7539ce70ef1bceaf7cde2e8c4f2ca6c3afb84642aabc5c97d9fc2a0d" + ;; + *) + echo "Unsupported architecture: $(uname -m)" + exit 1 + ;; + esac + echo "jq not found. Downloading..." + curl -LO https://github.com/jqlang/jq/releases/download/jq-1.8.1/${jq_filename} + echo "Verifying jq checksum..." + echo "${jq_sha256} ${jq_filename}" | sha256sum -c + chmod +x ${jq_filename} + echo "Installing jq..." + mv ${jq_filename} /usr/bin/jq + echo "jq installed successfully." +fi + +# Install and run conan +pipx install conan +conan profile detect +conan remote add tket-libs https://quantinuumsw.jfrog.io/artifactory/api/conan/tket1-libs --index 0 +conan install /tket1-passes \ + --build=missing \ + --options="tket-c-api/*:shared=True" \ + --format=json \ + --output-folder=/tmp/conan_output \ + --out-file=/tmp/conanbuild.json + +# Extract the library folder path from the conan JSON output, and +# copy the built artifacts to the host tket1-passes/out directory +lib_folder=$(jq -r '.graph.nodes."1".package_folder' /tmp/conanbuild.json) +echo "Installation folder: ${lib_folder}" +chmod -R a+r "${lib_folder}" +echo "Copying built artifacts to output directory: ${output_dir}" +cp -r "${lib_folder}"/* "${output_dir}" diff --git a/tket1-passes/scripts/build/macos.sh b/tket1-passes/scripts/build/macos.sh new file mode 100755 index 000000000..9f7a812e0 --- /dev/null +++ b/tket1-passes/scripts/build/macos.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -eou pipefail + +# Build script for macOS targets. A MACOSX_DEPLOYMENT_TARGET must +# be set in the environment before calling this script. + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +output_dir="$1" + +echo "Building tket-c-api on aarch64-apple-darwin with MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET}..." + +cd "$(dirname "$0")/"../../../ + +brew install jq + +# Install and run conan +pipx install conan +conan profile detect +conan remote add tket-libs https://quantinuumsw.jfrog.io/artifactory/api/conan/tket1-libs --index 0 +conan install tket1-passes \ + --build=missing \ + --options="tket-c-api/*:shared=True" \ + --format=json \ + --output-folder=/tmp/conan_output \ + --out-file=/tmp/conanbuild.json + +# Extract the library folder path from the conan JSON output, and +# copy the built artifacts to tket1-passes/out +lib_folder=$(jq -r '.graph.nodes."1".package_folder' /tmp/conanbuild.json) +cp -r "${lib_folder}"/* "${output_dir}" diff --git a/tket1-passes/scripts/build/windows.ps1 b/tket1-passes/scripts/build/windows.ps1 new file mode 100755 index 000000000..09c40b13f --- /dev/null +++ b/tket1-passes/scripts/build/windows.ps1 @@ -0,0 +1,30 @@ +param ( + [Parameter(Mandatory = $true)] + [string]$OutputDir +) + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version Latest + +Set-Location (Join-Path $PSScriptRoot "..\..\..\") + +choco install jq -y +pipx install conan +conan profile detect +conan remote add tket-libs ` + "https://quantinuumsw.jfrog.io/artifactory/api/conan/tket1-libs" ` + --index 0 + +# Run install and capture JSON output +$tmp = New-TemporaryFile +conan install tket1-passes ` + --build=missing ` + --options="tket-c-api/*:shared=True" ` + --format=json | + Out-File -Encoding UTF8 $tmp + +$libFolder = jq -r '.graph.nodes."1".package_folder' $tmp + +Copy-Item -Recurse -Force ` + (Join-Path $libFolder "*") ` + $OutputDir