diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2486ec76..17c227f8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,6 +68,11 @@ on: default: 12 required: false type: number + node-gyp-build-major: + description: Major version of node-gyp-build used by the package (3 or 4). Controls the prebuild directory and filename naming convention. + default: 3 + required: false + type: number concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -86,6 +91,7 @@ env: GYP: ${{ !inputs.napi && !inputs.napi-rs && !inputs.neon && !inputs.rust }} DIRECTORY_PATH: ${{ inputs.directory-path }} NODE_VERSIONS: '>=${{ inputs.min-node-version }}' + NODE_GYP_BUILD_MAJOR: ${{ inputs.node-gyp-build-major }} jobs: versions: diff --git a/prebuild/action.yml b/prebuild/action.yml index aab9f8a2..913ac998 100644 --- a/prebuild/action.yml +++ b/prebuild/action.yml @@ -54,6 +54,7 @@ runs: -e NODE_VERSIONS="$NODE_VERSIONS" \ -e NODE_HEADERS_DIRECTORY="/usr/node_headers" \ -e LIBC="$LIBC" \ + -e NODE_GYP_BUILD_MAJOR="$NODE_GYP_BUILD_MAJOR" \ -w /usr/action \ $DOCKER_BUILDER \ /bin/bash -c 'yarn && cd /usr/workspace && yarn exec node /usr/action' @@ -64,3 +65,10 @@ runs: name: prebuilds-${{ github.job }} if-no-files-found: ignore path: ${{ env.DIRECTORY_PATH }}/prebuilds/**/${{ env.PREBUILDS_DIR || github.job }}/* + if: ${{ env.NODE_GYP_BUILD_MAJOR != '4' }} + - uses: actions/upload-artifact@v4 + with: + name: prebuilds-${{ github.job }} + if-no-files-found: ignore + path: ${{ env.DIRECTORY_PATH }}/prebuilds/**/* + if: ${{ env.NODE_GYP_BUILD_MAJOR == '4' }} diff --git a/prebuild/index.js b/prebuild/index.js index 65f4b799..7ee16237 100644 --- a/prebuild/index.js +++ b/prebuild/index.js @@ -24,9 +24,41 @@ const { PREBUILD = '', DIRECTORY_PATH = '.', TARGET_NAME = 'addon', - NODE_HEADERS_DIRECTORY = path.join(os.tmpdir(), 'prebuilds') + NODE_HEADERS_DIRECTORY = path.join(os.tmpdir(), 'prebuilds'), + NODE_GYP_BUILD_MAJOR = '3' } = process.env +// Prebuild directory and filename conventions differ between node-gyp-build v3 and v4: +// +// v3: prebuilds/${platform}${libc}-${arch}/node-${abi}.node +// e.g. prebuilds/linuxglibc-arm64/node-115.node +// +// v4: prebuilds/${platform}-${arch}/${TARGET_NAME}[.musl].node.[napi|abi${N}].node +// e.g. prebuilds/linux-arm64/dd_pprof.node.abi115.node +// prebuilds/linux-arm64/dd_pprof.musl.node.napi.node +// +// When NODE_GYP_BUILD_MAJOR=4, libc is encoded as a filename tag ('musl' only; +// glibc is the default and needs no tag) rather than in the directory name. + +function prebuildDir () { + if (NODE_GYP_BUILD_MAJOR === '4') { + return `${DIRECTORY_PATH}/prebuilds/${platform}-${arch}` + } + return `${DIRECTORY_PATH}/prebuilds/${platform}${libc}-${arch}` +} + +function prebuildFilename (abi, baseName) { + if (NODE_GYP_BUILD_MAJOR === '4') { + const libcTag = libc === 'musl' ? '.musl' : '' + const abiTag = abi === 'napi' ? '.napi' : `.abi${abi}` + return `${baseName}${libcTag}.node${abiTag}.node` + } + if (abi === 'napi') { + return 'node-napi.node' + } + return `node-${abi}.node` +} + let alpineVersion if (platform === 'linux' && libc === 'musl') { try { @@ -57,7 +89,7 @@ prebuildify() function prebuildify () { fs.mkdirSync(NODE_HEADERS_DIRECTORY, { recursive: true }) - fs.mkdirSync(`${DIRECTORY_PATH}/prebuilds/${platform}${libc}-${arch}`, { recursive: true }) + fs.mkdirSync(prebuildDir(), { recursive: true }) if (PREBUILD) { execSync(PREBUILD, { cwd, stdio, shell }) @@ -124,13 +156,13 @@ function prebuildTarget (arch, target) { const names = fs.readdirSync(`${DIRECTORY_PATH}/build/Release`) for (const name of names) { - const output = `${DIRECTORY_PATH}/prebuilds/${platform}${libc}-${arch}/${name}` - .replace('.node', `-${target.abi}.node`) + const baseName = name.replace(/\.node$/, '') + const output = `${prebuildDir()}/${prebuildFilename(target.abi, baseName)}` fs.copyFileSync(`${DIRECTORY_PATH}/build/Release/${name}`, output) } } else { - const output = `${DIRECTORY_PATH}/prebuilds/${platform}${libc}-${arch}/node-${target.abi}.node` + const output = `${prebuildDir()}/${prebuildFilename(target.abi, TARGET_NAME)}` const input = NAPI_RS === 'true' ? `${DIRECTORY_PATH}/${TARGET_NAME}.node` : `${DIRECTORY_PATH}/build/Release/${TARGET_NAME}.node`