From 28cf45626e3f9f256d5cede841973986daa4417f Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 23 Aug 2024 12:52:17 -0700 Subject: [PATCH 1/3] fix: make postinstall script production specific + check in build script dists --- .gitignore | 1 - package.json | 6 ++- script/build.js | 118 ++++++++++++++++++++++++++++++++++++++++++++ script/prebuild.mjs | 59 ++++++++++++++++++++++ script/utils.js | 30 +++++++++++ 5 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 script/build.js create mode 100644 script/prebuild.mjs create mode 100644 script/utils.js diff --git a/.gitignore b/.gitignore index fbd8dd1e..f1756b28 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ build-tmp-napi-v* test.js .cache/ test/typings-compatibility/ -/script/*js /script/*.d.ts /script/*.d.*ts /script/*js.map diff --git a/package.json b/package.json index d972b065..e911cd2d 100644 --- a/package.json +++ b/package.json @@ -82,8 +82,10 @@ "tsconfig.json" ], "scripts": { - "install": "(npm run build.js || echo __skipping_js_build__) && cross-env npm_config_build_from_source=true aminya-node-gyp-build", - "clean": "shx rm -rf ./build ./lib/ ./prebuilds ./script/*.js ./script/*.mjs ./script/*.js.map ./script/*.mjs.map ./script/*.d.ts ./script/*.d.mts ./script/*.cjs ./scripts/*.cjs.map ./scripts/*.d.cts ./script/*.tsbuildinfo", + "install": "cross-env npm_config_build_from_source=true aminya-node-gyp-build", + "prepare": "pnpm run build.js", + "clean": "shx rm -rf ./build ./lib/ ./prebuilds", + "clean.script": "shx rm -rf ./script/*.js ./script/*.mjs ./script/*.js.map ./script/*.mjs.map ./script/*.d.ts ./script/*.d.mts ./script/*.cjs ./scripts/*.cjs.map ./scripts/*.d.cts ./script/*.tsbuildinfo", "clean.release": "shx rm -rf ./build/Release", "clean.temp": "shx rm -rf ./tmp && shx mkdir -p ./tmp", "build.library": "tsc -p ./src/tsconfig.json", diff --git a/script/build.js b/script/build.js new file mode 100644 index 00000000..0a94c2e2 --- /dev/null +++ b/script/build.js @@ -0,0 +1,118 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const fs_1 = require("fs"); +const shelljs_1 = require("shelljs"); +const utils_js_1 = require("./utils.js"); +const root = (0, path_1.dirname)(__dirname); +function parseOptions() { + return { + zmq_shared: (0, utils_js_1.toBool)(process.env.npm_config_zmq_shared) ?? false, + zmq_draft: (0, utils_js_1.toBool)(process.env.npm_config_zmq_draft) ?? false, + zmq_version: (0, utils_js_1.toString)(process.env.npm_config_zmq_version) ?? + "5657b4586f24ec433930e8ece02ddba7afcf0fe0", + zmq_build_type: (0, utils_js_1.toString)(process.env.npm_config_zmq_build_type) ?? "Release", + arch: (0, utils_js_1.toString)(process.env.npm_config_arch) ?? process.arch, + macosx_deployment_target: (0, utils_js_1.toString)(process.env.npm_config_macosx_deployment_target) ?? "10.15", + }; +} +function main() { + const opts = parseOptions(); + console.log("Building libzmq with options ", opts); + if (opts.zmq_shared) { + return; + } + const src_url = `https://github.com/zeromq/libzmq/archive/${opts.zmq_version}.tar.gz`; + const libzmq_build_prefix = `${root}/build/libzmq-staging`; + const libzmq_install_prefix = `${root}/build/libzmq`; + const installed_artifact = `${libzmq_install_prefix}/lib/libzmq${process.platform === "win32" ? ".lib" : ".a"}`; + const src_dir = `libzmq-${opts.zmq_version}`; + const tarball = `libzmq-${opts.zmq_version}.tar.gz`; + let build_options = ""; + // https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html + if (process.platform === "win32") { + if (opts.zmq_build_type !== "Debug") { + build_options += " -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL"; + } + else { + build_options += " -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebugDLL"; + } + } + build_options += archCMakeOptions(opts); + if (process.platform === "darwin") { + process.env.MACOSX_DEPLOYMENT_TARGET = opts.macosx_deployment_target; + build_options += ` -DCMAKE_OSX_DEPLOYMENT_TARGET=${opts.macosx_deployment_target}`; + } + (0, shelljs_1.mkdir)("-p", libzmq_build_prefix); + (0, shelljs_1.cd)(libzmq_build_prefix); + if ((0, fs_1.existsSync)(installed_artifact)) { + console.log(`Skipping rebuild, found previously built libzmq at ${installed_artifact}`); + return; + } + const execOptions = { fatal: true }; + if ((0, fs_1.existsSync)(tarball)) { + console.log("Found libzmq source; skipping download..."); + } + else { + console.log(`Downloading libzmq source from ${src_url}`); + (0, shelljs_1.exec)(`curl "${src_url}" -fsSL -o "${tarball}"`, execOptions); + } + if (!(0, fs_1.existsSync)(src_dir)) { + (0, shelljs_1.exec)(`tar xzf "${tarball}"`, execOptions); + } + if (opts.zmq_draft) { + console.log("Enabling draft support"); + build_options += " -DENABLE_DRAFTS=ON"; + } + console.log(`Building libzmq ${opts.zmq_build_type}`); + // ClangFormat include causes issues but is not required to build. + const clang_format_file = `${src_dir}/builds/cmake/Modules/ClangFormat.cmake`; + if ((0, fs_1.existsSync)(clang_format_file)) { + (0, fs_1.writeFileSync)(clang_format_file, ""); + } + const cmake_configure = `cmake -S "${src_dir}" -B ./build ${build_options} -DCMAKE_BUILD_TYPE=${opts.zmq_build_type} -DCMAKE_INSTALL_PREFIX="${libzmq_install_prefix}" -DCMAKE_INSTALL_LIBDIR=lib -DBUILD_STATIC=ON -DBUILD_TESTS=OFF -DBUILD_SHARED=OFF -DWITH_DOCS=OFF -DWITH_LIBSODIUM=OFF`; + console.log(cmake_configure); + (0, shelljs_1.exec)(cmake_configure, execOptions); + const cmake_build = `cmake --build ./build --config ${opts.zmq_build_type} --target install --parallel`; + console.log(cmake_build); + (0, shelljs_1.exec)(cmake_build, execOptions); + if (process.platform === "win32") { + // rename libzmq-v143-mt-s-4_3_4.lib to libzmq.lib + const build_file = (0, shelljs_1.find)(`${libzmq_install_prefix}/lib/*.lib`)[0]; + (0, shelljs_1.mv)(build_file, `${libzmq_install_prefix}/lib/libzmq.lib`); + } +} +main(); +function archCMakeOptions(opts) { + const arch = opts.arch.toLowerCase(); + if (process.platform === "win32") { + // CMAKE_GENERATOR_PLATFORM only supported on Windows + // https://cmake.org/cmake/help/latest/variable/CMAKE_GENERATOR_PLATFORM.html + switch (arch) { + case "x86": + case "ia32": { + return " -DCMAKE_GENERATOR_PLATFORM=win32"; + } + default: { + return ` -DCMAKE_GENERATOR_PLATFORM=${arch.toUpperCase()}`; + } + } + } + if (process.platform === "darwin") { + // handle MacOS Arm + switch (arch) { + case "x64": + case "x86_64": { + return ""; + } + case "arm64": { + return ` -DCMAKE_OSX_ARCHITECTURES=${arch}`; + } + default: { + return ""; + } + } + } + return ""; +} +//# sourceMappingURL=build.js.map \ No newline at end of file diff --git a/script/prebuild.mjs b/script/prebuild.mjs new file mode 100644 index 00000000..cea68919 --- /dev/null +++ b/script/prebuild.mjs @@ -0,0 +1,59 @@ +import { execaCommandSync } from "execa"; +import * as buildUtils from "./utils.js"; +const { toString } = buildUtils; +function parserOptions() { + return { + arch: toString(process.env.npm_config_arch) ?? process.arch, + }; +} +async function main() { + const opts = parserOptions(); + console.log("Building distribution binary with options ", opts); + const prebuildArch = getNodearch(opts); + process.env.ARCH = prebuildArch; + process.env.npm_config_arch = prebuildArch; + process.env.npm_config_target_arch = prebuildArch; + process.env.PREBUILD_arch = prebuildArch; + // TODO test the triple feature + if (typeof process.env.TRIPLE === "string") { + const TRIPLE = process.env.TRIPLE; + const GCC = process.env.GCC; + process.env.CC = `${TRIPLE}-gcc-${GCC}`; + process.env.CXX = `${TRIPLE}-g++-${GCC}`; + const STRIP = `${TRIPLE}-strip`; + process.env.PREBUILD_STRIP_BIN = STRIP; + process.env.ZMQ_BUILD_OPTIONS = `--host=${TRIPLE}`; + } + // use the current node version to build the prebuild + // If the distribution for that particular architecture is not available, updated your Node: + // https://nodejs.org/dist/ + const nodeVersion = process.version.replace("v", ""); + let prebuildScript = `prebuildify --napi --arch=${prebuildArch} --strip --tag-libc -t ${nodeVersion}`; + if (typeof process.env.ALPINE_CHROOT === "string") { + prebuildScript = `/alpine/enter-chroot ${prebuildScript}`; + } + execaCommandSync(prebuildScript, { + env: process.env, + shell: true, + windowsHide: true, + stdio: "inherit", + encoding: "utf8", + }); +} +main().catch(e => { + throw e; +}); +function getNodearch(opts) { + switch (opts.arch) { + case "x86": { + return "ia32"; + } + case "x86_64": { + return "x64"; + } + default: { + return opts.arch; + } + } +} +//# sourceMappingURL=prebuild.mjs.map \ No newline at end of file diff --git a/script/utils.js b/script/utils.js new file mode 100644 index 00000000..2489e4fd --- /dev/null +++ b/script/utils.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toString = exports.toBool = void 0; +function toBool(value) { + switch (value) { + case "true": + case "1": + return true; + case "false": + case "0": + return false; + case undefined: + case "": + return undefined; + default: + throw new Error(`Invalid boolean value: ${value}`); + } +} +exports.toBool = toBool; +function toString(value) { + switch (value) { + case undefined: + case "": + return undefined; + default: + return value; + } +} +exports.toString = toString; +//# sourceMappingURL=utils.js.map \ No newline at end of file From db5abfc1628f0166e391082d5f812590e0bf6d98 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 23 Aug 2024 13:01:33 -0700 Subject: [PATCH 2/3] chore: run downlevel-ts script for older TypeScript compatibility --- package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index e911cd2d..867dafc0 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,10 @@ "version": "6.0.2", "description": "Next-generation ZeroMQ bindings for Node.js", "main": "lib/index.js", - "types": "lib/index.d.ts", "type": "commonjs", + "types": "lib/index.d.ts", "typesVersions": { - ">=3.7": { + "<3.7": { "lib/*": [ "lib/ts3.7/*" ] @@ -88,7 +88,8 @@ "clean.script": "shx rm -rf ./script/*.js ./script/*.mjs ./script/*.js.map ./script/*.mjs.map ./script/*.d.ts ./script/*.d.mts ./script/*.cjs ./scripts/*.cjs.map ./scripts/*.d.cts ./script/*.tsbuildinfo", "clean.release": "shx rm -rf ./build/Release", "clean.temp": "shx rm -rf ./tmp && shx mkdir -p ./tmp", - "build.library": "tsc -p ./src/tsconfig.json", + "build.library": "tsc -p ./src/tsconfig.json && run-s build.downlevel", + "build.downlevel": "downlevel-dts ./lib ./lib/ts3.7", "build.script": "tsc -p ./script/tsconfig.esm.json && tsc -p ./script/tsconfig.json", "build.js": "run-p build.script build.library", "build.doc": "typedoc --options ./typedoc.json && minify-all -s docs-unminified -d docs --jsCompressor terser && shx rm -rf docs-unminified", From dbcb9186ac46fb1c49d7ef9683bb259792bf7c31 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 23 Aug 2024 13:08:35 -0700 Subject: [PATCH 3/3] fix: include typescript 3.7 itself in typesVersion [skip ci] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 867dafc0..fc926c66 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "commonjs", "types": "lib/index.d.ts", "typesVersions": { - "<3.7": { + "<=3.7": { "lib/*": [ "lib/ts3.7/*" ]