diff --git a/.github/workflows/build-native.yml b/.github/workflows/build-native.yml index 55ec9e89..fb6760a2 100644 --- a/.github/workflows/build-native.yml +++ b/.github/workflows/build-native.yml @@ -20,18 +20,34 @@ jobs: target: x86_64-unknown-linux-gnu node_arch: x64 node_os: linux + artifact_key: linux-x64 + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + node_arch: arm64 + node_os: linux + artifact_key: linux-arm64 + cross: true + - os: ubuntu-latest + target: x86_64-unknown-linux-musl + node_arch: x64 + node_os: linux + artifact_key: linux-x64-musl + cross: true - os: macos-latest target: aarch64-apple-darwin node_arch: arm64 node_os: darwin + artifact_key: darwin-arm64 - os: macos-14 target: x86_64-apple-darwin node_arch: x64 node_os: darwin + artifact_key: darwin-x64 - os: windows-latest target: x86_64-pc-windows-msvc node_arch: x64 node_os: win32 + artifact_key: win32-x64 runs-on: ${{ matrix.os }} name: Build ${{ matrix.target }} @@ -56,6 +72,29 @@ jobs: with: workspaces: crates/codegraph-core + - name: Install cross-compilation tools (aarch64-gnu) + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + sudo apt-get update + sudo apt-get install -y gcc-aarch64-linux-gnu + echo "CC=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" + echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" + + - name: Install cross-compilation tools (x86_64-musl) + if: matrix.target == 'x86_64-unknown-linux-musl' + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + # Create linker script so -lgcc_s resolves to static libgcc + MUSL_LIB_DIR="$(dirname "$(musl-gcc -print-libgcc-file-name)")" + echo 'INPUT(-lgcc)' | sudo tee "${MUSL_LIB_DIR}/libgcc_s.so" > /dev/null + echo "CC_x86_64_unknown_linux_musl=musl-gcc" >> "$GITHUB_ENV" + echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc" >> "$GITHUB_ENV" + # Symlink libgcc_s into Rust sysroot so rust-lld can find it for host builds + GNU_LIB="$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/lib" + sudo ln -sf /lib/x86_64-linux-gnu/libgcc_s.so.1 "${GNU_LIB}/libgcc_s.so" + sudo ln -sf /lib/x86_64-linux-gnu/libgcc_s.so.1 "${GNU_LIB}/libgcc_s.so.1" + - name: Install napi-rs CLI run: npm install -g @napi-rs/cli@3 @@ -66,6 +105,6 @@ jobs: - name: Upload artifact uses: actions/upload-artifact@v7 with: - name: native-${{ matrix.node_os }}-${{ matrix.node_arch }} + name: native-${{ matrix.artifact_key }} path: crates/codegraph-core/*.node if-no-files-found: error diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index af9bf174..99c77c9f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -97,18 +97,34 @@ jobs: target: x86_64-unknown-linux-gnu node_arch: x64 node_os: linux + artifact_key: linux-x64 + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + node_arch: arm64 + node_os: linux + artifact_key: linux-arm64 + cross: true + - os: ubuntu-latest + target: x86_64-unknown-linux-musl + node_arch: x64 + node_os: linux + artifact_key: linux-x64-musl + cross: true - os: macos-latest target: aarch64-apple-darwin node_arch: arm64 node_os: darwin + artifact_key: darwin-arm64 - os: macos-14 target: x86_64-apple-darwin node_arch: x64 node_os: darwin + artifact_key: darwin-x64 - os: windows-latest target: x86_64-pc-windows-msvc node_arch: x64 node_os: win32 + artifact_key: win32-x64 runs-on: ${{ matrix.os }} name: Build ${{ matrix.target }} @@ -133,6 +149,29 @@ jobs: with: workspaces: crates/codegraph-core + - name: Install cross-compilation tools (aarch64-gnu) + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + sudo apt-get update + sudo apt-get install -y gcc-aarch64-linux-gnu + echo "CC=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" + echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" + + - name: Install cross-compilation tools (x86_64-musl) + if: matrix.target == 'x86_64-unknown-linux-musl' + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + # Create linker script so -lgcc_s resolves to static libgcc + MUSL_LIB_DIR="$(dirname "$(musl-gcc -print-libgcc-file-name)")" + echo 'INPUT(-lgcc)' | sudo tee "${MUSL_LIB_DIR}/libgcc_s.so" > /dev/null + echo "CC_x86_64_unknown_linux_musl=musl-gcc" >> "$GITHUB_ENV" + echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc" >> "$GITHUB_ENV" + # Symlink libgcc_s into Rust sysroot so rust-lld can find it for host builds + GNU_LIB="$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/lib" + sudo ln -sf /lib/x86_64-linux-gnu/libgcc_s.so.1 "${GNU_LIB}/libgcc_s.so" + sudo ln -sf /lib/x86_64-linux-gnu/libgcc_s.so.1 "${GNU_LIB}/libgcc_s.so.1" + - name: Install napi-rs CLI run: npm install -g @napi-rs/cli@3 @@ -143,7 +182,7 @@ jobs: - name: Upload native binary uses: actions/upload-artifact@v7 with: - name: native-${{ matrix.node_os }}-${{ matrix.node_arch }} + name: native-${{ matrix.artifact_key }} path: crates/codegraph-core/*.node if-no-files-found: error @@ -189,11 +228,14 @@ jobs: VERSION: ${{ needs.compute-version.outputs.version }} shell: bash run: | + # Format: pkg_name|os|cpu|libc (libc empty for non-linux) declare -A PACKAGES=( - ["linux-x64"]="@optave/codegraph-linux-x64-gnu" - ["darwin-arm64"]="@optave/codegraph-darwin-arm64" - ["darwin-x64"]="@optave/codegraph-darwin-x64" - ["win32-x64"]="@optave/codegraph-win32-x64-msvc" + ["linux-x64"]="@optave/codegraph-linux-x64-gnu|linux|x64|glibc" + ["linux-x64-musl"]="@optave/codegraph-linux-x64-musl|linux|x64|musl" + ["linux-arm64"]="@optave/codegraph-linux-arm64-gnu|linux|arm64|glibc" + ["darwin-arm64"]="@optave/codegraph-darwin-arm64|darwin|arm64|" + ["darwin-x64"]="@optave/codegraph-darwin-x64|darwin|x64|" + ["win32-x64"]="@optave/codegraph-win32-x64-msvc|win32|x64|" ) ARTIFACTS="${RUNNER_TEMP}/artifacts" @@ -201,13 +243,23 @@ jobs: for artifact_dir in "${ARTIFACTS}"/native-*/; do platform=$(basename "$artifact_dir" | sed 's/^native-//') - pkg_name=${PACKAGES[$platform]} - node_os=${platform%%-*} - node_arch=${platform##*-} + entry=${PACKAGES[$platform]} + if [ -z "$entry" ]; then + echo "::warning::Unknown platform artifact: $platform — skipping" + continue + fi + + IFS='|' read -r pkg_name node_os node_arch libc <<< "$entry" mkdir -p "${PKG_DIR}/$platform" cp "$artifact_dir"/*.node "${PKG_DIR}/$platform/codegraph-core.node" + # Build libc field for Linux packages + libc_field="" + if [ -n "$libc" ]; then + libc_field="\"libc\": [\"${libc}\"]," + fi + cat > "${PKG_DIR}/$platform/package.json" < "${PKG_DIR}/$platform/package.json" < f.startsWith('ld-musl-') && f.endsWith('.so.1'))) { + return 'musl'; + } + } catch {} + return 'gnu'; +} + +/** Map of (platform-arch[-libc]) → npm package name. */ const PLATFORM_PACKAGES = { - 'linux-x64': '@optave/codegraph-linux-x64-gnu', + 'linux-x64-gnu': '@optave/codegraph-linux-x64-gnu', + 'linux-x64-musl': '@optave/codegraph-linux-x64-musl', + 'linux-arm64-gnu': '@optave/codegraph-linux-arm64-gnu', + 'linux-arm64-musl': '@optave/codegraph-linux-arm64-musl', // not yet published — placeholder for future CI target 'darwin-arm64': '@optave/codegraph-darwin-arm64', 'darwin-x64': '@optave/codegraph-darwin-x64', 'win32-x64': '@optave/codegraph-win32-x64-msvc', @@ -29,7 +47,9 @@ export function loadNative() { const require = createRequire(import.meta.url); - const key = `${os.platform()}-${os.arch()}`; + const platform = os.platform(); + const arch = os.arch(); + const key = platform === 'linux' ? `${platform}-${arch}-${detectLibc()}` : `${platform}-${arch}`; const pkg = PLATFORM_PACKAGES[key]; if (pkg) { try {