name: Build & Test on: workflow_call: inputs: run-test: default: true type: boolean jobs: build: name: ${{ matrix.platform }} (${{ matrix.target }}) (${{ matrix.os }}) runs-on: ${{ matrix.os }} timeout-minutes: 40 strategy: fail-fast: false matrix: platform: - linux-arm64 - linux-arm - linux-x64 - linux-x86 - linux-powerpc64 - windows-arm64 - windows-x64 - windows-x86 - macos-arm64 - macos-x64 - illumos-x64 - wasm32 include: # When adding a new `target`: # 1. Define a new platform alias above # 2. Add a new record to the matrix map in `crates/cli/npm/install.js` # 3. Consider adding the mapping at the end of 'crates/cli/Cargo.toml' for cargo-binstall support - { platform: linux-arm64 , target: aarch64-unknown-linux-gnu , os: ubuntu-24.04-arm } - { platform: linux-arm , target: armv7-unknown-linux-gnueabihf , os: ubuntu-24.04-arm } - { platform: linux-x64 , target: x86_64-unknown-linux-gnu , os: ubuntu-24.04 } - { platform: linux-x86 , target: i686-unknown-linux-gnu , os: ubuntu-24.04 } - { platform: linux-powerpc64 , target: powerpc64-unknown-linux-gnu , os: ubuntu-24.04 } - { platform: windows-arm64 , target: aarch64-pc-windows-msvc , os: windows-11-arm } - { platform: windows-x64 , target: x86_64-pc-windows-msvc , os: windows-2025 } - { platform: windows-x86 , target: i686-pc-windows-msvc , os: windows-2025 } - { platform: macos-arm64 , target: aarch64-apple-darwin , os: macos-15 } - { platform: macos-x64 , target: x86_64-apple-darwin , os: macos-15-intel } - { platform: wasm32 , target: wasm32-unknown-unknown , os: ubuntu-24.04 } # illumos is not supported OOTB, it runs in a vm - { platform: illumos-x64 , target: x86_64-unknown-illumos , os: ubuntu-24.04 , vm: true , no-run: true } # Extra features - { platform: linux-arm64 , features: wasm } - { platform: linux-x64 , features: wasm , run-wasm-test: true } - { platform: macos-arm64 , features: wasm , run-wasm-test: true } - { platform: macos-x64 , features: wasm } # Cross-compilation - { platform: linux-arm , cross: true } - { platform: linux-x86 , cross: true } - { platform: linux-powerpc64 , cross: true } # Compile-only - { platform: wasm32 , no-run: true } env: CARGO_TERM_COLOR: always RUSTFLAGS: -D warnings defaults: run: shell: bash steps: - name: Checkout repository uses: actions/checkout@v7.0.1 - name: Set up cross-compilation if: matrix.cross run: | for target in armv7-unknown-linux-gnueabihf i686-unknown-linux-gnu powerpc64-unknown-linux-gnu; do camel_target=${target//-/_}; target_cc=${target/-unknown/} printf 'CC_%s=%s\n' "$camel_target" "${target_cc/v7/}-gcc" printf 'AR_%s=%s\n' "$camel_target" "${target_cc/v7/}-ar" printf 'CARGO_TARGET_%s_LINKER=%s\n' "${camel_target^^}" "${target_cc/v7/}-gcc" done >> $GITHUB_ENV { printf 'CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm -L /usr/arm-linux-gnueabihf\n' printf 'CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64 -L /usr/powerpc64-linux-gnu\n' } >> $GITHUB_ENV - name: Get emscripten version if: contains(matrix.features, 'wasm') && (matrix.run-wasm-test || !inputs.run-test) run: printf 'EMSCRIPTEN_VERSION=%s\n' "$(> $GITHUB_ENV - name: Cache Emscripten SDK if: contains(matrix.features, 'wasm') && (matrix.run-wasm-test || !inputs.run-test) uses: actions/cache@v6 with: path: emsdk key: emsdk-${{ env.EMSCRIPTEN_VERSION }}-${{ runner.os }}-${{ runner.arch }} - name: Install Emscripten if: contains(matrix.features, 'wasm') && (matrix.run-wasm-test || !inputs.run-test) run: | if [[ ! -d emsdk ]]; then git clone --depth 1 https://github.com/emscripten-core/emsdk.git fi cd emsdk ./emsdk install ${{ env.EMSCRIPTEN_VERSION }} ./emsdk activate ${{ env.EMSCRIPTEN_VERSION }} echo "$PWD" >> "$GITHUB_PATH" echo "$PWD/upstream/emscripten" >> "$GITHUB_PATH" echo "EMSDK=$PWD" >> "$GITHUB_ENV" echo "EMSDK_NODE=$PWD/node/$(ls node)/bin/node" >> "$GITHUB_ENV" - name: Set up Node.js if: contains(matrix.features, 'wasm') && (matrix.run-wasm-test || !inputs.run-test) uses: actions/setup-node@v7.0.0 with: node-version: 24 cache: npm cache-dependency-path: lib/binding_web/package-lock.json - name: Set up Rust if: ${{ !matrix.vm }} uses: actions-rust-lang/setup-rust-toolchain@v1 with: target: ${{ matrix.target }} - name: Install Rust Wasm test target if: matrix.run-wasm-test run: rustup toolchain install nightly --profile minimal --component rust-src - name: Install cross-compilation toolchain if: matrix.cross run: | sudo apt-get update -qy if [[ $PLATFORM == linux-arm ]]; then sudo apt-get install -qy {binutils,gcc}-arm-linux-gnueabihf qemu-user elif [[ $PLATFORM == linux-x86 ]]; then sudo apt-get install -qy {binutils,gcc}-i686-linux-gnu elif [[ $PLATFORM == linux-powerpc64 ]]; then sudo apt-get install -qy {binutils,gcc}-powerpc64-linux-gnu qemu-user fi env: PLATFORM: ${{ matrix.platform }} - name: Install MinGW and Clang (Windows x64 MSYS2) if: matrix.platform == 'windows-x64' uses: msys2/setup-msys2@v2 with: install: | mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang mingw-w64-x86_64-make mingw-w64-x86_64-cmake - name: Build C library (Windows x64 MSYS2 CMake) if: matrix.platform == 'windows-x64' shell: msys2 {0} run: | cmake -G Ninja -S . -B build/static \ -DBUILD_SHARED_LIBS=OFF \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \ -DTREE_SITTER_FEATURE_WASM=$WASM \ -DCMAKE_C_COMPILER=clang cmake --build build/static cmake -G Ninja -S . -B build/shared \ -DBUILD_SHARED_LIBS=ON \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \ -DTREE_SITTER_FEATURE_WASM=$WASM \ -DCMAKE_C_COMPILER=clang cmake --build build/shared rm -rf \ build/{static,shared} \ "${CMAKE_PREFIX_PATH}/artifacts" \ target/wasmtime-${WASMTIME_VERSION} env: WASM: ${{ contains(matrix.features, 'wasm') && 'ON' || 'OFF' }} - name: Download wasmtime C API if: contains(matrix.features, 'wasm') && (matrix.run-wasm-test || !inputs.run-test) run: | mkdir -p target WASMTIME_VERSION=$(cargo metadata --format-version=1 --locked --features wasm | \ jq -r '.packages[] | select(.name == "wasmtime-c-api-impl") | .version') case '${{ matrix.target }}' in x86_64-unknown-linux-gnu) WT_TARGET=x86_64-linux ;; aarch64-unknown-linux-gnu) WT_TARGET=aarch64-linux ;; x86_64-apple-darwin) WT_TARGET=x86_64-macos ;; aarch64-apple-darwin) WT_TARGET=aarch64-macos ;; esac curl -LSs "$WASMTIME_REPO/releases/download/v${WASMTIME_VERSION}/wasmtime-v${WASMTIME_VERSION}-${WT_TARGET}-c-api.tar.xz" \ | tar xJf - -C target printf 'CMAKE_PREFIX_PATH=%s\n' "$PWD/target/wasmtime-v${WASMTIME_VERSION}-${WT_TARGET}-c-api" >> $GITHUB_ENV env: WASMTIME_REPO: https://github.com/bytecodealliance/wasmtime - name: Build C library (make) if: runner.os != 'Windows' && !matrix.vm run: | if [[ $PLATFORM == linux-arm ]]; then CC=arm-linux-gnueabihf-gcc; AR=arm-linux-gnueabihf-ar elif [[ $PLATFORM == linux-x86 ]]; then CC=i686-linux-gnu-gcc; AR=i686-linux-gnu-ar elif [[ $PLATFORM == linux-powerpc64 ]]; then CC=powerpc64-linux-gnu-gcc; AR=powerpc64-linux-gnu-ar else CC=gcc; AR=ar fi make -j CFLAGS="$CFLAGS" CC=$CC AR=$AR env: PLATFORM: ${{ matrix.platform }} CFLAGS: -g -Werror -Wall -Wextra -Wshadow -Wpedantic -Werror=incompatible-pointer-types -Werror=strict-aliasing -Wstrict-aliasing=2 - name: Build C library (CMake) if: "!matrix.cross && !matrix.vm" run: | cmake -S . -B build/static \ -DBUILD_SHARED_LIBS=OFF \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \ -DTREE_SITTER_FEATURE_WASM=$WASM cmake --build build/static --verbose cmake -S . -B build/shared \ -DBUILD_SHARED_LIBS=ON \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \ -DTREE_SITTER_FEATURE_WASM=$WASM cmake --build build/shared --verbose env: CC: ${{ contains(matrix.platform, 'linux') && 'clang' || '' }} WASM: ${{ contains(matrix.features, 'wasm') && (matrix.run-wasm-test || !inputs.run-test) && 'ON' || 'OFF' }} - name: Build C library and Rust crate (illumos gmake) if: matrix.platform == 'illumos-x64' uses: vmactions/omnios-vm@v1.3.6 with: release: r151056-build copyback: false prepare: | pkg install -q build-essential || [ $? -eq 4 ] curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal run: | . "$HOME/.cargo/env" gmake -j cargo build -p tree-sitter - name: Build Wasm library if: contains(matrix.features, 'wasm') && (matrix.run-wasm-test || !inputs.run-test) shell: bash run: | cd lib/binding_web npm ci CJS=true npm run build CJS=true npm run build:debug npm run build npm run build:debug - name: Check no_std builds if: inputs.run-test && !matrix.no-run working-directory: lib shell: bash run: cargo check --no-default-features --target='${{ matrix.target }}' - name: Build target if: "!inputs.run-test && !matrix.vm" run: cargo build --release --target='${{ matrix.target }}' --features='${{ (matrix.run-wasm-test || !inputs.run-test) && matrix.features || '' }}' $PACKAGE env: PACKAGE: ${{ matrix.platform == 'wasm32' && '-p tree-sitter' || '' }} - name: Cache fixtures id: cache if: inputs.run-test && !matrix.no-run uses: ./.github/actions/cache - name: Fetch fixtures if: inputs.run-test && !matrix.no-run run: cargo run -p xtask --target='${{ matrix.target }}' -- fetch-fixtures - name: Generate fixtures if: inputs.run-test && !matrix.no-run && steps.cache.outputs.cache-hit != 'true' run: cargo run -p xtask --target='${{ matrix.target }}' -- generate-fixtures - name: Generate Wasm fixtures if: inputs.run-test && !matrix.no-run && contains(matrix.features, 'wasm') && matrix.run-wasm-test && steps.cache.outputs.cache-hit != 'true' run: cargo run -p xtask --target='${{ matrix.target }}' -- generate-fixtures --wasm - name: Run main tests if: inputs.run-test && !matrix.no-run run: cargo test --workspace --target='${{ matrix.target }}' --features='${{ (matrix.run-wasm-test || !inputs.run-test) && matrix.features || '' }}' - name: Run Wasm tests if: inputs.run-test && !matrix.no-run && contains(matrix.features, 'wasm') && matrix.run-wasm-test run: cargo run -p xtask --target='${{ matrix.target }}' -- test-wasm - name: Run Rust Wasm web test if: inputs.run-test && !matrix.no-run && contains(matrix.features, 'wasm') && matrix.run-wasm-test run: cargo run -p xtask --target='${{ matrix.target }}' -- test-rust-wasm-web - name: Upload CLI artifact if: "!inputs.run-test && !matrix.no-run" uses: actions/upload-artifact@v7 with: name: tree-sitter.${{ matrix.platform }} path: target/${{ matrix.target }}/release/tree-sitter${{ contains(matrix.target, 'windows') && '.exe' || '' }} if-no-files-found: error retention-days: 7 - name: Upload Wasm artifacts if: "!inputs.run-test && matrix.platform == 'linux-x64'" uses: actions/upload-artifact@v7 with: name: tree-sitter.wasm path: | lib/binding_web/web-tree-sitter.js lib/binding_web/web-tree-sitter.js.map lib/binding_web/web-tree-sitter.cjs lib/binding_web/web-tree-sitter.cjs.map lib/binding_web/web-tree-sitter.wasm lib/binding_web/web-tree-sitter.wasm.map lib/binding_web/debug/web-tree-sitter.cjs lib/binding_web/debug/web-tree-sitter.cjs.map lib/binding_web/debug/web-tree-sitter.js lib/binding_web/debug/web-tree-sitter.js.map lib/binding_web/debug/web-tree-sitter.wasm lib/binding_web/debug/web-tree-sitter.wasm.map lib/binding_web/lib/*.c lib/binding_web/lib/*.h lib/binding_web/lib/*.ts lib/binding_web/src/*.ts if-no-files-found: error retention-days: 7