name: Build
on:
push:
branches: ["master"]
pull_request:
branches: ["master"]
release:
types: ["created"]
permissions:
contents: "write"
jobs:
build:
strategy:
matrix:
os:
- runner: "ubuntu-22.04"
sys: "linux"
arch: "x64"
friendly_name: "Linux (x64)"
ext: ""
- runner: "ubuntu-22.04-arm"
sys: "linux"
arch: "arm64"
friendly_name: "Linux (ARM64)"
ext: ""
- runner: "macos-14"
sys: "darwin"
arch: "arm64"
friendly_name: "macOS (Apple Silicon)"
ext: ""
- runner: "windows-2022"
sys: "windows"
arch: "x64"
friendly_name: "Windows (x64)"
ext: ".exe"
build:
- channel: "release"
flag: ""
- channel: "debug"
flag: "-g"
linking:
- mode: "dynamic"
- mode: "static"
fail-fast: false
runs-on: ${{ matrix.os.runner }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Install the latest version of uv
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
python-version: "3.13"
cache-dependency-glob: "**/*.py.lock"
- name: Restore cached libclang
id: cache-libclang-restore
if: matrix.linking.mode == 'static'
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7
with:
path: lib/libclang
key: libclang-${{ matrix.os.runner }}-${{ matrix.os.arch }}-${{ hashFiles('scripts/libclang.json') }}
- name: Download libclang
if: matrix.linking.mode == 'static' && steps.cache-libclang-restore.outputs.cache-hit != 'true'
run: |
uv run scripts/download.py
- name: Setup Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
go-version: 1.24
cache: true
- name: Setup Cangjie
uses: Zxilly/setup-cangjie@91463316b1c359f216c2ac49e35900f9341c1571
with:
channel: "nightly"
version: "1.1.0-alpha.20260603010036"
- name: Install system libclang (dynamic, Linux)
if: matrix.linking.mode == 'dynamic' && matrix.os.sys == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libclang-dev
- name: Install system libclang (dynamic, macOS)
if: matrix.linking.mode == 'dynamic' && matrix.os.sys == 'darwin'
run: |
brew install llvm
echo "LIBCLANG_PATH=$(brew --prefix llvm)/lib" >> $GITHUB_ENV
- name: Install OpenSSL on macOS
if: runner.os == 'macOS'
run: |
brew install openssl
echo "DYLD_LIBRARY_PATH=$(brew --prefix openssl)/lib:$DYLD_LIBRARY_PATH" >> $GITHUB_ENV
- name: Setup MSYS2
if: matrix.os.sys == 'windows'
uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d
with:
msystem: CLANG64
update: true
install: >-
mingw-w64-clang-x86_64-clang
path-type: inherit
- name: Build unix ${{ matrix.build.channel }} (${{ matrix.linking.mode }})
if: matrix.os.sys != 'windows' && !(github.event_name == 'release' && matrix.build.channel == 'debug')
run: |
static_flag=""
if [ "${{ matrix.linking.mode }}" = "static" ]; then
static_flag="--static"
fi
uv run scripts/cjpm.py $static_flag build --cfg_verbose -V ${{ matrix.build.flag }}
- name: Build windows ${{ matrix.build.channel }} (${{ matrix.linking.mode }})
if: matrix.os.sys == 'windows' && !(github.event_name == 'release' && matrix.build.channel == 'debug')
shell: msys2 {0}
run: |
static_flag=""
if [ "${{ matrix.linking.mode }}" = "static" ]; then
static_flag="--static"
fi
uv run python scripts/cjpm.py $static_flag build --cfg_verbose -V ${{ matrix.build.flag }}
- name: Enable core dumps (Linux)
if: matrix.os.sys == 'linux'
run: |
sudo mkdir -p /tmp/cores
sudo chmod 1777 /tmp/cores
sudo sysctl -w kernel.core_pattern=/tmp/cores/core.%e.%p
# Disable apport if present
sudo service apport stop 2>/dev/null || true
echo "Core dumps enabled, pattern: /tmp/cores/core.%e.%p"
- name: Enable core dumps (macOS)
if: matrix.os.sys == 'darwin'
run: |
sudo mkdir -p /tmp/cores
sudo chmod 1777 /tmp/cores
sudo sysctl -w kern.corefile=/tmp/cores/core.%P
echo "Core dumps enabled, pattern: /tmp/cores/core.%P"
- name: Test binary (Unix)
id: test_binary_unix
if: ${{ matrix.os.sys != 'windows' && !(github.event_name == 'release' && matrix.build.channel == 'debug') }}
continue-on-error: true
shell: bash
run: |
ulimit -c unlimited
./target/${{ matrix.build.channel }}/bin/cjbind_cli${{ matrix.os.ext }} --version
- name: Test binary (Windows)
id: test_binary_win
if: ${{ matrix.os.sys == 'windows' && !(github.event_name == 'release' && matrix.build.channel == 'debug') }}
continue-on-error: true
shell: msys2 {0}
run: |
./target/${{ matrix.build.channel }}/bin/cjbind_cli${{ matrix.os.ext }} --version
- name: Collect crash artifacts (Linux)
if: (steps.test_binary_unix.outcome == 'failure' || steps.test_binary_win.outcome == 'failure') && matrix.os.sys == 'linux'
run: |
mkdir -p crash-artifacts
cp ./target/${{ matrix.build.channel }}/bin/cjbind_cli crash-artifacts/ || true
cp /tmp/cores/core.* crash-artifacts/ 2>/dev/null || true
ls -la /tmp/cores/ 2>/dev/null || echo "No cores in /tmp/cores/"
ls -la crash-artifacts/
- name: Collect crash artifacts (macOS)
if: (steps.test_binary_unix.outcome == 'failure' || steps.test_binary_win.outcome == 'failure') && matrix.os.sys == 'darwin'
run: |
mkdir -p crash-artifacts
cp ./target/${{ matrix.build.channel }}/bin/cjbind_cli crash-artifacts/ || true
cp /tmp/cores/core.* crash-artifacts/ 2>/dev/null || true
ls -la /tmp/cores/ 2>/dev/null || echo "No cores in /tmp/cores/"
# macOS crash reports
cp ~/Library/Logs/DiagnosticReports/cjbind_cli* crash-artifacts/ 2>/dev/null || true
ls -la crash-artifacts/
- name: Collect crash artifacts (Windows)
if: (steps.test_binary_unix.outcome == 'failure' || steps.test_binary_win.outcome == 'failure') && matrix.os.sys == 'windows'
shell: bash
run: |
mkdir -p crash-artifacts
cp ./target/${{ matrix.build.channel }}/bin/cjbind_cli.exe crash-artifacts/ || true
# Windows minidumps
find /c/Users/runneradmin/AppData/Local/CrashDumps -name '*.dmp' -exec cp {} crash-artifacts/ \; 2>/dev/null || true
ls -la crash-artifacts/
- name: Upload crash artifacts
if: (steps.test_binary_unix.outcome == 'failure' || steps.test_binary_win.outcome == 'failure')
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: crash-${{ matrix.os.runner }}-${{ matrix.os.arch }}-${{ matrix.build.channel }}-${{ matrix.linking.mode }}
path: crash-artifacts/
- name: Upload artifact
if: ${{ !(github.event_name == 'release' && matrix.build.channel == 'debug') }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: cjbind-${{ matrix.os.runner }}-${{ matrix.os.arch }}-${{ matrix.build.channel }}-${{ matrix.linking.mode }}
path: |
target/${{ matrix.build.channel }}/bin/cjbind_cli*
- name: Fail if test crashed
if: (steps.test_binary_unix.outcome == 'failure' || steps.test_binary_win.outcome == 'failure')
run: exit 1
- name: Rename binary
if: github.event_name == 'release' && matrix.build.channel == 'release'
shell: bash
run: |
cd target/release/bin
mv cjbind_cli${{ matrix.os.ext }} cjbind-${{ matrix.os.sys }}-${{ matrix.os.arch }}-${{ matrix.linking.mode }}${{ matrix.os.ext }}
- name: Upload to Release
if: github.event_name == 'release' && matrix.build.channel == 'release'
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ASSET_PATH: target/release/bin/cjbind-${{ matrix.os.sys }}-${{ matrix.os.arch }}-${{ matrix.linking.mode }}${{ matrix.os.ext }}
run: |
gh release upload ${{ github.event.release.tag_name }} "$ASSET_PATH#${{ matrix.os.friendly_name }} (${{ matrix.linking.mode }})" \
--clobber
- name: Always Save libclang
id: cache-libclang-save
if: always() && matrix.linking.mode == 'static' && steps.cache-libclang-restore.outputs.cache-hit != 'true'
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7
with:
key: ${{ steps.cache-libclang-restore.outputs.cache-primary-key }}
path: |
lib/libclang