'use strict'; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function (t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : ( new P(function (resolve) { resolve(value); }) ); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator['throw'](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [], }, f, y, t, g; return ( (g = { next: verb(0), throw: verb(1), return: verb(2) }), typeof Symbol === 'function' && (g[Symbol.iterator] = function () { return this; }), g ); function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError('Generator is already executing.'); while (_) try { if ( ((f = 1), y && (t = op[0] & 2 ? y['return'] : op[0] ? y['throw'] || ((t = y['return']) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) ) return t; if (((y = 0), t)) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if ( !((t = _.trys), (t = t.length > 0 && t[t.length - 1])) && (op[0] === 6 || op[0] === 2) ) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, '__esModule', { value: true }); var zlib_1 = require('zlib'); var crypto_1 = __importDefault(require('crypto')); var fs_extra_1 = __importDefault(require('fs-extra')); var os_1 = __importDefault(require('os')); var path_1 = __importDefault(require('path')); var stream_1 = require('stream'); var util_1 = require('util'); var tar_fs_1 = __importDefault(require('tar-fs')); var places_1 = require('./places'); var utils_1 = require('./utils'); var system_1 = require('./system'); var log_1 = require('./log'); var patches_json_1 = __importDefault(require('../patches/patches.json')); var buildPath = path_1.default.resolve( process.env.PKG_BUILD_PATH || path_1.default.join( os_1.default.tmpdir(), 'pkg.' + crypto_1.default.randomBytes(12).toString('hex') ) ); var nodePath = path_1.default.join(buildPath, 'node'); var patchesPath = path_1.default.resolve(__dirname, '../patches'); var nodeRepo = 'https://nodejs.org/dist'; var nodeArchivePath = path_1.default.join(places_1.cachePath, 'node'); function getMajor(nodeVersion) { var _a = nodeVersion.match(/^v?(\d+)/) || ['', 0], version = _a[1]; return Number(version) | 0; } function getConfigureArgs(major, targetPlatform) { var args = []; // first of all v8_inspector introduces the use // of `prime_rehash_policy` symbol that requires // GLIBCXX_3.4.18 on some systems // also we don't support any kind of debugging // against packaged apps, hence v8_inspector is useless args.push('--without-inspector'); if (system_1.hostPlatform === 'alpine') { // Statically Link against libgcc and libstdc++ libraries. See vercel/pkg#555. // libgcc and libstdc++ grant GCC Runtime Library Exception of GPL args.push('--partly-static'); } if (targetPlatform === 'linuxstatic') { args.push('--fully-static'); } // Link Time Optimization if (major >= 12) { if (system_1.hostPlatform !== 'win') { args.push('--enable-lto'); } } // production binaries do NOT take NODE_OPTIONS from end-users args.push('--without-node-options'); // DTrace args.push('--without-dtrace'); // bundled npm package manager args.push('--without-npm'); // Small ICU args.push('--with-intl=small-icu'); // Workaround for nodejs/node#39313 // All supported macOS versions have zlib as a system library if (targetPlatform === 'macos') { args.push('--shared-zlib'); } return args; } function tarFetch(nodeVersion) { return __awaiter(this, void 0, void 0, function () { var distUrl, tarName, archivePath, hashPath, _a, _b, _c; return __generator(this, function (_d) { switch (_d.label) { case 0: log_1.log.info('Fetching Node.js source archive from nodejs.org...'); distUrl = nodeRepo + '/' + nodeVersion; tarName = 'node-' + nodeVersion + '.tar.gz'; archivePath = path_1.default.join(nodeArchivePath, tarName); hashPath = path_1.default.join( nodeArchivePath, tarName + '.sha256sum' ); if ( fs_extra_1.default.existsSync(hashPath) && fs_extra_1.default.existsSync(archivePath) ) { return [2 /*return*/]; } return [ 4 /*yield*/, fs_extra_1.default.remove(hashPath).catch(function () { return undefined; }), ]; case 1: _d.sent(); return [ 4 /*yield*/, fs_extra_1.default.remove(archivePath).catch(function () { return undefined; }), ]; case 2: _d.sent(); return [ 4 /*yield*/, (0, utils_1.downloadUrl)(distUrl + '/SHASUMS256.txt', hashPath), ]; case 3: _d.sent(); _b = (_a = fs_extra_1.default).writeFile; _c = [hashPath]; return [4 /*yield*/, fs_extra_1.default.readFile(hashPath, 'utf8')]; case 4: return [ 4 /*yield*/, _b.apply( _a, _c.concat([ _d .sent() .split('\n') .filter(function (l) { return l.includes(tarName); })[0], ]) ), ]; case 5: _d.sent(); return [ 4 /*yield*/, (0, utils_1.downloadUrl)(distUrl + '/' + tarName, archivePath), ]; case 6: _d.sent(); return [2 /*return*/]; } }); }); } function tarExtract(nodeVersion) { return __awaiter(this, void 0, void 0, function () { var tarName, expectedHash, actualHash, pipe, source, gunzip, extract; return __generator(this, function (_a) { switch (_a.label) { case 0: log_1.log.info('Extracting Node.js source archive...'); tarName = 'node-' + nodeVersion + '.tar.gz'; return [ 4 /*yield*/, fs_extra_1.default.readFile( path_1.default.join(nodeArchivePath, tarName + '.sha256sum'), 'utf8' ), ]; case 1: expectedHash = _a.sent().split(' ')[0]; return [ 4 /*yield*/, (0, utils_1.hash)(path_1.default.join(nodeArchivePath, tarName)), ]; case 2: actualHash = _a.sent(); if (!(expectedHash !== actualHash)) return [3 /*break*/, 5]; return [ 4 /*yield*/, fs_extra_1.default.remove( path_1.default.join(nodeArchivePath, tarName) ), ]; case 3: _a.sent(); return [ 4 /*yield*/, fs_extra_1.default.remove( path_1.default.join(nodeArchivePath, tarName + '.sha256sum') ), ]; case 4: _a.sent(); throw (0, log_1.wasReported)('Hash mismatch for ' + tarName); case 5: pipe = (0, util_1.promisify)(stream_1.pipeline); source = fs_extra_1.default.createReadStream( path_1.default.join(nodeArchivePath, tarName) ); gunzip = (0, zlib_1.createGunzip)(); extract = tar_fs_1.default.extract(nodePath, { strip: 1, map: function (header) { log_1.log.info(header.name); return header; }, }); return [4 /*yield*/, pipe(source, gunzip, extract)]; case 6: _a.sent(); return [2 /*return*/]; } }); }); } function applyPatches(nodeVersion) { return __awaiter(this, void 0, void 0, function () { var storedPatches, storedPatch, patches, _i, patches_1, patch, patchPath, args; return __generator(this, function (_a) { switch (_a.label) { case 0: log_1.log.info('Applying patches'); storedPatches = patches_json_1.default[nodeVersion]; storedPatch = 'patches' in storedPatches ? storedPatches.patches : storedPatches; patches = 'sameAs' in storedPatch ? patches_json_1.default[storedPatch.sameAs] : storedPatch; (_i = 0), (patches_1 = patches); _a.label = 1; case 1: if (!(_i < patches_1.length)) return [3 /*break*/, 4]; patch = patches_1[_i]; patchPath = path_1.default.join(patchesPath, patch); args = ['-p1', '-i', patchPath]; return [ 4 /*yield*/, (0, utils_1.spawn)('patch', args, { cwd: nodePath, stdio: 'inherit', }), ]; case 2: _a.sent(); _a.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/]; } }); }); } function compileOnWindows(nodeVersion, targetArch, targetPlatform) { return __awaiter(this, void 0, void 0, function () { var args, major, config_flags; return __generator(this, function (_a) { switch (_a.label) { case 0: args = ['/c', 'vcbuild.bat', targetArch]; major = getMajor(nodeVersion); config_flags = getConfigureArgs(major, targetPlatform); // Event Tracing for Windows args.push('noetw'); // Performance counters on Windows if (major <= 10) { args.push('noperfctr'); } // Link Time Code Generation if (major >= 12) { args.push('ltcg'); } // Can't cross compile for arm64 with small-icu if ( system_1.hostArch !== targetArch && !config_flags.includes('--with-intl=full-icu') ) { config_flags.push('--without-intl'); } return [ 4 /*yield*/, (0, utils_1.spawn)('cmd', args, { cwd: nodePath, env: __assign(__assign({}, process.env), { config_flags: config_flags.join(' '), }), stdio: 'inherit', }), ]; case 1: _a.sent(); if (major <= 10) { return [ 2 /*return*/, path_1.default.join(nodePath, 'Release/node.exe'), ]; } return [ 2 /*return*/, path_1.default.join(nodePath, 'out/Release/node.exe'), ]; } }); }); } var _a = process.env.MAKE_JOB_COUNT, MAKE_JOB_COUNT = _a === void 0 ? os_1.default.cpus().length : _a; function compileOnUnix(nodeVersion, targetArch, targetPlatform) { return __awaiter(this, void 0, void 0, function () { var args, cpu, output; return __generator(this, function (_a) { switch (_a.label) { case 0: args = []; cpu = { x86: 'ia32', x64: 'x64', armv6: 'arm', armv7: 'arm', arm64: 'arm64', ppc64: 'ppc64', s390x: 's390x', }[targetArch]; if (cpu) { args.push('--dest-cpu', cpu); } if (system_1.hostArch !== targetArch) { log_1.log.warn('Cross compiling!'); log_1.log.warn( 'You are responsible for appropriate env like CC, CC_host, etc.' ); args.push('--cross-compiling'); } args.push.apply( args, getConfigureArgs(getMajor(nodeVersion), targetPlatform) ); // TODO same for windows? return [ 4 /*yield*/, (0, utils_1.spawn)( '/bin/sh', __spreadArray(['./configure'], args, true), { cwd: nodePath, stdio: 'inherit', } ), ]; case 1: // TODO same for windows? _a.sent(); return [ 4 /*yield*/, (0, utils_1.spawn)( system_1.hostPlatform === 'freebsd' ? 'gmake' : 'make', ['-j', String(MAKE_JOB_COUNT)], { cwd: nodePath, stdio: 'inherit', } ), ]; case 2: _a.sent(); output = path_1.default.join(nodePath, 'out/Release/node'); return [ 4 /*yield*/, (0, utils_1.spawn)( process.env.STRIP || 'strip', __spreadArray( __spreadArray( [], targetPlatform === 'macos' ? ['-x'] : [], true ), [output], false ), { stdio: 'inherit', } ), ]; case 3: _a.sent(); if (!(targetPlatform === 'macos')) return [3 /*break*/, 5]; // Newer versions of Apple Clang automatically ad-hoc sign the compiled executable. // However, for final executable to be signable, base binary MUST NOT have an existing signature. return [ 4 /*yield*/, (0, utils_1.spawn)('codesign', ['--remove-signature', output], { stdio: 'inherit', }), ]; case 4: // Newer versions of Apple Clang automatically ad-hoc sign the compiled executable. // However, for final executable to be signable, base binary MUST NOT have an existing signature. _a.sent(); _a.label = 5; case 5: return [2 /*return*/, output]; } }); }); } function compile(nodeVersion, targetArch, targetPlatform) { return __awaiter(this, void 0, void 0, function () { var win; return __generator(this, function (_a) { log_1.log.info('Compiling Node.js from sources...'); win = system_1.hostPlatform === 'win'; if (win) { return [ 2 /*return*/, compileOnWindows(nodeVersion, targetArch, targetPlatform), ]; } return [ 2 /*return*/, compileOnUnix(nodeVersion, targetArch, targetPlatform), ]; }); }); } function build(nodeVersion, targetArch, targetPlatform, local) { return __awaiter(this, void 0, void 0, function () { var output, outputHash; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, fs_extra_1.default.remove(buildPath)]; case 1: _a.sent(); return [4 /*yield*/, fs_extra_1.default.mkdirp(nodePath)]; case 2: _a.sent(); return [4 /*yield*/, fs_extra_1.default.mkdirp(nodeArchivePath)]; case 3: _a.sent(); return [4 /*yield*/, tarFetch(nodeVersion)]; case 4: _a.sent(); return [4 /*yield*/, tarExtract(nodeVersion)]; case 5: _a.sent(); return [4 /*yield*/, applyPatches(nodeVersion)]; case 6: _a.sent(); return [ 4 /*yield*/, compile(nodeVersion, targetArch, targetPlatform), ]; case 7: output = _a.sent(); return [4 /*yield*/, (0, utils_1.hash)(output)]; case 8: outputHash = _a.sent(); return [ 4 /*yield*/, fs_extra_1.default.mkdirp(path_1.default.dirname(local)), ]; case 9: _a.sent(); return [4 /*yield*/, fs_extra_1.default.copy(output, local)]; case 10: _a.sent(); return [ 4 /*yield*/, fs_extra_1.default.promises.writeFile( local + '.sha256sum', outputHash + ' ' + path_1.default.basename(local) + '\n' ), ]; case 11: _a.sent(); return [4 /*yield*/, fs_extra_1.default.remove(buildPath)]; case 12: _a.sent(); return [2 /*return*/]; } }); }); } exports.default = build; //# sourceMappingURL=build.js.map