From b5d926af84123f23d42d8b66bb01bc78bdabfcff Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Mon, 12 Apr 2021 20:53:10 +0800 Subject: [PATCH] Add a fully static "linuxstatic" variant Bug: #72 --- .github/workflows/build-alpine.yml | 1 + .github/workflows/build-linuxstatic.yml | 47 +++++++++++++++++++++++++ Dockerfile.alpine | 3 +- lib/build.ts | 35 +++++++++++++----- lib/index.ts | 10 +++--- lib/system.ts | 2 +- 6 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/build-linuxstatic.yml diff --git a/.github/workflows/build-alpine.yml b/.github/workflows/build-alpine.yml index f5471239..1ddd9737 100644 --- a/.github/workflows/build-alpine.yml +++ b/.github/workflows/build-alpine.yml @@ -31,6 +31,7 @@ jobs: TARGET_TOOLCHAIN_ARCH=${{ matrix.target-toolchain }} PKG_FETCH_OPTION_a=${{ matrix.target-arch }} PKG_FETCH_OPTION_n=node${{ matrix.target-node }} + PKG_FETCH_OPTION_p=alpine context: . file: ./Dockerfile.alpine platforms: linux/amd64 diff --git a/.github/workflows/build-linuxstatic.yml b/.github/workflows/build-linuxstatic.yml new file mode 100644 index 00000000..199f1139 --- /dev/null +++ b/.github/workflows/build-linuxstatic.yml @@ -0,0 +1,47 @@ +name: Build Node binaries for Linux static + +on: + workflow_dispatch: + +jobs: + linuxstatic: + runs-on: ubuntu-20.04 + + strategy: + fail-fast: false + matrix: + target-node: [8, 10, 12, 14] + target-arch: [x64, arm64] + include: + - target-arch: x64 + target-toolchain: x86_64 + - target-arch: arm64 + target-toolchain: aarch64 + + steps: + - uses: actions/checkout@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Build + uses: docker/build-push-action@v2 + with: + build-args: | + TARGET_TOOLCHAIN_ARCH=${{ matrix.target-toolchain }} + PKG_FETCH_OPTION_a=${{ matrix.target-arch }} + PKG_FETCH_OPTION_n=node${{ matrix.target-node }} + PKG_FETCH_OPTION_p=linuxstatic + context: . + file: ./Dockerfile.alpine + platforms: linux/amd64 + outputs: type=tar,dest=../out.tar + + - name: Extract binaries from Docker image + run: | + tar xvf ../out.tar root/pkg-fetch/dist + + - uses: actions/upload-artifact@v2 + with: + name: node${{ matrix.target-node }}-linuxstatic-${{ matrix.target-arch }} + path: root/pkg-fetch/dist/* diff --git a/Dockerfile.alpine b/Dockerfile.alpine index bf9eecac..99532aff 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -4,6 +4,7 @@ FROM muslcc/x86_64:$TARGET_TOOLCHAIN_ARCH-linux-musl ARG PKG_FETCH_OPTION_a ARG PKG_FETCH_OPTION_n +ARG PKG_FETCH_OPTION_p USER root:root @@ -34,4 +35,4 @@ COPY . ./ RUN yarn install -RUN yarn start --force-build --arch $PKG_FETCH_OPTION_a --node-range $PKG_FETCH_OPTION_n --output dist +RUN yarn start --force-build --arch $PKG_FETCH_OPTION_a --node-range $PKG_FETCH_OPTION_n --platform $PKG_FETCH_OPTION_p --output dist diff --git a/lib/build.ts b/lib/build.ts index 9fe6c8a4..a6a49013 100644 --- a/lib/build.ts +++ b/lib/build.ts @@ -21,7 +21,7 @@ function getMajor(nodeVersion: string) { return Number(version) | 0; } -function getConfigureArgs(major: number): string[] { +function getConfigureArgs(major: number, targetPlatform: string): string[] { const args: string[] = []; // first of all v8_inspector introduces the use @@ -40,6 +40,10 @@ function getConfigureArgs(major: number): string[] { args.push('--partly-static'); } + if (targetPlatform === 'linuxstatic') { + args.push('--fully-static'); + } + // Link Time Optimization if (major >= 12) { if (hostPlatform === 'linux' || hostPlatform === 'alpine') { @@ -113,10 +117,14 @@ async function applyPatches(nodeVersion: string) { } } -async function compileOnWindows(nodeVersion: string, targetArch: string) { +async function compileOnWindows( + nodeVersion: string, + targetArch: string, + targetPlatform: string +) { const args = ['/c', 'vcbuild.bat', targetArch]; const major = getMajor(nodeVersion); - const config_flags = getConfigureArgs(major); + const config_flags = getConfigureArgs(major, targetPlatform); // Event Tracing for Windows args.push('noetw'); @@ -154,7 +162,11 @@ async function compileOnWindows(nodeVersion: string, targetArch: string) { const { MAKE_JOB_COUNT = os.cpus().length } = process.env; -async function compileOnUnix(nodeVersion: string, targetArch: string) { +async function compileOnUnix( + nodeVersion: string, + targetArch: string, + targetPlatform: string +) { const args = []; const cpu = { x86: 'ia32', @@ -176,7 +188,7 @@ async function compileOnUnix(nodeVersion: string, targetArch: string) { args.push('--cross-compiling'); } - args.push(...getConfigureArgs(getMajor(nodeVersion))); + args.push(...getConfigureArgs(getMajor(nodeVersion), targetPlatform)); // TODO same for windows? spawnSync('./configure', args, { cwd: nodePath, stdio: 'inherit' }); @@ -199,15 +211,19 @@ async function compileOnUnix(nodeVersion: string, targetArch: string) { return output; } -async function compile(nodeVersion: string, targetArch: string) { +async function compile( + nodeVersion: string, + targetArch: string, + targetPlatform: string +) { log.info('Compiling Node.js from sources...'); const win = hostPlatform === 'win'; if (win) { - return compileOnWindows(nodeVersion, targetArch); + return compileOnWindows(nodeVersion, targetArch, targetPlatform); } - return compileOnUnix(nodeVersion, targetArch); + return compileOnUnix(nodeVersion, targetArch, targetPlatform); } async function hash(filePath: string): Promise { @@ -233,6 +249,7 @@ async function hash(filePath: string): Promise { export default async function build( nodeVersion: string, targetArch: string, + targetPlatform: string, local: string ) { await fs.remove(buildPath); @@ -242,7 +259,7 @@ export default async function build( await gitResetHard(nodeVersion); await applyPatches(nodeVersion); - const output = await compile(nodeVersion, targetArch); + const output = await compile(nodeVersion, targetArch, targetPlatform); const outputHash = await hash(output); await fs.mkdirp(path.dirname(local)); diff --git a/lib/index.ts b/lib/index.ts index 9901f971..1e7ea8c1 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -145,9 +145,11 @@ export async function need(opts: NeedOptions) { } if (hostPlatform !== platform) { - throw wasReported( - `Not able to build for '${opts.platform}' here, only for '${hostPlatform}'` - ); + if (hostPlatform !== 'alpine' || platform !== 'linuxstatic') { + throw wasReported( + `Not able to build for '${opts.platform}' here, only for '${hostPlatform}'` + ); + } } if (knownArchs.indexOf(arch) < 0) { @@ -160,7 +162,7 @@ export async function need(opts: NeedOptions) { return 'built'; } - await build(nodeVersion, arch, built); + await build(nodeVersion, arch, platform, built); return built; } diff --git a/lib/system.ts b/lib/system.ts index 611a3c31..716bc1ad 100644 --- a/lib/system.ts +++ b/lib/system.ts @@ -68,7 +68,7 @@ function getHostPlatform() { } function getKnownPlatforms() { - return ['alpine', 'freebsd', 'linux', 'macos', 'win']; + return ['alpine', 'freebsd', 'linux', 'linuxstatic', 'macos', 'win']; } export function toFancyArch(arch: string) {