From d8700c9777b4324cd06b9751aa446a4f278da244 Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 9 Oct 2025 08:26:58 -0700 Subject: [PATCH 01/21] upgrade to openssl 3.0 --- generate/templates/templates/binding.gyp | 5 ++-- utils/acquireOpenSSL.mjs | 13 ++++++++--- ...01-linux-force_getentropy_dso_lookup.patch | 23 ------------------- 3 files changed, 12 insertions(+), 29 deletions(-) delete mode 100644 vendor/patches/openssl/001-linux-force_getentropy_dso_lookup.patch diff --git a/generate/templates/templates/binding.gyp b/generate/templates/templates/binding.gyp index 61cad0cb5..b5e189c32 100644 --- a/generate/templates/templates/binding.gyp +++ b/generate/templates/templates/binding.gyp @@ -160,9 +160,8 @@ "<(electron_openssl_root)/include" ], "libraries": [ - # this order is significant on centos7 apparently... - "<(electron_openssl_root)/lib/libssl.a", - "<(electron_openssl_root)/lib/libcrypto.a" + "<(electron_openssl_root)/lib64/libssl.a", + "<(electron_openssl_root)/lib64/libcrypto.a" ] }], ["<(is_electron) == 1 and <(electron_openssl_static) != 1", { diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index 1d83f540b..f16c62e15 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -14,7 +14,7 @@ const pipeline = promisify(stream.pipeline); import packageJson from '../package.json' with { type: "json" }; -const OPENSSL_VERSION = "1.1.1t"; +const OPENSSL_VERSION = "3.0.18"; const win32BatPath = path.join(import.meta.dirname, "build-openssl.bat"); const vendorPath = path.resolve(import.meta.dirname, "..", "vendor"); const opensslPatchPath = path.join(vendorPath, "patches", "openssl"); @@ -56,6 +56,8 @@ const makeHashVerifyOnFinal = (expected) => (digest) => { // currently this only needs to be done on linux const applyOpenSSLPatches = async (buildCwd, operatingSystem) => { try { + await fs.access(opensslPatchPath); + for (const patchFilename of await fs.readdir(opensslPatchPath)) { const patchTarget = patchFilename.split("-")[1]; if (patchFilename.split(".").pop() === "patch" && (patchTarget === operatingSystem || patchTarget === "all")) { @@ -66,6 +68,11 @@ const applyOpenSSLPatches = async (buildCwd, operatingSystem) => { } } } catch(e) { + if (e.code === "ENOENT") { + // no patches to apply + return; + } + console.log("Patch application failed: ", e); throw e; } @@ -121,7 +128,7 @@ const buildLinux = async (buildCwd) => { // dependency on the system libssl/libcrypto which causes symbol conflicts and segfaults. // To fix this we need to hide all the openssl symbols to prevent them from being overridden // by the runtime linker. - "-fvisibility=hidden", + // "-fvisibility=hidden", // compile static libraries "no-shared", // disable ssl2, ssl3, and compression @@ -259,7 +266,7 @@ const buildOpenSSLIfNecessary = async ({ const openSSLUrl = getOpenSSLSourceUrl(openSSLVersion); const openSSLSha256Url = getOpenSSLSourceSha256Url(openSSLVersion); - const openSSLSha256 = (await got(openSSLSha256Url)).body.trim(); + const openSSLSha256 = (await got(openSSLSha256Url)).body.trim().split(' ')[0]; const downloadStream = got.stream(openSSLUrl); downloadStream.on("downloadProgress", makeOnStreamDownloadProgress()); diff --git a/vendor/patches/openssl/001-linux-force_getentropy_dso_lookup.patch b/vendor/patches/openssl/001-linux-force_getentropy_dso_lookup.patch deleted file mode 100644 index 6802c7fa5..000000000 --- a/vendor/patches/openssl/001-linux-force_getentropy_dso_lookup.patch +++ /dev/null @@ -1,23 +0,0 @@ -openssl doesn't have any sort of guard around this section of code other than -checking if we're compiling an elf binary on gnu linux. the syscall wrapper -`getentropy` is only available on glibc >= 2.25 which is a problem if we want -to support platforms like centos7 which ships with glibc 2.17. Attempting to -load this code on centos7 causes a runtime "undefined symbol error since glibc -doesn't provide it. -luckily openssl provides a backup lookup method in form of a dlopen call but -theres no way to configure for it, hence this patch. -Note further that centos7 doesn't have this function or the syscall it wraps -so the symbol lookup will fail and it will fallback to reading from /dev/random. -hence this patch just fixes compilation. -author: JZA ---- crypto/rand/rand_unix.c -+++ crypto/rand/rand_unix.c -@@ -372,7 +372,7 @@ static ssize_t syscall_random(void *buf, size_t buflen) - * Note: Sometimes getentropy() can be provided but not implemented - * internally. So we need to check errno for ENOSYS - */ --# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) -+# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) && 0 - extern int getentropy(void *buffer, size_t length) __attribute__((weak)); - - if (getentropy != NULL) { From 453920ae867565fe7ba8ffeab1c515dac4082bef Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 16 Oct 2025 10:34:12 -0700 Subject: [PATCH 02/21] fix workflow matrix windows arm64 will be done in a follow-up pr --- .github/workflows/build-openssl-packages.yml | 24 +++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index 426ca0652..1ecb3366b 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -9,8 +9,15 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13, windows-2022] - arch: [x64, arm64] + include: + - os: windows-latest + arch: x64 + # - os: windows-latest + # arch: arm64 + - os: macos-15 + arch: x64 + - os: macos-15-intel + arch: arm64 fail-fast: false steps: @@ -21,12 +28,23 @@ jobs: uses: actions/setup-node@v4 with: node-version: 22 - architecture: ${{ matrix.arch }} + + - name: Install Toolchain + if: matrix.os == 'windows-latest' && matrix.arch == 'arm64' + uses: msys2/setup-msys2@v2 + with: + update: true + install: > + mingw-w64-aarch64-toolchain + mingw-w64-aarch64-cmake + mingw-w64-aarch64-ninja - name: Install dependencies run: npm install - name: Build OpenSSL packages + env: + TARGET_ARCH: ${{ matrix.arch }} run: node utils/acquireOpenSSL.js - name: Push OpenSSL package to S3 From a83b09864c180433957fdcda403308ce088bc3cf Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 16 Oct 2025 10:57:55 -0700 Subject: [PATCH 03/21] woops --- .github/workflows/build-openssl-packages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index 1ecb3366b..6df004d63 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -14,9 +14,9 @@ jobs: arch: x64 # - os: windows-latest # arch: arm64 - - os: macos-15 - arch: x64 - os: macos-15-intel + arch: x64 + - os: macos-15 arch: arm64 fail-fast: false From 4c6a8a6ce0638d4cbb1a8711f140da2fb9ca6e0b Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 16 Oct 2025 11:48:42 -0700 Subject: [PATCH 04/21] downgrade runners for now --- .github/workflows/build-openssl-packages.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index 6df004d63..fb6613b9d 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -14,9 +14,9 @@ jobs: arch: x64 # - os: windows-latest # arch: arm64 - - os: macos-15-intel + - os: macos-13 arch: x64 - - os: macos-15 + - os: macos-14 arch: arm64 fail-fast: false @@ -45,11 +45,11 @@ jobs: - name: Build OpenSSL packages env: TARGET_ARCH: ${{ matrix.arch }} - run: node utils/acquireOpenSSL.js + run: node utils/acquireOpenSSL.mjs - name: Push OpenSSL package to S3 env: node_pre_gyp_bucket: ${{ secrets.node_pre_gyp_bucket }} AWS_ACCESS_KEY_ID: ${{ secrets.node_pre_gyp_accessKeyId }} AWS_SECRET_ACCESS_KEY: ${{ secrets.node_pre_gyp_secretAccessKey }} - run: node utils/uploadOpenSSL.js \ No newline at end of file + run: node utils/uploadOpenSSL.mjs \ No newline at end of file From f5e83808a440ecbd2eb23d757777ebe362952c71 Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 16 Oct 2025 12:00:02 -0700 Subject: [PATCH 05/21] force build openssl package --- .github/workflows/build-openssl-packages.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index fb6613b9d..bfb2e0088 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -45,6 +45,7 @@ jobs: - name: Build OpenSSL packages env: TARGET_ARCH: ${{ matrix.arch }} + NODEGIT_OPENSSL_BUILD_PACKAGE: 1 run: node utils/acquireOpenSSL.mjs - name: Push OpenSSL package to S3 From fc1aecff96465166ec8dc1fb8458a5fc4bf2d349 Mon Sep 17 00:00:00 2001 From: John Alden Date: Fri, 24 Oct 2025 11:54:30 -0700 Subject: [PATCH 06/21] set macos deployment target --- .github/workflows/build-openssl-packages.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index bfb2e0088..b3d3cc67c 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -46,6 +46,7 @@ jobs: env: TARGET_ARCH: ${{ matrix.arch }} NODEGIT_OPENSSL_BUILD_PACKAGE: 1 + OPENSSL_MACOS_DEPLOYMENT_TARGET: "11.0" run: node utils/acquireOpenSSL.mjs - name: Push OpenSSL package to S3 @@ -53,4 +54,4 @@ jobs: node_pre_gyp_bucket: ${{ secrets.node_pre_gyp_bucket }} AWS_ACCESS_KEY_ID: ${{ secrets.node_pre_gyp_accessKeyId }} AWS_SECRET_ACCESS_KEY: ${{ secrets.node_pre_gyp_secretAccessKey }} - run: node utils/uploadOpenSSL.mjs \ No newline at end of file + run: node utils/uploadOpenSSL.mjs From 1689cb8aca22fab2464837e0702becdbbe8bac3e Mon Sep 17 00:00:00 2001 From: John Alden Date: Wed, 5 Nov 2025 21:06:21 -0700 Subject: [PATCH 07/21] update macos runner images --- .github/workflows/build-openssl-packages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index b3d3cc67c..bd584002d 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -14,9 +14,9 @@ jobs: arch: x64 # - os: windows-latest # arch: arm64 - - os: macos-13 + - os: macos-15 arch: x64 - - os: macos-14 + - os: macos-15-intel arch: arm64 fail-fast: false From d51bb6f98f5f074d4299460c65ffa03f51524282 Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 6 Nov 2025 10:00:44 -0700 Subject: [PATCH 08/21] disable ui on macos --- utils/acquireOpenSSL.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index f16c62e15..bc6b93264 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -93,6 +93,8 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => { "no-ssl2", "no-ssl3", "no-comp", + // disable tty ui since it fails a bunch of tests on GHA runners and we're just gonna link anyways + "no-ui-console", // set install directory `--prefix="${extractPath}"`, `--openssldir="${extractPath}"`, From bfffac9f9dfdf3646d119961c81684a52ba5b094 Mon Sep 17 00:00:00 2001 From: John Alden Date: Fri, 24 Oct 2025 12:09:03 -0700 Subject: [PATCH 09/21] update visual studio version selection --- utils/acquireOpenSSL.mjs | 65 ++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index bc6b93264..dd76021a8 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -7,7 +7,6 @@ import tar from "tar-fs"; import zlib from "zlib"; import { createWriteStream, promises as fs } from "fs"; import { performance } from "perf_hooks"; -import { fileURLToPath } from 'url'; import { promisify } from "util"; const pipeline = promisify(stream.pipeline); @@ -168,18 +167,60 @@ const buildWin32 = async (buildCwd, vsBuildArch) => { throw new Error("Expected vsBuildArch to be specified"); } - const programFilesPath = (process.arch === "x64" - ? process.env["ProgramFiles(x86)"] - : process.env.ProgramFiles) || "C:\\Program Files"; - const vcvarsallPath = process.env.npm_config_vcvarsall_path || `${ - programFilesPath - }\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Auxiliary\\Build\\vcvarsall.bat`; - try { - await fs.stat(vcvarsallPath); - } catch { - throw new Error(`vcvarsall.bat not found at ${vcvarsallPath}`); + const exists = (filePath) => fs.stat(filePath).then(() => true).catch(() => false); + + let vcvarsallPath = undefined; + + if (process.env.npm_config_vcvarsall_path && await exists(process.env.npm_config_vcvarsall_path)) { + vcvarsallPath = process.env.npm_config_vcvarsall_path; + } else { + const potentialMsvsPaths = []; + + // GYP_MSVS_OVERRIDE_PATH is set by node-gyp so this should cover most cases + if (process.env.GYP_MSVS_OVERRIDE_PATH) { + potentialMsvsPaths.push(process.env.GYP_MSVS_OVERRIDE_PATH); + } + + const packageTypes = ["BuildTools", "Community", "Professional", "Enterprise"]; + const versions = ["2022", "2019"] + + const computePossiblePaths = (parentPath) => { + let possiblePaths = [] + for (const packageType of packageTypes) { + for (const version of versions) { + possiblePaths.push(path.join(parentPath, version, packageType)); + } + } + + return possiblePaths; + } + + if (process.env["ProgramFiles(x86)"]) { + const parentPath = path.join(process.env["ProgramFiles(x86)"], 'Microsoft Visual Studio'); + potentialMsvsPaths.push(...computePossiblePaths(parentPath)); + } + + if (process.env.ProgramFiles) { + const parentPath = path.join(process.env.ProgramFiles, 'Microsoft Visual Studio'); + potentialMsvsPaths.push(...computePossiblePaths(parentPath)); + } + + for (const potentialPath of potentialMsvsPaths) { + const wholePath = path.join(potentialPath, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat'); + console.log("checking", wholePath); + if (await exists(wholePath)) { + vcvarsallPath = wholePath; + break; + } + } + + if (!vcvarsallPath) { + throw new Error(`vcvarsall.bat not found`); + } } + console.log('using', vcvarsallPath); + let vcTarget; switch (vsBuildArch) { case "x64": { @@ -401,7 +442,7 @@ const acquireOpenSSL = async () => { let macOsDeploymentTarget; if (process.platform === "darwin") { - macOsDeploymentTarget = process.argv[2]; + macOsDeploymentTarget = process.argv[2] ?? process.env.OPENSSL_MACOS_DEPLOYMENT_TARGET if (!macOsDeploymentTarget || !macOsDeploymentTarget.match(/\d+\.\d+/)) { throw new Error(`Invalid macOsDeploymentTarget: ${macOsDeploymentTarget}`); } From 424cad31238c1fafc9eb7d0386d5ce9a5e28ed72 Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 6 Nov 2025 11:55:33 -0700 Subject: [PATCH 10/21] fix upload --- utils/acquireOpenSSL.mjs | 8 +++++--- utils/uploadOpenSSL.mjs | 17 +++++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index dd76021a8..047b95cb7 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -382,7 +382,7 @@ const downloadOpenSSLIfNecessary = async ({ console.log("Download finished."); } -const getOpenSSLPackageName = () => { +export const getOpenSSLPackageName = () => { let arch = process.arch; if (process.platform === "win32" && ( process.arch === "ia32" || process.env.NODEGIT_VS_BUILD_ARCH === "x86" @@ -393,6 +393,8 @@ const getOpenSSLPackageName = () => { return `openssl-${OPENSSL_VERSION}-${process.platform}-${arch}.tar.gz`; } +export const getOpenSSLPackagePath = () => path.join(import.meta.dirname, getOpenSSLPackageName()); + const getOpenSSLPackageUrl = () => `${packageJson.binary.host}${getOpenSSLPackageName()}`; const buildPackage = async () => { @@ -416,7 +418,7 @@ const buildPackage = async () => { new HashVerify("sha256", (digest) => { resolve(digest); }), - createWriteStream(getOpenSSLPackageName()) + createWriteStream(getOpenSSLPackagePath()) ); const digest = await promise; await fs.writeFile(`${getOpenSSLPackageName()}.sha256`, digest); @@ -477,5 +479,5 @@ if (process.argv[1] === import.meta.filename) { catch(error) { console.error("Acquire OpenSSL failed: ", error); process.exit(1); - }; + } } diff --git a/utils/uploadOpenSSL.mjs b/utils/uploadOpenSSL.mjs index 784379cb6..86495e98e 100644 --- a/utils/uploadOpenSSL.mjs +++ b/utils/uploadOpenSSL.mjs @@ -2,26 +2,27 @@ import aws from 'aws-sdk'; import fs from "fs"; import path from "path"; -import pkgJson from './package.json' assert { type: "json" }; -import { getOpenSSLPackageName } from './acquireOpenSSL'; +import pkgJson from '../package.json' with { type: "json" }; +import { getOpenSSLPackagePath, getOpenSSLPackageName } from './acquireOpenSSL.mjs'; const s3 = new aws.S3(); -const uploadBinaryToS3 = (binaryName, bucketName, pathToFile) => +const uploadBinaryToS3 = (fileName, bucketName, pathToFile) => s3.upload({ Body: fs.createReadStream(pathToFile), Bucket: bucketName, - Key: binaryName, + Key: fileName, ACL: "public-read" }).promise(); export const uploadOpenSSL = async () => { - const binaryName = getOpenSSLPackageName(); - const pathToFile = path.join(import.meta.dirname, binaryName); - return uploadBinaryToS3(binaryName, pkgJson.binary.bucket_name, pathToFile); + const packageName = path.basename(getOpenSSLPackageName()); + const packagePath = getOpenSSLPackagePath(); + console.log(`Uploading ${packagePath} to s3://${pkgJson.binary.bucket_name}/${packageName}`); + return uploadBinaryToS3(packageName, pkgJson.binary.bucket_name, packagePath); }; -if (require.main === module) { +if (process.argv[1] === import.meta.filename) { uploadOpenSSL().catch((error) => { console.error('Push to S3 failed: ', error); process.exit(1); From c60718c1e22542ec056936ed6b15ba0a8730d9ee Mon Sep 17 00:00:00 2001 From: Bill Mill Date: Sun, 9 Nov 2025 09:37:24 -0500 Subject: [PATCH 11/21] fix: correct macos arch labels macos-15-intel is x64 and macos-15 is arm64, per the docs: https://github.com/actions/runner-images#available-images --- .github/workflows/build-openssl-packages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index bd584002d..79cd94ade 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -15,9 +15,9 @@ jobs: # - os: windows-latest # arch: arm64 - os: macos-15 - arch: x64 - - os: macos-15-intel arch: arm64 + - os: macos-15-intel + arch: x64 fail-fast: false steps: From 9bc5b39616e8180f96014645a68de556185e7589 Mon Sep 17 00:00:00 2001 From: John Alden Date: Mon, 10 Nov 2025 20:55:51 -0700 Subject: [PATCH 12/21] fix missing git_email_create_from_diff not sure why this error only happened when building for electron --- generate/input/descriptor.json | 5 +++ generate/input/libgit2-supplement.json | 51 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json index 889b792e7..99837534d 100644 --- a/generate/input/descriptor.json +++ b/generate/input/descriptor.json @@ -1526,6 +1526,11 @@ } } }, + "email": { + "cDependencies": [ + "git2/sys/email.h" + ] + }, "email_create_options": { "hasConstructor": true }, diff --git a/generate/input/libgit2-supplement.json b/generate/input/libgit2-supplement.json index 09433e7fa..742216f03 100644 --- a/generate/input/libgit2-supplement.json +++ b/generate/input/libgit2-supplement.json @@ -294,6 +294,54 @@ "isErrorCode": true } }, + "git_email_create_from_diff": { + "file": "sys/email.h", + "type": "function", + "isAsync": true, + "group": "email", + "args": [ + { + "name": "out", + "type": "git_buf *" + }, + { + "name": "diff", + "type": "git_diff *" + }, + { + "name": "patch_idx", + "type": "size_t" + }, + { + "name": "patch_count", + "type": "size_t" + }, + { + "name": "commit_id", + "type": "const git_oid *" + }, + { + "name": "summary", + "type": "const char *" + }, + { + "name": "body", + "type": "const char *" + }, + { + "name": "author", + "type": "const git_signature *" + }, + { + "name": "opts", + "type": "git_email_create_options *" + } + ], + "return": { + "type": "int", + "isErrorCode": true + } + }, "git_diff_get_perfdata": { "file": "sys/diff.h", "args": [ @@ -2619,6 +2667,9 @@ "blame": [ "git_blame_file" ], + "email": [ + "git_email_create_from_diff" + ], "note": [ "git_note_author", "git_note_commit_create", From ad00c9a86319660a06f10d5da6b67b7c1f22a3d4 Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 16 Oct 2025 11:21:07 -0700 Subject: [PATCH 13/21] natively compile for arm64 --- lifecycleScripts/install.js | 4 ++- utils/acquireOpenSSL.mjs | 58 +++++++++++++++++++++++-------------- vendor/libgit2.gyp | 21 ++++++++++---- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/lifecycleScripts/install.js b/lifecycleScripts/install.js index ddbb90e9c..e7f90ee90 100755 --- a/lifecycleScripts/install.js +++ b/lifecycleScripts/install.js @@ -30,7 +30,9 @@ module.exports = function install() { return new Promise(function(resolve, reject) { const gypPath = path.join(__dirname, "..", "node_modules", "node-gyp", "bin", "node-gyp.js"); - var spawnedNodePreGyp = spawn(nodePreGyp, args, { + + const nodePreGypPath = path.resolve(path.join(__dirname, "..", "node_modules", "@mapbox", "node-pre-gyp", "bin", nodePreGyp)); + var spawnedNodePreGyp = spawn(nodePreGypPath, args, { env: { ...process.env, npm_config_node_gyp: gypPath diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index 047b95cb7..124860506 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -19,6 +19,26 @@ const vendorPath = path.resolve(import.meta.dirname, "..", "vendor"); const opensslPatchPath = path.join(vendorPath, "patches", "openssl"); const extractPath = path.join(vendorPath, "openssl"); +const convertArch = (archStr) => { + const convertedArch = { + 'ia32': 'x86', + 'x86': 'x86', + 'x64': 'x64', + 'arm64': 'arm64' + }[archStr]; + + if (!convertedArch) { + throw new Error('unsupported architecture'); + } + + return convertedArch; +} + +const hostArch = convertArch(process.arch); +const targetArch = process.env.npm_config_arch + ? convertArch(process.env.npm_config_arch) + : hostArch; + const pathsToIncludeForPackage = [ "include", "lib" ]; @@ -82,8 +102,10 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => { throw new Error("Expected macOsDeploymentTarget to be specified"); } + const buildConfig = targetArch === "x64" ? "darwin64-x86_64-cc" : "darwin64-arm64-cc"; + const configureArgs = [ - process.arch === "x64" ? "darwin64-x86_64-cc" : "darwin64-arm64-cc", + buildConfig, // speed up ecdh on little-endian platforms with 128bit int support "enable-ec_nistp_64_gcc_128", // compile static libraries @@ -107,7 +129,7 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => { await applyOpenSSLPatches(buildCwd, "darwin"); - // only build the libraries, not the tests/fuzzer or apps + // only build the libraries, not the fuzzer or apps await execPromise("make build_libs", { cwd: buildCwd }, { pipeOutput: true }); @@ -123,8 +145,10 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => { }; const buildLinux = async (buildCwd) => { + const buildConfig = targetArch === "x64" ? "linux-x86_64" : "linux-aarch64"; + const configureArgs = [ - "linux-x86_64", + buildConfig, // Electron(at least on centos7) imports the libcups library at runtime, which has a // dependency on the system libssl/libcrypto which causes symbol conflicts and segfaults. // To fix this we need to hide all the openssl symbols to prevent them from being overridden @@ -146,7 +170,7 @@ const buildLinux = async (buildCwd) => { await applyOpenSSLPatches(buildCwd, "linux"); - // only build the libraries, not the tests/fuzzer or apps + // only build the libraries, not the fuzzer or apps await execPromise("make build_libs", { cwd: buildCwd }, { pipeOutput: true }); @@ -232,6 +256,11 @@ const buildWin32 = async (buildCwd, vsBuildArch) => { vcTarget = "VC-WIN32"; break; } + + case "arm64": { + vcTarget = "VC-WIN64-ARM"; + break; + } default: { throw new Error(`Unknown vsBuildArch: ${vsBuildArch}`); @@ -382,15 +411,8 @@ const downloadOpenSSLIfNecessary = async ({ console.log("Download finished."); } -export const getOpenSSLPackageName = () => { - let arch = process.arch; - if (process.platform === "win32" && ( - process.arch === "ia32" || process.env.NODEGIT_VS_BUILD_ARCH === "x86" - )) { - arch = "x86"; - } - - return `openssl-${OPENSSL_VERSION}-${process.platform}-${arch}.tar.gz`; +const getOpenSSLPackageName = () => { + return `openssl-${OPENSSL_VERSION}-${process.platform}-${targetArch}.tar.gz`; } export const getOpenSSLPackagePath = () => path.join(import.meta.dirname, getOpenSSLPackageName()); @@ -450,18 +472,10 @@ const acquireOpenSSL = async () => { } } - let vsBuildArch; - if (process.platform === "win32") { - vsBuildArch = process.env.NODEGIT_VS_BUILD_ARCH || (process.arch === "x64" ? "x64" : "x86"); - if (!["x64", "x86"].includes(vsBuildArch)) { - throw new Error(`Invalid vsBuildArch: ${vsBuildArch}`); - } - } - await buildOpenSSLIfNecessary({ openSSLVersion: OPENSSL_VERSION, macOsDeploymentTarget, - vsBuildArch + vsBuildArch: process.platform === "win32" ? targetArch : undefined }); if (process.env.NODEGIT_OPENSSL_BUILD_PACKAGE) { await buildPackage(); diff --git a/vendor/libgit2.gyp b/vendor/libgit2.gyp index a155fb67f..f141e4d2d 100644 --- a/vendor/libgit2.gyp +++ b/vendor/libgit2.gyp @@ -315,13 +315,22 @@ # Workaround of a strange bug: # TargetMachine + static_library + x64 = nothing. "conditions": [ - ["target_arch=='x64'", { - "VCLibrarianTool": { - "AdditionalOptions": [ - "/MACHINE:X64", - ], + [ + "target_arch=='x64'", { + "VCLibrarianTool": { + "AdditionalOptions": [ + "/MACHINE:X64", + ], + }, + }, + "target_arch=='arm64'", { + "VCLibrarianTool": { + "AdditionalOptions": [ + "/MACHINE:ARM64", + ], + }, }, - }, { + { "VCLibrarianTool": { "AdditionalOptions": [ "/MACHINE:x86", From cd1c5dba01b4e928d79c0225b844bc412ef943c8 Mon Sep 17 00:00:00 2001 From: John Alden Date: Mon, 10 Nov 2025 19:16:38 -0700 Subject: [PATCH 14/21] better node-pre-gyp path detection --- lifecycleScripts/install.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lifecycleScripts/install.js b/lifecycleScripts/install.js index e7f90ee90..96e47afbe 100755 --- a/lifecycleScripts/install.js +++ b/lifecycleScripts/install.js @@ -2,6 +2,8 @@ var buildFlags = require("../utils/buildFlags"); var spawn = require("child_process").spawn; var path = require("path"); +const nodePreGypModulePath = require.resolve("@mapbox/node-pre-gyp"); + module.exports = function install() { console.log("[nodegit] Running install script"); @@ -31,7 +33,8 @@ module.exports = function install() { return new Promise(function(resolve, reject) { const gypPath = path.join(__dirname, "..", "node_modules", "node-gyp", "bin", "node-gyp.js"); - const nodePreGypPath = path.resolve(path.join(__dirname, "..", "node_modules", "@mapbox", "node-pre-gyp", "bin", nodePreGyp)); + const nodePreGypPath = path.resolve(path.dirname(nodePreGypModulePath), path.join("..", "bin", nodePreGyp)); + console.log("node-pre-gyp path", nodePreGypPath); var spawnedNodePreGyp = spawn(nodePreGypPath, args, { env: { ...process.env, From 4978cbb51646b8818d88a943fa31205b08a35534 Mon Sep 17 00:00:00 2001 From: John Alden Date: Wed, 12 Nov 2025 21:18:24 -0700 Subject: [PATCH 15/21] allow cross-compiling openssl for windows --- utils/acquireOpenSSL.mjs | 76 +++++++++++++++++++++++++--------------- utils/build-openssl.bat | 11 +++++- 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index 124860506..6a3d26252 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -1,4 +1,5 @@ import crypto from "crypto"; +import { spawn } from "child_process"; import execPromise from "./execPromise.js"; import got from "got"; import path from "path"; @@ -19,6 +20,8 @@ const vendorPath = path.resolve(import.meta.dirname, "..", "vendor"); const opensslPatchPath = path.join(vendorPath, "patches", "openssl"); const extractPath = path.join(vendorPath, "openssl"); +const exists = (filePath) => fs.stat(filePath).then(() => true).catch(() => false); + const convertArch = (archStr) => { const convertedArch = { 'ia32': 'x86', @@ -186,13 +189,7 @@ const buildLinux = async (buildCwd) => { }, { pipeOutput: true }); }; -const buildWin32 = async (buildCwd, vsBuildArch) => { - if (!vsBuildArch) { - throw new Error("Expected vsBuildArch to be specified"); - } - - const exists = (filePath) => fs.stat(filePath).then(() => true).catch(() => false); - +const buildWin32 = async (buildCwd) => { let vcvarsallPath = undefined; if (process.env.npm_config_vcvarsall_path && await exists(process.env.npm_config_vcvarsall_path)) { @@ -243,34 +240,57 @@ const buildWin32 = async (buildCwd, vsBuildArch) => { } } - console.log('using', vcvarsallPath); - let vcTarget; - switch (vsBuildArch) { - case "x64": { + switch (targetArch) { + case "x64": vcTarget = "VC-WIN64A"; break; - } - case "x86": { + case "x86": vcTarget = "VC-WIN32"; break; - } - case "arm64": { + case "arm64": vcTarget = "VC-WIN64-ARM"; break; - } - - default: { - throw new Error(`Unknown vsBuildArch: ${vsBuildArch}`); - } } - await execPromise(`"${win32BatPath}" "${vcvarsallPath}" ${vsBuildArch} ${vcTarget}`, { - cwd: buildCwd, - maxBuffer: 10 * 1024 * 1024 // we should really just use spawn - }, { pipeOutput: true }); + let vsBuildArch = hostArch === targetArch + ? hostArch + : `${hostArch}_${targetArch}`; + + console.log("Using vcvarsall.bat at: ", vcvarsallPath); + console.log("Using vsBuildArch: ", vsBuildArch); + console.log("Using vcTarget: ", vcTarget); + + await new Promise((resolve, reject) => { + const buildProcess = spawn(`"${win32BatPath}" "${vcvarsallPath}" ${vsBuildArch} ${vcTarget}`, { + cwd: buildCwd, + shell: process.platform === "win32", + env: { + ...process.env, + NODEGIT_SKIP_TESTS: targetArch !== hostArch ? "1" : undefined + } + }); + + buildProcess.stdout.on("data", function(data) { + console.info(data.toString().trim()); + }); + + buildProcess.stderr.on("data", function(data) { + console.error(data.toString().trim()); + }); + + buildProcess.on("close", function(code) { + if (!code) { + resolve(); + } else { + reject(code); + } + }); + }); + + }; const removeOpenSSLIfOudated = async (openSSLVersion) => { @@ -314,8 +334,7 @@ const makeOnStreamDownloadProgress = () => { const buildOpenSSLIfNecessary = async ({ macOsDeploymentTarget, - openSSLVersion, - vsBuildArch + openSSLVersion }) => { if (process.platform !== "darwin" && process.platform !== "win32" && process.platform !== "linux") { console.log(`Skipping OpenSSL build, not required on ${process.platform}`); @@ -359,7 +378,7 @@ const buildOpenSSLIfNecessary = async ({ } else if (process.platform === "linux") { await buildLinux(buildCwd); } else if (process.platform === "win32") { - await buildWin32(buildCwd, vsBuildArch); + await buildWin32(buildCwd); } else { throw new Error(`Unknown platform: ${process.platform}`); } @@ -474,8 +493,7 @@ const acquireOpenSSL = async () => { await buildOpenSSLIfNecessary({ openSSLVersion: OPENSSL_VERSION, - macOsDeploymentTarget, - vsBuildArch: process.platform === "win32" ? targetArch : undefined + macOsDeploymentTarget }); if (process.env.NODEGIT_OPENSSL_BUILD_PACKAGE) { await buildPackage(); diff --git a/utils/build-openssl.bat b/utils/build-openssl.bat index 6e146cf89..af8063d7c 100644 --- a/utils/build-openssl.bat +++ b/utils/build-openssl.bat @@ -1,9 +1,18 @@ +rem Build OpenSSL for Windows +rem %1 - path to vcvarsall.bat +rem %2 - architecture argument for vcvarsall.bat +rem %3 - OpenSSL Configure target + @call %1 %2 perl .\Configure %3 no-shared no-ssl2 no-ssl3 no-comp --prefix="%cd%\.." --openssldir="%cd%\.." || goto :error nmake || goto :error -nmake test || goto :error + +if "%NODEGIT_SKIP_TESTS%" NEQ "1" ( + nmake test || goto :error +) + nmake install || goto :error goto :EOF From 972a08333578e8988a0badb91109310afa793bd9 Mon Sep 17 00:00:00 2001 From: John Alden Date: Wed, 12 Nov 2025 21:19:23 -0700 Subject: [PATCH 16/21] add windows arm64 to openssl package workflow --- .github/workflows/build-openssl-packages.yml | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index 79cd94ade..1437e6d91 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -10,10 +10,10 @@ jobs: strategy: matrix: include: + - os: windows-latest + arch: arm64 - os: windows-latest arch: x64 - # - os: windows-latest - # arch: arm64 - os: macos-15 arch: arm64 - os: macos-15-intel @@ -29,22 +29,12 @@ jobs: with: node-version: 22 - - name: Install Toolchain - if: matrix.os == 'windows-latest' && matrix.arch == 'arm64' - uses: msys2/setup-msys2@v2 - with: - update: true - install: > - mingw-w64-aarch64-toolchain - mingw-w64-aarch64-cmake - mingw-w64-aarch64-ninja - - name: Install dependencies run: npm install - name: Build OpenSSL packages env: - TARGET_ARCH: ${{ matrix.arch }} + npm_config_arch: ${{ matrix.arch }} NODEGIT_OPENSSL_BUILD_PACKAGE: 1 OPENSSL_MACOS_DEPLOYMENT_TARGET: "11.0" run: node utils/acquireOpenSSL.mjs From f856f0fde4d50a45e8a4d17ee1c78d866d1a9b72 Mon Sep 17 00:00:00 2001 From: John Alden Date: Wed, 12 Nov 2025 21:43:38 -0700 Subject: [PATCH 17/21] fix package upload --- .github/workflows/build-openssl-packages.yml | 1 + utils/acquireOpenSSL.mjs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index 1437e6d91..7b7a5dea3 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -41,6 +41,7 @@ jobs: - name: Push OpenSSL package to S3 env: + npm_config_arch: ${{ matrix.arch }} node_pre_gyp_bucket: ${{ secrets.node_pre_gyp_bucket }} AWS_ACCESS_KEY_ID: ${{ secrets.node_pre_gyp_accessKeyId }} AWS_SECRET_ACCESS_KEY: ${{ secrets.node_pre_gyp_secretAccessKey }} diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index 6a3d26252..9eb4c73f7 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -430,7 +430,7 @@ const downloadOpenSSLIfNecessary = async ({ console.log("Download finished."); } -const getOpenSSLPackageName = () => { +export const getOpenSSLPackageName = () => { return `openssl-${OPENSSL_VERSION}-${process.platform}-${targetArch}.tar.gz`; } From abc5a6655968f5b3652b216d8b026128558bf1ac Mon Sep 17 00:00:00 2001 From: John Alden Date: Thu, 13 Nov 2025 19:59:52 -0700 Subject: [PATCH 18/21] upload sha256 files aswell --- utils/uploadOpenSSL.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/uploadOpenSSL.mjs b/utils/uploadOpenSSL.mjs index 86495e98e..5de760462 100644 --- a/utils/uploadOpenSSL.mjs +++ b/utils/uploadOpenSSL.mjs @@ -19,7 +19,9 @@ export const uploadOpenSSL = async () => { const packageName = path.basename(getOpenSSLPackageName()); const packagePath = getOpenSSLPackagePath(); console.log(`Uploading ${packagePath} to s3://${pkgJson.binary.bucket_name}/${packageName}`); - return uploadBinaryToS3(packageName, pkgJson.binary.bucket_name, packagePath); + await uploadBinaryToS3(packageName, pkgJson.binary.bucket_name, packagePath); + const sha256PackageName = `${packageName}.sha256`; + await uploadBinaryToS3(sha256PackageName, pkgJson.binary.bucket_name, `${packagePath}.sha256`); }; if (process.argv[1] === import.meta.filename) { From 637d2eb53ff9c21533ad3c3566a15ebd490e50df Mon Sep 17 00:00:00 2001 From: John Alden Date: Fri, 14 Nov 2025 11:33:43 -0700 Subject: [PATCH 19/21] readd openssl fixes missing from PR - give full path to openssl package hash - fix package download url --- utils/acquireOpenSSL.mjs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index 9eb4c73f7..044454026 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -436,7 +436,11 @@ export const getOpenSSLPackageName = () => { export const getOpenSSLPackagePath = () => path.join(import.meta.dirname, getOpenSSLPackageName()); -const getOpenSSLPackageUrl = () => `${packageJson.binary.host}${getOpenSSLPackageName()}`; +const getOpenSSLPackageUrl = () => { + const hostUrl = new URL(packageJson.binary.host); + hostUrl.pathname = getOpenSSLPackageName(); + return hostUrl.toString(); +}; const buildPackage = async () => { let resolve, reject; @@ -462,7 +466,7 @@ const buildPackage = async () => { createWriteStream(getOpenSSLPackagePath()) ); const digest = await promise; - await fs.writeFile(`${getOpenSSLPackageName()}.sha256`, digest); + await fs.writeFile(`${getOpenSSLPackagePath()}.sha256`, digest); }; const acquireOpenSSL = async () => { From 3806c58561103dffb3c9b3909cecbabbe53072fb Mon Sep 17 00:00:00 2001 From: John Alden Date: Fri, 14 Nov 2025 15:36:00 -0700 Subject: [PATCH 20/21] add arm64 to test/release workflow --- .github/workflows/tests.yml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3a2f8cc7a..444a3e960 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -123,7 +123,7 @@ jobs: strategy: matrix: node: [20, 22, 24] - arch: [x86, x64] + arch: [x86, x64, arm64] exclude: - node: 24 arch: x86 @@ -141,16 +141,27 @@ jobs: - uses: actions/checkout@v4 - name: Use Node.js + if: matrix.arch == 'x86' uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} check-latest: true - architecture: ${{ matrix.arch }} + architecture: x86 + + - name: Use Node.js + uses: actions/setup-node@v4 + if: matrix.arch != 'x86' + with: + node-version: ${{ matrix.node }} + check-latest: true - name: Install + env: + npm_config_arch: ${{ matrix.arch == 'x86' && 'ia32' || matrix.arch }} run: npm install - name: Test + if: matrix.arch != 'arm64' env: GIT_SSH: ${{ github.workspace }}\vendor\plink.exe run: | @@ -170,7 +181,7 @@ jobs: - name: Deploy (Package) if: startsWith(github.ref, 'refs/tags/v') - run: node-pre-gyp package + run: node-pre-gyp package --target_arch=${{ matrix.arch }} - name: Deploy (Publish) if: startsWith(github.ref, 'refs/tags/v') @@ -178,4 +189,4 @@ jobs: node_pre_gyp_bucket: ${{ secrets.node_pre_gyp_bucket }} AWS_ACCESS_KEY_ID: ${{ secrets.node_pre_gyp_accessKeyId }} AWS_SECRET_ACCESS_KEY: ${{ secrets.node_pre_gyp_secretAccessKey }} - run: node-pre-gyp publish + run: node-pre-gyp publish --target_arch=${{ matrix.arch }} From 03b3c8844c3092cad9a7c79ddb1038bb2c3fedba Mon Sep 17 00:00:00 2001 From: John Alden Date: Fri, 14 Nov 2025 18:42:03 -0700 Subject: [PATCH 21/21] bump to v0.28.0-alpha.35 --- CHANGELOG.md | 16 ++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12d3a9dce..57d0616de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Change Log +## v0.28.0-alpha.35 [(2025-06-03)](https://github.com/nodegit/nodegit/releases/tag/v0.28.0-alpha.35) + +[Full Changelog](https://github.com/nodegit/nodegit/compare/v0.28.0-alpha.34...v0.28.0-alpha.35) + +#### Summary of Changes + - Bump libgit2 to 1.9.1 + - Bump OpenSSL to 3.0 + - Move OpenSSL Packaging to Github Actions + - Add arm64 build Support + +#### Merged PRs into NodeGit +- [Bump libgit2 to 1.9.1](https://github.com/nodegit/nodegit/pull/2025) +- [Bump OpenSSL to 3.0, Move OpenSSL package generation to Github Actions](https://github.com/nodegit/nodegit/pull/2026) +- [fix: correct macos arch labels](github.com/nodegit/nodegit/pull/2027) +- [Add Ability to compile for arm64](https://github.com/nodegit/nodegit/pull/2028) + ## v0.28.0-alpha.34 [(2025-06-03)](https://github.com/nodegit/nodegit/releases/tag/v0.28.0-alpha.34) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.28.0-alpha.33...v0.28.0-alpha.34) diff --git a/package-lock.json b/package-lock.json index 25edeaf61..64454026d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nodegit", - "version": "0.28.0-alpha.34", + "version": "0.28.0-alpha.35", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nodegit", - "version": "0.28.0-alpha.34", + "version": "0.28.0-alpha.35", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index fe1273285..ca97223da 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nodegit", "description": "Node.js libgit2 asynchronous native bindings", - "version": "0.28.0-alpha.34", + "version": "0.28.0-alpha.35", "homepage": "http://nodegit.org", "keywords": [ "libgit2",