Add support for cross compilation with Zig (#983)

feat(cli): add support for cross compilation with Zig
This commit is contained in:
messense 2021-12-31 11:20:55 +08:00 committed by GitHub
parent d58246ea62
commit ca3790bdf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 122 additions and 2 deletions

View file

@ -0,0 +1,69 @@
name: Linux-aarch64-zig
env:
DEBUG: 'napi:*'
on:
push:
branches:
- main
pull_request:
jobs:
build:
name: stable - aarch64-unknown-linux-gnu - node@16
runs-on: ubuntu-latest
steps:
- run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: 16
check-latest: true
cache: 'yarn'
- name: Install
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
target: aarch64-unknown-linux-musl
- name: Install aarch64 toolchain
run: rustup target add aarch64-unknown-linux-gnu
- name: Install ziglang
uses: goto-bus-stop/setup-zig@v1
with:
version: 0.9.0
- name: Cache NPM dependencies
uses: actions/cache@v2
with:
path: node_modules
key: npm-cache-linux-aarch64-gnu-node@16-${{ hashFiles('yarn.lock') }}
- name: Install dependencies
run: yarn install --frozen-lockfile --ignore-platform --registry https://registry.npmjs.org --network-timeout 300000
- name: 'Build TypeScript'
run: yarn build
- name: Cross build native tests
run: |
yarn --cwd ./examples/napi-compat-mode build --target aarch64-unknown-linux-musl --zig
yarn --cwd ./examples/napi build --target aarch64-unknown-linux-musl --zig
- name: Setup and run tests
uses: docker://multiarch/alpine:aarch64-latest-stable
with:
args: >
sh -c "
apk add nodejs yarn && \
yarn test
"

View file

@ -47,6 +47,7 @@
"chalk": "4",
"clipanion": "^3.1.0",
"debug": "^4.3.3",
"env-paths": "^3.0.0",
"fdir": "^5.1.0",
"inquirer": "^8.2.0",
"js-yaml": "^4.1.0",

View file

@ -1,16 +1,17 @@
import { execSync } from 'child_process'
import { existsSync } from 'fs'
import { existsSync, mkdirSync, writeFileSync } from 'fs'
import { join, parse, sep } from 'path'
import { Instance } from 'chalk'
import { Command, Option } from 'clipanion'
import envPaths from 'env-paths'
import { groupBy } from 'lodash-es'
import toml from 'toml'
import { getNapiConfig } from './consts'
import { debugFactory } from './debug'
import { createJsBinding } from './js-binding-template'
import { getDefaultTargetTriple, parseTriple } from './parse-triple'
import { getCpuArch, getDefaultTargetTriple, parseTriple } from './parse-triple'
import {
copyFileAsync,
mkdirAsync,
@ -117,6 +118,10 @@ export class BuildCommand extends Command {
required: false,
})
useZig = Option.Boolean(`--zig`, false, {
description: `Use ${chalk.green('zig')} as linker`,
})
async execute() {
const cwd = this.cargoCwd
? join(process.cwd(), this.cargoCwd)
@ -160,6 +165,34 @@ export class BuildCommand extends Command {
CARGO_PROFILE_RELEASE_LTO: false,
})
}
if (triple.raw.includes('musl')) {
let rustflags = process.env.RUSTFLAGS ?? ''
if (!rustflags.includes('target-feature=-crt-static')) {
rustflags += '-C target-feature=-crt-static'
additionalEnv['RUSTFLAGS'] = rustflags
}
}
if (this.useZig && triple.platform === 'linux') {
const paths = envPaths('napi-rs')
const cpuArch = getCpuArch(triple.arch)
const linkerWrapper = join(paths.cache, `zig-cc-${triple.abi}.sh`)
const zigTarget = `${cpuArch}-linux-${triple.abi}`
mkdirSync(paths.cache, { recursive: true })
writeFileSync(
linkerWrapper,
`#!/bin/bash\nzig cc \${@/-lgcc_s/-lunwind} -target ${zigTarget}\n`,
{ mode: 0o700 },
)
const envTarget = triple.raw.replaceAll('-', '_').toUpperCase()
Object.assign(additionalEnv, {
TARGET_CC: linkerWrapper,
TARGET_CXX: `zig c++ -target ${zigTarget}`,
})
additionalEnv[`CARGO_TARGET_${envTarget}_LINKER`] = linkerWrapper
}
execSync(cargoCommand, {
env: {
...process.env,

View file

@ -21,6 +21,14 @@ const CpuToNodeArch: { [index: string]: NodeJSArch } = {
armv7: 'arm',
}
const NodeArchToCpu: { [index: string]: string } = {
arm64: 'aarch64',
ppc: 'powerpc',
ppc64: 'powerpc64',
x32: 'i686',
x64: 'x86_64',
}
const SysToNodePlatform: { [index: string]: NodeJS.Platform } = {
linux: 'linux',
freebsd: 'freebsd',
@ -125,3 +133,7 @@ export function getDefaultTargetTriple(rustcfg: string): PlatformDetail {
}
return parseTriple(triple)
}
export function getCpuArch(nodeArch: NodeJSArch): string {
return NodeArchToCpu[nodeArch] || nodeArch
}

View file

@ -2636,6 +2636,11 @@ env-paths@^2.2.0:
resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
env-paths@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz#2f1e89c2f6dbd3408e1b1711dd82d62e317f58da"
integrity sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==
envinfo@^7.7.4:
version "7.8.1"
resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"