Skip to content

Commit 661f3d9

Browse files
authored
Merge pull request #2028 from zawata/native-arm64-compilation
Add Ability to compile for arm64
2 parents 1a05e79 + abc5a66 commit 661f3d9

File tree

8 files changed

+173
-69
lines changed

8 files changed

+173
-69
lines changed

.github/workflows/build-openssl-packages.yml

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ jobs:
1010
strategy:
1111
matrix:
1212
include:
13+
- os: windows-latest
14+
arch: arm64
1315
- os: windows-latest
1416
arch: x64
15-
# - os: windows-latest
16-
# arch: arm64
1717
- os: macos-15
1818
arch: arm64
1919
- os: macos-15-intel
@@ -29,28 +29,19 @@ jobs:
2929
with:
3030
node-version: 22
3131

32-
- name: Install Toolchain
33-
if: matrix.os == 'windows-latest' && matrix.arch == 'arm64'
34-
uses: msys2/setup-msys2@v2
35-
with:
36-
update: true
37-
install: >
38-
mingw-w64-aarch64-toolchain
39-
mingw-w64-aarch64-cmake
40-
mingw-w64-aarch64-ninja
41-
4232
- name: Install dependencies
4333
run: npm install
4434

4535
- name: Build OpenSSL packages
4636
env:
47-
TARGET_ARCH: ${{ matrix.arch }}
37+
npm_config_arch: ${{ matrix.arch }}
4838
NODEGIT_OPENSSL_BUILD_PACKAGE: 1
4939
OPENSSL_MACOS_DEPLOYMENT_TARGET: "11.0"
5040
run: node utils/acquireOpenSSL.mjs
5141

5242
- name: Push OpenSSL package to S3
5343
env:
44+
npm_config_arch: ${{ matrix.arch }}
5445
node_pre_gyp_bucket: ${{ secrets.node_pre_gyp_bucket }}
5546
AWS_ACCESS_KEY_ID: ${{ secrets.node_pre_gyp_accessKeyId }}
5647
AWS_SECRET_ACCESS_KEY: ${{ secrets.node_pre_gyp_secretAccessKey }}

generate/input/descriptor.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,11 @@
15261526
}
15271527
}
15281528
},
1529+
"email": {
1530+
"cDependencies": [
1531+
"git2/sys/email.h"
1532+
]
1533+
},
15291534
"email_create_options": {
15301535
"hasConstructor": true
15311536
},

