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 - 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` - { 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 } # Extra features - { platform: linux-arm64 , features: wasm } - { platform: linux-x64 , features: wasm } - { platform: macos-arm64 , features: wasm } - { 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@v6 - 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') run: printf 'EMSCRIPTEN_VERSION=%s\n' "$(> $GITHUB_ENV - name: Install Emscripten if: contains(matrix.features, 'wasm') uses: mymindstorm/setup-emsdk@v14 with: version: ${{ env.EMSCRIPTEN_VERSION }} - name: Set up Rust uses: actions-rust-lang/setup-rust-toolchain@v1 with: target: ${{ matrix.target }} - 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: update: true install: | mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang mingw-w64-x86_64-make mingw-w64-x86_64-cmake # TODO: Remove RUSTFLAGS="--cap-lints allow" once we use a wasmtime release that addresses # the `mismatched-lifetime-syntaxes` lint - name: Build wasmtime library (Windows x64 MSYS2) if: contains(matrix.features, 'wasm') && matrix.platform == 'windows-x64' run: | mkdir -p target WASMTIME_VERSION=$(cargo metadata --format-version=1 --locked --features wasm | \ jq -r '.packages[] | select(.name == "wasmtime-c-api-impl") | .version') curl -LSs "$WASMTIME_REPO/archive/refs/tags/v${WASMTIME_VERSION}.tar.gz" | tar xzf - -C target cd target/wasmtime-${WASMTIME_VERSION} cmake -S crates/c-api -B target/c-api \ -DCMAKE_INSTALL_PREFIX="$PWD/artifacts" \ -DWASMTIME_DISABLE_ALL_FEATURES=ON \ -DWASMTIME_FEATURE_CRANELIFT=ON \ -DWASMTIME_TARGET='x86_64-pc-windows-gnu' cmake --build target/c-api && cmake --install target/c-api printf 'CMAKE_PREFIX_PATH=%s\n' "$PWD/artifacts" >> $GITHUB_ENV env: WASMTIME_REPO: https://github.com/bytecodealliance/wasmtime RUSTFLAGS: ${{ env.RUSTFLAGS }} --cap-lints allow - 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' }} # TODO: Remove RUSTFLAGS="--cap-lints allow" once we use a wasmtime release that addresses # the `mismatched-lifetime-syntaxes` lint - name: Build wasmtime library if: contains(matrix.features, 'wasm') run: | mkdir -p target WASMTIME_VERSION=$(cargo metadata --format-version=1 --locked --features wasm | \ jq -r '.packages[] | select(.name == "wasmtime-c-api-impl") | .version') curl -LSs "$WASMTIME_REPO/archive/refs/tags/v${WASMTIME_VERSION}.tar.gz" | tar xzf - -C target cd target/wasmtime-${WASMTIME_VERSION} cmake -S crates/c-api -B target/c-api \ -DCMAKE_INSTALL_PREFIX="$PWD/artifacts" \ -DWASMTIME_DISABLE_ALL_FEATURES=ON \ -DWASMTIME_FEATURE_CRANELIFT=ON \ -DWASMTIME_TARGET='${{ matrix.target }}' cmake --build target/c-api && cmake --install target/c-api printf 'CMAKE_PREFIX_PATH=%s\n' "$PWD/artifacts" >> $GITHUB_ENV env: WASMTIME_REPO: https://github.com/bytecodealliance/wasmtime RUSTFLAGS: ${{ env.RUSTFLAGS }} --cap-lints allow - name: Build C library (make) if: runner.os != 'Windows' 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 - name: Build C library (CMake) if: "!matrix.cross" 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') && 'ON' || 'OFF' }} - name: Build Wasm library if: contains(matrix.features, 'wasm') 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 run: cargo build --release --target='${{ matrix.target }}' --features='${{ 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') && 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 --target='${{ matrix.target }}' --features='${{ matrix.features }}' - name: Run Wasm tests if: inputs.run-test && !matrix.no-run && contains(matrix.features, 'wasm') run: cargo run -p xtask --target='${{ matrix.target }}' -- test-wasm - name: Upload CLI artifact if: "!matrix.no-run" uses: actions/upload-artifact@v6 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: matrix.platform == 'linux-x64' uses: actions/upload-artifact@v6 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