generate/input/libgit2-supplement.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,54 @@
294294
"isErrorCode": true
295295
}
296296
},
297+
"git_email_create_from_diff": {
298+
"file": "sys/email.h",
299+
"type": "function",
300+
"isAsync": true,
301+
"group": "email",
302+
"args": [
303+
{
304+
"name": "out",
305+
"type": "git_buf *"
306+
},
307+
{
308+
"name": "diff",
309+
"type": "git_diff *"
310+
},
311+
{
312+
"name": "patch_idx",
313+
"type": "size_t"
314+
},
315+
{
316+
"name": "patch_count",
317+
"type": "size_t"
318+
},
319+
{
320+
"name": "commit_id",
321+
"type": "const git_oid *"
322+
},
323+
{
324+
"name": "summary",
325+
"type": "const char *"
326+
},
327+
{
328+
"name": "body",
329+
"type": "const char *"
330+
},
331+
{
332+
"name": "author",
333+
"type": "const git_signature *"
334+
},
335+
{
336+
"name": "opts",
337+
"type": "git_email_create_options *"
338+
}
339+
],
340+
"return": {
341+
"type": "int",
342+
"isErrorCode": true
343+
}
344+
},
297345
"git_diff_get_perfdata": {
298346
"file": "sys/diff.h",
299347
"args": [
@@ -2619,6 +2667,9 @@
26192667
"blame": [
26202668
"git_blame_file"
26212669
],
2670+
"email": [
2671+
"git_email_create_from_diff"
2672+
],
26222673
"note": [
26232674
"git_note_author",
26242675
"git_note_commit_create",

lifecycleScripts/install.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ var buildFlags = require("../utils/buildFlags");
22
var spawn = require("child_process").spawn;
33
var path = require("path");
44

5+
const nodePreGypModulePath = require.resolve("@mapbox/node-pre-gyp");
6+
57
module.exports = function install() {
68
console.log("[nodegit] Running install script");
79

@@ -30,7 +32,10 @@ module.exports = function install() {
3032

3133
return new Promise(function(resolve, reject) {
3234
const gypPath = path.join(__dirname, "..", "node_modules", "node-gyp", "bin", "node-gyp.js");
33-
var spawnedNodePreGyp = spawn(nodePreGyp, args, {
35+
36+
const nodePreGypPath = path.resolve(path.dirname(nodePreGypModulePath), path.join("..", "bin", nodePreGyp));
37+
console.log("node-pre-gyp path", nodePreGypPath);
38+
var spawnedNodePreGyp = spawn(nodePreGypPath, args, {
3439
env: {
3540
...process.env,
3641
npm_config_node_gyp: gypPath

utils/acquireOpenSSL.mjs

Lines changed: 79 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import crypto from "crypto";
2+
import { spawn } from "child_process";
23
import execPromise from "./execPromise.js";
34
import got from "got";
45
import path from "path";
@@ -19,6 +20,28 @@ const vendorPath = path.resolve(import.meta.dirname, "..", "vendor");
1920
const opensslPatchPath = path.join(vendorPath, "patches", "openssl");
2021
const extractPath = path.join(vendorPath, "openssl");
2122

23+
const exists = (filePath) => fs.stat(filePath).then(() => true).catch(() => false);
24+
25+
const convertArch = (archStr) => {
26+
const convertedArch = {
27+
'ia32': 'x86',
28+
'x86': 'x86',
29+
'x64': 'x64',
30+
'arm64': 'arm64'
31+
}[archStr];
32+
33+
if (!convertedArch) {
34+
throw new Error('unsupported architecture');
35+
}
36+
37+
return convertedArch;
38+
}
39+
40+
const hostArch = convertArch(process.arch);
41+
const targetArch = process.env.npm_config_arch
42+
? convertArch(process.env.npm_config_arch)
43+
: hostArch;
44+
2245
const pathsToIncludeForPackage = [
2346
"include", "lib"
2447
];
@@ -82,8 +105,10 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => {
82105
throw new Error("Expected macOsDeploymentTarget to be specified");
83106
}
84107

108+
const buildConfig = targetArch === "x64" ? "darwin64-x86_64-cc" : "darwin64-arm64-cc";
109+
85110
const configureArgs = [
86-
process.arch === "x64" ? "darwin64-x86_64-cc" : "darwin64-arm64-cc",
111+
buildConfig,
87112
// speed up ecdh on little-endian platforms with 128bit int support
88113
"enable-ec_nistp_64_gcc_128",
89114
// compile static libraries
@@ -107,7 +132,7 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => {
107132

108133
await applyOpenSSLPatches(buildCwd, "darwin");
109134

110-
// only build the libraries, not the tests/fuzzer or apps
135+
// only build the libraries, not the fuzzer or apps
111136
await execPromise("make build_libs", {
112137
cwd: buildCwd
113138
}, { pipeOutput: true });
@@ -123,8 +148,10 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => {
123148
};
124149

125150
const buildLinux = async (buildCwd) => {
151+
const buildConfig = targetArch === "x64" ? "linux-x86_64" : "linux-aarch64";
152+
126153
const configureArgs = [
127-
"linux-x86_64",
154+
buildConfig,
128155
// Electron(at least on centos7) imports the libcups library at runtime, which has a
129156
// dependency on the system libssl/libcrypto which causes symbol conflicts and segfaults.
130157
// To fix this we need to hide all the openssl symbols to prevent them from being overridden
@@ -146,7 +173,7 @@ const buildLinux = async (buildCwd) => {
146173

147174
await applyOpenSSLPatches(buildCwd, "linux");
148175

149-
// only build the libraries, not the tests/fuzzer or apps
176+
// only build the libraries, not the fuzzer or apps
150177
await execPromise("make build_libs", {
151178
cwd: buildCwd
152179
}, { pipeOutput: true });
@@ -162,13 +189,7 @@ const buildLinux = async (buildCwd) => {
162189
}, { pipeOutput: true });
163190
};
164191

165-
const buildWin32 = async (buildCwd, vsBuildArch) => {
166-
if (!vsBuildArch) {
167-
throw new Error("Expected vsBuildArch to be specified");
168-
}
169-
170-
const exists = (filePath) => fs.stat(filePath).then(() => true).catch(() => false);
171-
192+
const buildWin32 = async (buildCwd) => {
172193
let vcvarsallPath = undefined;
173194

174195
if (process.env.npm_config_vcvarsall_path && await exists(process.env.npm_config_vcvarsall_path)) {
@@ -219,29 +240,57 @@ const buildWin32 = async (buildCwd, vsBuildArch) => {
219240
}
220241
}
221242

222-
console.log('using', vcvarsallPath);
223-
224243
let vcTarget;
225-
switch (vsBuildArch) {
226-
case "x64": {
244+
switch (targetArch) {
245+
case "x64":
227246
vcTarget = "VC-WIN64A";
228247
break;
229-
}
230248

231-
case "x86": {
249+
case "x86":
232250
vcTarget = "VC-WIN32";
233251
break;
234-
}
235-
236-
default: {
237-
throw new Error(`Unknown vsBuildArch: ${vsBuildArch}`);
238-
}
252+
253+
case "arm64":
254+
vcTarget = "VC-WIN64-ARM";
255+
break;
239256
}
240257

241-
await execPromise(`"${win32BatPath}" "${vcvarsallPath}" ${vsBuildArch} ${vcTarget}`, {
242-
cwd: buildCwd,
243-
maxBuffer: 10 * 1024 * 1024 // we should really just use spawn
244-
}, { pipeOutput: true });
258+
let vsBuildArch = hostArch === targetArch
259+
? hostArch
260+
: `${hostArch}_${targetArch}`;
261+
262+
console.log("Using vcvarsall.bat at: ", vcvarsallPath);
263+
console.log("Using vsBuildArch: ", vsBuildArch);
264+
console.log("Using vcTarget: ", vcTarget);
265+
266+
await new Promise((resolve, reject) => {
267+
const buildProcess = spawn(`"${win32BatPath}" "${vcvarsallPath}" ${vsBuildArch} ${vcTarget}`, {
268+
cwd: buildCwd,
269+
shell: process.platform === "win32",
270+
env: {
271+
...process.env,
272+
NODEGIT_SKIP_TESTS: targetArch !== hostArch ? "1" : undefined
273+
}
274+
});
275+
276+
buildProcess.stdout.on("data", function(data) {
277+
console.info(data.toString().trim());
278+
});
279+
280+
buildProcess.stderr.on("data", function(data) {
281+
console.error(data.toString().trim());
282+
});
283+
284+
buildProcess.on("close", function(code) {
285+
if (!code) {
286+
resolve();
287+
} else {
288+
reject(code);
289+
}
290+
});
291+
});
292+
293+
245294
};
246295

247296
const removeOpenSSLIfOudated = async (openSSLVersion) => {
@@ -285,8 +334,7 @@ const makeOnStreamDownloadProgress = () => {
285334

286335
const buildOpenSSLIfNecessary = async ({
287336
macOsDeploymentTarget,
288-
openSSLVersion,
289-
vsBuildArch
337+
openSSLVersion
290338
}) => {
291339
if (process.platform !== "darwin" && process.platform !== "win32" && process.platform !== "linux") {
292340
console.log(`Skipping OpenSSL build, not required on ${process.platform}`);
@@ -330,7 +378,7 @@ const buildOpenSSLIfNecessary = async ({
330378
} else if (process.platform === "linux") {
331379
await buildLinux(buildCwd);
332380
} else if (process.platform === "win32") {
333-
await buildWin32(buildCwd, vsBuildArch);
381+
await buildWin32(buildCwd);
334382
} else {
335383
throw new Error(`Unknown platform: ${process.platform}`);
336384
}
@@ -383,14 +431,7 @@ const downloadOpenSSLIfNecessary = async ({
383431
}
384432

385433
export const getOpenSSLPackageName = () => {
386-
let arch = process.arch;
387-
if (process.platform === "win32" && (
388-
process.arch === "ia32" || process.env.NODEGIT_VS_BUILD_ARCH === "x86"
389-
)) {
390-
arch = "x86";
391-
}
392-
393-
return `openssl-${OPENSSL_VERSION}-${process.platform}-${arch}.tar.gz`;
434+
return `openssl-${OPENSSL_VERSION}-${process.platform}-${targetArch}.tar.gz`;
394435
}
395436

396437
export const getOpenSSLPackagePath = () => path.join(import.meta.dirname, getOpenSSLPackageName());
@@ -450,18 +491,9 @@ const acquireOpenSSL = async () => {
450491
}
451492
}
452493

453-
let vsBuildArch;
454-
if (process.platform === "win32") {
455-
vsBuildArch = process.env.NODEGIT_VS_BUILD_ARCH || (process.arch === "x64" ? "x64" : "x86");
456-
if (!["x64", "x86"].includes(vsBuildArch)) {
457-
throw new Error(`Invalid vsBuildArch: ${vsBuildArch}`);
458-
}
459-
}
460-
461494
await buildOpenSSLIfNecessary({
462495
openSSLVersion: OPENSSL_VERSION,
463-
macOsDeploymentTarget,
464-
vsBuildArch
496+
macOsDeploymentTarget
465497
});
466498
if (process.env.NODEGIT_OPENSSL_BUILD_PACKAGE) {
467499
await buildPackage();

utils/build-openssl.bat

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1+
rem Build OpenSSL for Windows
2+
rem %1 - path to vcvarsall.bat
3+
rem %2 - architecture argument for vcvarsall.bat
4+
rem %3 - OpenSSL Configure target
5+
16
@call %1 %2
27

38
perl .\Configure %3 no-shared no-ssl2 no-ssl3 no-comp --prefix="%cd%\.." --openssldir="%cd%\.." || goto :error
49

510
nmake || goto :error
6-
nmake test || goto :error
11+
12+
if "%NODEGIT_SKIP_TESTS%" NEQ "1" (
13+
nmake test || goto :error
14+
)
15+
716
nmake install || goto :error
817

918
goto :EOF

utils/uploadOpenSSL.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ export const uploadOpenSSL = async () => {
1919
const packageName = path.basename(getOpenSSLPackageName());
2020
const packagePath = getOpenSSLPackagePath();
2121
console.log(`Uploading ${packagePath} to s3://${pkgJson.binary.bucket_name}/${packageName}`);
22-
return uploadBinaryToS3(packageName, pkgJson.binary.bucket_name, packagePath);
22+
await uploadBinaryToS3(packageName, pkgJson.binary.bucket_name, packagePath);
23+
const sha256PackageName = `${packageName}.sha256`;
24+
await uploadBinaryToS3(sha256PackageName, pkgJson.binary.bucket_name, `${packagePath}.sha256`);
2325
};
2426

2527
if (process.argv[1] === import.meta.filename) {

0 commit comments

Comments
 (0)