Socket
Socket
Sign inDemoInstall

node-gyp

Package Overview
Dependencies
Maintainers
4
Versions
145
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-gyp - npm Package Compare versions

Comparing version 7.1.2 to 8.0.0

42

gyp/CHANGELOG.md
# Changelog
### [0.8.1](https://www.github.com/nodejs/gyp-next/compare/v0.8.0...v0.8.1) (2021-02-18)
### Bug Fixes
* update shebang lines from python to python3 ([#94](https://www.github.com/nodejs/gyp-next/issues/94)) ([a1b0d41](https://www.github.com/nodejs/gyp-next/commit/a1b0d4171a8049a4ab7a614202063dec332f2df4))
## [0.8.0](https://www.github.com/nodejs/gyp-next/compare/v0.7.0...v0.8.0) (2021-01-15)
### ⚠ BREAKING CHANGES
* remove support for Python 2
### Bug Fixes
* revert posix build job ([#86](https://www.github.com/nodejs/gyp-next/issues/86)) ([39dc34f](https://www.github.com/nodejs/gyp-next/commit/39dc34f0799c074624005fb9bbccf6e028607f9d))
### gyp
* Remove support for Python 2 ([#88](https://www.github.com/nodejs/gyp-next/issues/88)) ([22e4654](https://www.github.com/nodejs/gyp-next/commit/22e465426fd892403c95534229af819a99c3f8dc))
## [0.7.0](https://www.github.com/nodejs/gyp-next/compare/v0.6.2...v0.7.0) (2020-12-17)
### ⚠ BREAKING CHANGES
* **msvs:** On Windows, arguments passed to the "action" commands are no longer transformed to replace slashes with backslashes.
### Features
* **xcode:** --cross-compiling overrides arch-specific settings ([973bae0](https://www.github.com/nodejs/gyp-next/commit/973bae0b7b08be7b680ecae9565fbd04b3e0787d))
### Bug Fixes
* **msvs:** do not fix paths in action command arguments ([fc22f83](https://www.github.com/nodejs/gyp-next/commit/fc22f8335e2016da4aae4f4233074bd651d2faea))
* cmake on python 3 ([fd61f5f](https://www.github.com/nodejs/gyp-next/commit/fd61f5faa5275ec8fc98e3c7868c0dd46f109540))
* ValueError: invalid mode: 'rU' while trying to load binding.gyp ([d0504e6](https://www.github.com/nodejs/gyp-next/commit/d0504e6700ce48f44957a4d5891b142a60be946f))
* xcode cmake parsing ([eefe8d1](https://www.github.com/nodejs/gyp-next/commit/eefe8d10e99863bc4ac7e2ed32facd608d400d4b))
### [0.6.2](https://www.github.com/nodejs/gyp-next/compare/v0.6.1...v0.6.2) (2020-10-16)

@@ -4,0 +46,0 @@

2

lib/configure.js

@@ -99,3 +99,3 @@ 'use strict'

var config = process.config || {}
var config = Object.assign({}, process.config)
var defaults = config.target_defaults

@@ -102,0 +102,0 @@ var variables = config.variables

'use strict'
const path = require('path')
const log = require('npmlog')

@@ -11,2 +10,19 @@ const semver = require('semver')

const systemDrive = process.env.SystemDrive || 'C:'
const username = process.env.USERNAME || process.env.USER || require('os').userInfo().username
const localAppData = process.env.LOCALAPPDATA || `${systemDrive}\\${username}\\AppData\\Local`
const programFiles = process.env.ProgramW6432 || process.env.ProgramFiles || `${systemDrive}\\Program Files`
const programFilesX86 = process.env['ProgramFiles(x86)'] || `${programFiles} (x86)`
const winDefaultLocationsArray = []
for (const majorMinor of ['39', '38', '37', '36']) {
winDefaultLocationsArray.push(
`${localAppData}\\Programs\\Python\\Python${majorMinor}\\python.exe`,
`${programFiles}\\Python${majorMinor}\\python.exe`,
`${localAppData}\\Programs\\Python\\Python${majorMinor}-32\\python.exe`,
`${programFiles}\\Python${majorMinor}-32\\python.exe`,
`${programFilesX86}\\Python${majorMinor}-32\\python.exe`
)
}
function PythonFinder (configPython, callback) {

@@ -22,3 +38,3 @@ this.callback = callback

argsVersion: ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'],
semverRange: '2.7.x || >=3.5.0',
semverRange: '>=3.6.0',

@@ -30,6 +46,3 @@ // These can be overridden for testing:

pyLauncher: 'py.exe',
winDefaultLocations: [
path.join(process.env.SystemDrive || 'C:', 'Python37', 'python.exe'),
path.join(process.env.SystemDrive || 'C:', 'Python27', 'python.exe')
],
winDefaultLocations: winDefaultLocationsArray,

@@ -102,7 +115,2 @@ // Logs a message at verbose level, but also saves it to be displayed later

arg: 'python'
},
{
before: () => { this.addLog('checking if "python2" can be used') },
check: this.checkCommand,
arg: 'python2'
}

@@ -126,3 +134,3 @@ ]

this.addLog(
'checking if the py launcher can be used to find Python')
'checking if the py launcher can be used to find Python 3')
},

@@ -196,6 +204,11 @@ check: this.checkPyLauncher

// being in the $PATH.
// Because the Python launcher supports Python 2 and Python 3, we should
// explicitly request a Python 3 version. This is done by supplying "-3" as
// the first command line argument. Since "py.exe -3" would be an invalid
// executable for "execFile", we have to use the launcher to figure out
// where the actual "python.exe" executable is located.
checkPyLauncher: function checkPyLauncher (errorCallback) {
this.log.verbose(
`- executing "${this.pyLauncher}" to get Python executable path`)
this.run(this.pyLauncher, this.argsExecutable, false,
`- executing "${this.pyLauncher}" to get Python 3 executable path`)
this.run(this.pyLauncher, ['-3', ...this.argsExecutable], false,
function (err, execPath) {

@@ -202,0 +215,0 @@ // Possible outcomes: same as checkCommand

@@ -7,29 +7,18 @@ 'use strict'

const path = require('path')
const util = require('util')
const stream = require('stream')
const crypto = require('crypto')
const log = require('npmlog')
const semver = require('semver')
const request = require('request')
const fetch = require('make-fetch-happen')
const processRelease = require('./process-release')
const win = process.platform === 'win32'
const getProxyFromURI = require('./proxy')
const streamPipeline = util.promisify(stream.pipeline)
function install (fs, gyp, argv, callback) {
var release = processRelease(argv, gyp, process.version, process.release)
/**
* @param {typeof import('graceful-fs')} fs
*/
// ensure no double-callbacks happen
function cb (err) {
if (cb.done) {
return
}
cb.done = true
if (err) {
log.warn('install', 'got an error, rolling back install')
// roll-back the install if anything went wrong
gyp.commands.remove([release.versionDir], function () {
callback(err)
})
} else {
callback(null, release.version)
}
}
async function install (fs, gyp, argv) {
const release = processRelease(argv, gyp, process.version, process.release)

@@ -41,7 +30,7 @@ // Determine which node dev files version we are installing

// could not parse the version string with semver
return callback(new Error('Invalid version number: ' + release.version))
throw new Error('Invalid version number: ' + release.version)
}
if (semver.lt(release.version, '0.8.0')) {
return callback(new Error('Minimum target version is `0.8.0` or greater. Got: ' + release.version))
throw new Error('Minimum target version is `0.8.0` or greater. Got: ' + release.version)
}

@@ -52,8 +41,6 @@

log.verbose('detected "pre" node version', release.version)
if (gyp.opts.nodedir) {
log.verbose('--nodedir flag was passed; skipping install', gyp.opts.nodedir)
callback()
} else {
callback(new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead'))
if (!gyp.opts.nodedir) {
throw new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead')
}
log.verbose('--nodedir flag was passed; skipping install', gyp.opts.nodedir)
return

@@ -66,3 +53,3 @@ }

// the directory where the dev files will be installed
var devDir = path.resolve(gyp.devDir, release.versionDir)
const devDir = path.resolve(gyp.devDir, release.versionDir)

@@ -73,58 +60,53 @@ // If '--ensure' was passed, then don't *always* install the version;

log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed')
fs.stat(devDir, function (err) {
if (err) {
if (err.code === 'ENOENT') {
log.verbose('install', 'version not already installed, continuing with install', release.version)
go()
} else if (err.code === 'EACCES') {
eaccesFallback(err)
} else {
cb(err)
try {
await fs.promises.stat(devDir)
} catch (err) {
if (err.code === 'ENOENT') {
log.verbose('install', 'version not already installed, continuing with install', release.version)
try {
return await go()
} catch (err) {
return rollback(err)
}
return
} else if (err.code === 'EACCES') {
return eaccesFallback(err)
}
log.verbose('install', 'version is already installed, need to check "installVersion"')
var installVersionFile = path.resolve(devDir, 'installVersion')
fs.readFile(installVersionFile, 'ascii', function (err, ver) {
if (err && err.code !== 'ENOENT') {
return cb(err)
}
var installVersion = parseInt(ver, 10) || 0
log.verbose('got "installVersion"', installVersion)
log.verbose('needs "installVersion"', gyp.package.installVersion)
if (installVersion < gyp.package.installVersion) {
log.verbose('install', 'version is no good; reinstalling')
go()
} else {
log.verbose('install', 'version is good')
cb()
}
})
})
throw err
}
log.verbose('install', 'version is already installed, need to check "installVersion"')
const installVersionFile = path.resolve(devDir, 'installVersion')
let installVersion = 0
try {
const ver = await fs.promises.readFile(installVersionFile, 'ascii')
installVersion = parseInt(ver, 10) || 0
} catch (err) {
if (err.code !== 'ENOENT') {
throw err
}
}
log.verbose('got "installVersion"', installVersion)
log.verbose('needs "installVersion"', gyp.package.installVersion)
if (installVersion < gyp.package.installVersion) {
log.verbose('install', 'version is no good; reinstalling')
try {
return await go()
} catch (err) {
return rollback(err)
}
}
log.verbose('install', 'version is good')
} else {
go()
try {
return await go()
} catch (err) {
return rollback(err)
}
}
function getContentSha (res, callback) {
var shasum = crypto.createHash('sha256')
res.on('data', function (chunk) {
shasum.update(chunk)
}).on('end', function () {
callback(null, shasum.digest('hex'))
})
}
function go () {
async function go () {
log.verbose('ensuring nodedir is created', devDir)
// first create the dir for the node dev files
fs.mkdir(devDir, { recursive: true }, function (err, created) {
if (err) {
if (err.code === 'EACCES') {
eaccesFallback(err)
} else {
cb(err)
}
return
}
try {
const created = await fs.promises.mkdir(devDir, { recursive: true })

@@ -134,226 +116,160 @@ if (created) {

}
} catch (err) {
if (err.code === 'EACCES') {
return eaccesFallback(err)
}
// now download the node tarball
var tarPath = gyp.opts.tarball
var badDownload = false
var extractCount = 0
var contentShasums = {}
var expectShasums = {}
throw err
}
// checks if a file to be extracted from the tarball is valid.
// only .h header files and the gyp files get extracted
function isValid (path) {
var isValid = valid(path)
if (isValid) {
log.verbose('extracted file from tarball', path)
extractCount++
} else {
// invalid
log.silly('ignoring from tarball', path)
}
return isValid
}
// now download the node tarball
const tarPath = gyp.opts.tarball
let extractCount = 0
const contentShasums = {}
const expectShasums = {}
// download the tarball and extract!
if (tarPath) {
return tar.extract({
file: tarPath,
strip: 1,
filter: isValid,
cwd: devDir
}).then(afterTarball, cb)
// checks if a file to be extracted from the tarball is valid.
// only .h header files and the gyp files get extracted
function isValid (path) {
const isValid = valid(path)
if (isValid) {
log.verbose('extracted file from tarball', path)
extractCount++
} else {
// invalid
log.silly('ignoring from tarball', path)
}
return isValid
}
try {
var req = download(gyp, process.env, release.tarballUrl)
} catch (e) {
return cb(e)
}
// download the tarball and extract!
// something went wrong downloading the tarball?
req.on('error', function (err) {
if (err.code === 'ENOTFOUND') {
return cb(new Error('This is most likely not a problem with node-gyp or the package itself and\n' +
'is related to network connectivity. In most cases you are behind a proxy or have bad \n' +
'network settings.'))
}
badDownload = true
cb(err)
if (tarPath) {
await tar.extract({
file: tarPath,
strip: 1,
filter: isValid,
cwd: devDir
})
} else {
try {
const res = await download(gyp, release.tarballUrl)
req.on('close', function () {
if (extractCount === 0) {
cb(new Error('Connection closed while downloading tarball file'))
if (res.status !== 200) {
throw new Error(`${res.status} response downloading ${release.tarballUrl}`)
}
})
req.on('response', function (res) {
if (res.statusCode !== 200) {
badDownload = true
cb(new Error(res.statusCode + ' response downloading ' + release.tarballUrl))
return
await streamPipeline(
res.body,
// content checksum
new ShaSum((_, checksum) => {
const filename = path.basename(release.tarballUrl).trim()
contentShasums[filename] = checksum
log.verbose('content checksum', filename, checksum)
}),
tar.extract({
strip: 1,
cwd: devDir,
filter: isValid
})
)
} catch (err) {
// something went wrong downloading the tarball?
if (err.code === 'ENOTFOUND') {
throw new Error('This is most likely not a problem with node-gyp or the package itself and\n' +
'is related to network connectivity. In most cases you are behind a proxy or have bad \n' +
'network settings.')
}
// content checksum
getContentSha(res, function (_, checksum) {
var filename = path.basename(release.tarballUrl).trim()
contentShasums[filename] = checksum
log.verbose('content checksum', filename, checksum)
})
throw err
}
}
// start unzipping and untaring
res.pipe(tar.extract({
strip: 1,
cwd: devDir,
filter: isValid
}).on('close', afterTarball).on('error', cb))
})
// invoked after the tarball has finished being extracted
if (extractCount === 0) {
throw new Error('There was a fatal problem while downloading/extracting the tarball')
}
// invoked after the tarball has finished being extracted
function afterTarball () {
if (badDownload) {
return
}
if (extractCount === 0) {
return cb(new Error('There was a fatal problem while downloading/extracting the tarball'))
}
log.verbose('tarball', 'done parsing tarball')
var async = 0
log.verbose('tarball', 'done parsing tarball')
if (win) {
// need to download node.lib
async++
downloadNodeLib(deref)
}
const installVersionPath = path.resolve(devDir, 'installVersion')
await Promise.all([
// need to download node.lib
...(win ? downloadNodeLib() : []),
// write the "installVersion" file
fs.promises.writeFile(installVersionPath, gyp.package.installVersion + '\n'),
// Only download SHASUMS.txt if we downloaded something in need of SHA verification
...(!tarPath || win ? [downloadShasums()] : [])
])
// write the "installVersion" file
async++
var installVersionPath = path.resolve(devDir, 'installVersion')
fs.writeFile(installVersionPath, gyp.package.installVersion + '\n', deref)
log.verbose('download contents checksum', JSON.stringify(contentShasums))
// check content shasums
for (const k in contentShasums) {
log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k])
if (contentShasums[k] !== expectShasums[k]) {
throw new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k])
}
}
// Only download SHASUMS.txt if we downloaded something in need of SHA verification
if (!tarPath || win) {
// download SHASUMS.txt
async++
downloadShasums(deref)
}
async function downloadShasums () {
log.verbose('check download content checksum, need to download `SHASUMS256.txt`...')
log.verbose('checksum url', release.shasumsUrl)
if (async === 0) {
// no async tasks required
cb()
}
const res = await download(gyp, release.shasumsUrl)
function deref (err) {
if (err) {
return cb(err)
}
async--
if (!async) {
log.verbose('download contents checksum', JSON.stringify(contentShasums))
// check content shasums
for (var k in contentShasums) {
log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k])
if (contentShasums[k] !== expectShasums[k]) {
cb(new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k]))
return
}
}
cb()
}
}
if (res.status !== 200) {
throw new Error(`${res.status} status code downloading checksum`)
}
function downloadShasums (done) {
log.verbose('check download content checksum, need to download `SHASUMS256.txt`...')
log.verbose('checksum url', release.shasumsUrl)
try {
var req = download(gyp, process.env, release.shasumsUrl)
} catch (e) {
return cb(e)
for (const line of (await res.text()).trim().split('\n')) {
const items = line.trim().split(/\s+/)
if (items.length !== 2) {
return
}
req.on('error', done)
req.on('response', function (res) {
if (res.statusCode !== 200) {
done(new Error(res.statusCode + ' status code downloading checksum'))
return
}
var chunks = []
res.on('data', function (chunk) {
chunks.push(chunk)
})
res.on('end', function () {
var lines = Buffer.concat(chunks).toString().trim().split('\n')
lines.forEach(function (line) {
var items = line.trim().split(/\s+/)
if (items.length !== 2) {
return
}
// 0035d18e2dcf9aad669b1c7c07319e17abfe3762 ./node-v0.11.4.tar.gz
var name = items[1].replace(/^\.\//, '')
expectShasums[name] = items[0]
})
log.verbose('checksum data', JSON.stringify(expectShasums))
done()
})
})
// 0035d18e2dcf9aad669b1c7c07319e17abfe3762 ./node-v0.11.4.tar.gz
const name = items[1].replace(/^\.\//, '')
expectShasums[name] = items[0]
}
function downloadNodeLib (done) {
log.verbose('on Windows; need to download `' + release.name + '.lib`...')
var archs = ['ia32', 'x64', 'arm64']
var async = archs.length
archs.forEach(function (arch) {
var dir = path.resolve(devDir, arch)
var targetLibPath = path.resolve(dir, release.name + '.lib')
var libUrl = release[arch].libUrl
var libPath = release[arch].libPath
var name = arch + ' ' + release.name + '.lib'
log.verbose(name, 'dir', dir)
log.verbose(name, 'url', libUrl)
log.verbose('checksum data', JSON.stringify(expectShasums))
}
fs.mkdir(dir, { recursive: true }, function (err) {
if (err) {
return done(err)
}
log.verbose('streaming', name, 'to:', targetLibPath)
function downloadNodeLib () {
log.verbose('on Windows; need to download `' + release.name + '.lib`...')
const archs = ['ia32', 'x64', 'arm64']
return archs.map(async (arch) => {
const dir = path.resolve(devDir, arch)
const targetLibPath = path.resolve(dir, release.name + '.lib')
const { libUrl, libPath } = release[arch]
const name = `${arch} ${release.name}.lib`
log.verbose(name, 'dir', dir)
log.verbose(name, 'url', libUrl)
try {
var req = download(gyp, process.env, libUrl, cb)
} catch (e) {
return cb(e)
}
await fs.promises.mkdir(dir, { recursive: true })
log.verbose('streaming', name, 'to:', targetLibPath)
req.on('error', done)
req.on('response', function (res) {
if (res.statusCode === 403 || res.statusCode === 404) {
if (arch === 'arm64') {
// Arm64 is a newer platform on Windows and not all node distributions provide it.
log.verbose(`${name} was not found in ${libUrl}`)
} else {
log.warn(`${name} was not found in ${libUrl}`)
}
return
} else if (res.statusCode !== 200) {
done(new Error(res.statusCode + ' status code downloading ' + name))
return
}
const res = await download(gyp, libUrl)
getContentSha(res, function (_, checksum) {
contentShasums[libPath] = checksum
log.verbose('content checksum', libPath, checksum)
})
if (res.status === 403 || res.status === 404) {
if (arch === 'arm64') {
// Arm64 is a newer platform on Windows and not all node distributions provide it.
log.verbose(`${name} was not found in ${libUrl}`)
} else {
log.warn(`${name} was not found in ${libUrl}`)
}
return
} else if (res.status !== 200) {
throw new Error(`${res.status} status code downloading ${name}`)
}
var ws = fs.createWriteStream(targetLibPath)
ws.on('error', cb)
req.pipe(ws)
})
req.on('end', function () { --async || done() })
})
})
} // downloadNodeLib()
}) // mkdir()
return streamPipeline(
res.body,
new ShaSum((_, checksum) => {
contentShasums[libPath] = checksum
log.verbose('content checksum', libPath, checksum)
}),
fs.createWriteStream(targetLibPath)
)
})
} // downloadNodeLib()
} // go()

@@ -367,6 +283,13 @@

// header files
var extname = path.extname(file)
const extname = path.extname(file)
return extname === '.h' || extname === '.gypi'
}
async function rollback (err) {
log.warn('install', 'got an error, rolling back install')
// roll-back the install if anything went wrong
await util.promisify(gyp.commands.remove)([release.versionDir])
throw err
}
/**

@@ -381,10 +304,10 @@ * The EACCES fallback is a workaround for npm's `sudo` behavior, where

function eaccesFallback (err) {
var noretry = '--node_gyp_internal_noretry'
async function eaccesFallback (err) {
const noretry = '--node_gyp_internal_noretry'
if (argv.indexOf(noretry) !== -1) {
return cb(err)
throw err
}
var tmpdir = os.tmpdir()
const tmpdir = os.tmpdir()
gyp.devDir = path.resolve(tmpdir, '.node-gyp')
var userString = ''
let userString = ''
try {

@@ -400,46 +323,52 @@ // os.userInfo can fail on some systems, it's not critical here

}
gyp.commands.install([noretry].concat(argv), cb)
return util.promisify(gyp.commands.install)([noretry].concat(argv))
}
}
function download (gyp, env, url) {
class ShaSum extends stream.Transform {
constructor (callback) {
super()
this._callback = callback
this._digester = crypto.createHash('sha256')
}
_transform (chunk, _, callback) {
this._digester.update(chunk)
callback(null, chunk)
}
_flush (callback) {
this._callback(null, this._digester.digest('hex'))
callback()
}
}
async function download (gyp, url) {
log.http('GET', url)
var requestOpts = {
uri: url,
const requestOpts = {
headers: {
'User-Agent': 'node-gyp v' + gyp.version + ' (node ' + process.version + ')',
'User-Agent': `node-gyp v${gyp.version} (node ${process.version})`,
Connection: 'keep-alive'
}
},
proxy: gyp.opts.proxy,
noProxy: gyp.opts.noproxy
}
var cafile = gyp.opts.cafile
const cafile = gyp.opts.cafile
if (cafile) {
requestOpts.ca = readCAFile(cafile)
requestOpts.ca = await readCAFile(cafile)
}
// basic support for a proxy server
var proxyUrl = getProxyFromURI(gyp, env, url)
if (proxyUrl) {
if (/^https?:\/\//i.test(proxyUrl)) {
log.verbose('download', 'using proxy url: "%s"', proxyUrl)
requestOpts.proxy = proxyUrl
} else {
log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
}
}
const res = await fetch(url, requestOpts)
log.http(res.status, res.url)
var req = request(requestOpts)
req.on('response', function (res) {
log.http(res.statusCode, url)
})
return req
return res
}
function readCAFile (filename) {
async function readCAFile (filename) {
// The CA file can contain multiple certificates so split on certificate
// boundaries. [\S\s]*? is used to match everything including newlines.
var ca = fs.readFileSync(filename, 'utf8')
var re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g
const ca = await fs.promises.readFile(filename, 'utf8')
const re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g
return ca.match(re)

@@ -449,9 +378,9 @@ }

module.exports = function (gyp, argv, callback) {
return install(fs, gyp, argv, callback)
install(fs, gyp, argv).then(callback.bind(undefined, null), callback)
}
module.exports.test = {
download: download,
install: install,
readCAFile: readCAFile
download,
install,
readCAFile
}
module.exports.usage = 'Install node development files for the specified node version.'

@@ -43,3 +43,3 @@ # Installation notes for macOS Catalina (v10.15)

If test succeeded, _you are done_! You should be ready to install `node-gyp`.
If test succeeded, _you are done_! You should be ready to [install](https://github.com/nodejs/node-gyp#installation) `node-gyp`.

@@ -93,3 +93,3 @@ If test failed, there is a problem with your Xcode Command Line Tools installation. [Continue to Solutions](#Solutions).

2. `sudo rm -rf /Library/Developer/CommandLineTools` # Enter root password.
3. `xcode-select --reset`
3. `sudo xcode-select --reset`
4. `xcode-select --install`

@@ -96,0 +96,0 @@ 5. If the [_acid test_ steps above](#The-acid-test) still does _not_ pass then...

@@ -14,3 +14,3 @@ {

],
"version": "7.1.2",
"version": "8.0.0",
"installVersion": 9,

@@ -28,9 +28,9 @@ "author": "Nathan Rajlich <nathan@tootallnate.net> (http://tootallnate.net)",

"glob": "^7.1.4",
"graceful-fs": "^4.2.3",
"graceful-fs": "^4.2.6",
"make-fetch-happen": "^8.0.14",
"nopt": "^5.0.0",
"npmlog": "^4.1.2",
"request": "^2.88.2",
"rimraf": "^3.0.2",
"semver": "^7.3.2",
"tar": "^6.0.2",
"semver": "^7.3.5",
"tar": "^6.1.0",
"which": "^2.0.2"

@@ -37,0 +37,0 @@ },

# `node-gyp` - Node.js native addon build tool
[![Build Status](https://github.com/nodejs/node-gyp/workflows/Tests/badge.svg?branch=master)](https://github.com/nodejs/node-gyp/actions?query=workflow%3ATests+branch%3Amaster)
![npm](https://img.shields.io/npm/dm/node-gyp)

@@ -26,3 +27,3 @@ `node-gyp` is a cross-platform command-line tool written in Node.js for

``` bash
$ npm install -g node-gyp
npm install -g node-gyp
```

@@ -34,3 +35,3 @@

* Python v2.7, v3.5, v3.6, v3.7, or v3.8
* Python v3.6, v3.7, v3.8, or v3.9
* `make`

@@ -43,3 +44,3 @@ * A proper C/C++ compiler toolchain, like [GCC](https://gcc.gnu.org)

* Python v2.7, v3.5, v3.6, v3.7, or v3.8
* Python v3.6, v3.7, v3.8, or v3.9
* [Xcode](https://developer.apple.com/xcode/download/)

@@ -52,8 +53,2 @@ * You also need to install the `XCode Command Line Tools` by running `xcode-select --install`. Alternatively, if you already have the full Xcode installed, you can find them under the menu `Xcode -> Open Developer Tool -> More Developer Tools...`. This step will install `clang`, `clang++`, and `make`.

#### Option 1
Install all the required tools and configurations using Microsoft's [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) using `npm install --global windows-build-tools` from an elevated PowerShell or CMD.exe (run as Administrator).
#### Option 2
Install tools and configuration manually:

@@ -71,4 +66,4 @@ * Install Visual C++ Build Environment: [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools)

`node-gyp` requires that you have installed a compatible version of Python, one of: v2.7, v3.5, v3.6,
v3.7, or v3.8. If you have multiple Python versions installed, you can identify which Python
`node-gyp` requires that you have installed a compatible version of Python, one of: v3.6, v3.7,
v3.8, or v3.9. If you have multiple Python versions installed, you can identify which Python
version `node-gyp` should use in one of the following ways:

@@ -79,3 +74,3 @@

``` bash
$ node-gyp <command> --python /path/to/executable/python
node-gyp <command> --python /path/to/executable/python
```

@@ -88,3 +83,3 @@

``` bash
$ npm config set python /path/to/executable/python
npm config set python /path/to/executable/python
```

@@ -105,3 +100,3 @@

``` bash
$ cd my_node_addon
cd my_node_addon
```

@@ -113,3 +108,3 @@

``` bash
$ node-gyp configure
node-gyp configure
```

@@ -120,3 +115,3 @@

``` bash
$ node-gyp configure --msvs_version=2015
node-gyp configure --msvs_version=2015
```

@@ -131,3 +126,3 @@

``` bash
$ node-gyp build
node-gyp build
```

@@ -228,3 +223,3 @@

```bash
$ export npm_config_devdir=/tmp/.gyp
export npm_config_devdir=/tmp/.gyp
```

@@ -235,3 +230,3 @@

```console
> set npm_config_devdir=c:\temp\.gyp
set npm_config_devdir=c:\temp\.gyp
```

@@ -246,3 +241,3 @@

```bash
$ npm config set [--global] devdir /tmp/.gyp
npm config set [--global] devdir /tmp/.gyp
```

@@ -249,0 +244,0 @@

'use strict'
const test = require('tap').test
const { test } = require('tap')
const fs = require('fs')
const path = require('path')
const util = require('util')
const http = require('http')

@@ -17,180 +18,131 @@ const https = require('https')

test('download over http', function (t) {
test('download over http', async (t) => {
t.plan(2)
var server = http.createServer(function (req, res) {
t.strictEqual(req.headers['user-agent'],
'node-gyp v42 (node ' + process.version + ')')
const server = http.createServer((req, res) => {
t.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
res.end('ok')
server.close()
})
var host = 'localhost'
server.listen(0, host, function () {
var port = this.address().port
var gyp = {
opts: {},
version: '42'
}
var url = 'http://' + host + ':' + port
var req = install.test.download(gyp, {}, url)
req.on('response', function (res) {
var body = ''
res.setEncoding('utf8')
res.on('data', function (data) {
body += data
})
res.on('end', function () {
t.strictEqual(body, 'ok')
})
})
})
t.tearDown(() => new Promise((resolve) => server.close(resolve)))
const host = 'localhost'
await new Promise((resolve) => server.listen(0, host, resolve))
const { port } = server.address()
const gyp = {
opts: {},
version: '42'
}
const url = `http://${host}:${port}`
const res = await install.test.download(gyp, url)
t.strictEqual(await res.text(), 'ok')
})
test('download over https with custom ca', function (t) {
test('download over https with custom ca', async (t) => {
t.plan(3)
var cert = fs.readFileSync(path.join(__dirname, 'fixtures/server.crt'), 'utf8')
var key = fs.readFileSync(path.join(__dirname, 'fixtures/server.key'), 'utf8')
const cafile = path.join(__dirname, '/fixtures/ca.crt')
const [cert, key, ca] = await Promise.all([
fs.promises.readFile(path.join(__dirname, 'fixtures/server.crt'), 'utf8'),
fs.promises.readFile(path.join(__dirname, 'fixtures/server.key'), 'utf8'),
install.test.readCAFile(cafile)
])
var cafile = path.join(__dirname, '/fixtures/ca.crt')
var ca = install.test.readCAFile(cafile)
t.strictEqual(ca.length, 1)
var options = { ca: ca, cert: cert, key: key }
var server = https.createServer(options, function (req, res) {
t.strictEqual(req.headers['user-agent'],
'node-gyp v42 (node ' + process.version + ')')
const options = { ca: ca, cert: cert, key: key }
const server = https.createServer(options, (req, res) => {
t.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
res.end('ok')
server.close()
})
server.on('clientError', function (err) {
throw err
})
t.tearDown(() => new Promise((resolve) => server.close(resolve)))
var host = 'localhost'
server.listen(8000, host, function () {
var port = this.address().port
var gyp = {
opts: { cafile: cafile },
version: '42'
}
var url = 'https://' + host + ':' + port
var req = install.test.download(gyp, {}, url)
req.on('response', function (res) {
var body = ''
res.setEncoding('utf8')
res.on('data', function (data) {
body += data
})
res.on('end', function () {
t.strictEqual(body, 'ok')
})
})
})
server.on('clientError', (err) => { throw err })
const host = 'localhost'
await new Promise((resolve) => server.listen(0, host, resolve))
const { port } = server.address()
const gyp = {
opts: { cafile },
version: '42'
}
const url = `https://${host}:${port}`
const res = await install.test.download(gyp, url)
t.strictEqual(await res.text(), 'ok')
})
test('download over http with proxy', function (t) {
test('download over http with proxy', async (t) => {
t.plan(2)
var server = http.createServer(function (req, res) {
t.strictEqual(req.headers['user-agent'],
'node-gyp v42 (node ' + process.version + ')')
const server = http.createServer((_, res) => {
res.end('ok')
pserver.close(function () {
server.close()
})
})
var pserver = http.createServer(function (req, res) {
t.strictEqual(req.headers['user-agent'],
'node-gyp v42 (node ' + process.version + ')')
const pserver = http.createServer((req, res) => {
t.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
res.end('proxy ok')
server.close(function () {
pserver.close()
})
})
var host = 'localhost'
server.listen(0, host, function () {
var port = this.address().port
pserver.listen(port + 1, host, function () {
var gyp = {
opts: {
proxy: 'http://' + host + ':' + (port + 1)
},
version: '42'
}
var url = 'http://' + host + ':' + port
var req = install.test.download(gyp, {}, url)
req.on('response', function (res) {
var body = ''
res.setEncoding('utf8')
res.on('data', function (data) {
body += data
})
res.on('end', function () {
t.strictEqual(body, 'proxy ok')
})
})
})
})
t.tearDown(() => Promise.all([
new Promise((resolve) => server.close(resolve)),
new Promise((resolve) => pserver.close(resolve))
]))
const host = 'localhost'
await new Promise((resolve) => server.listen(0, host, resolve))
const { port } = server.address()
await new Promise((resolve) => pserver.listen(port + 1, host, resolve))
const gyp = {
opts: {
proxy: `http://${host}:${port + 1}`,
noproxy: 'bad'
},
version: '42'
}
const url = `http://${host}:${port}`
const res = await install.test.download(gyp, url)
t.strictEqual(await res.text(), 'proxy ok')
})
test('download over http with noproxy', function (t) {
test('download over http with noproxy', async (t) => {
t.plan(2)
var server = http.createServer(function (req, res) {
t.strictEqual(req.headers['user-agent'],
'node-gyp v42 (node ' + process.version + ')')
const server = http.createServer((req, res) => {
t.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
res.end('ok')
pserver.close(function () {
server.close()
})
})
var pserver = http.createServer(function (req, res) {
t.strictEqual(req.headers['user-agent'],
'node-gyp v42 (node ' + process.version + ')')
const pserver = http.createServer((_, res) => {
res.end('proxy ok')
server.close(function () {
pserver.close()
})
})
var host = 'localhost'
server.listen(0, host, function () {
var port = this.address().port
pserver.listen(port + 1, host, function () {
var gyp = {
opts: {
proxy: 'http://' + host + ':' + (port + 1),
noproxy: 'localhost'
},
version: '42'
}
var url = 'http://' + host + ':' + port
var req = install.test.download(gyp, {}, url)
req.on('response', function (res) {
var body = ''
res.setEncoding('utf8')
res.on('data', function (data) {
body += data
})
res.on('end', function () {
t.strictEqual(body, 'ok')
})
})
})
})
t.tearDown(() => Promise.all([
new Promise((resolve) => server.close(resolve)),
new Promise((resolve) => pserver.close(resolve))
]))
const host = 'localhost'
await new Promise((resolve) => server.listen(0, host, resolve))
const { port } = server.address()
await new Promise((resolve) => pserver.listen(port + 1, host, resolve))
const gyp = {
opts: {
proxy: `http://${host}:${port + 1}`,
noproxy: host
},
version: '42'
}
const url = `http://${host}:${port}`
const res = await install.test.download(gyp, url)
t.strictEqual(await res.text(), 'ok')
})
test('download with missing cafile', function (t) {
test('download with missing cafile', async (t) => {
t.plan(1)
var gyp = {
const gyp = {
opts: { cafile: 'no.such.file' }
}
try {
install.test.download(gyp, {}, 'http://bad/')
await install.test.download(gyp, {}, 'http://bad/')
} catch (e) {

@@ -201,4 +153,4 @@ t.ok(/no.such.file/.test(e.message))

test('check certificate splitting', function (t) {
var cas = install.test.readCAFile(path.join(__dirname, 'fixtures/ca-bundle.crt'))
test('check certificate splitting', async (t) => {
const cas = await install.test.readCAFile(path.join(__dirname, 'fixtures/ca-bundle.crt'))
t.plan(2)

@@ -211,3 +163,3 @@ t.strictEqual(cas.length, 2)

test('download headers (actual)', function (t) {
test('download headers (actual)', async (t) => {
if (process.env.FAST_TEST ||

@@ -220,53 +172,40 @@ process.release.name !== 'node' ||

t.plan(17)
t.plan(12)
const expectedDir = path.join(devDir, process.version.replace(/^v/, ''))
rimraf(expectedDir, (err) => {
t.ifError(err)
await util.promisify(rimraf)(expectedDir)
const prog = gyp()
prog.parseArgv([])
prog.devDir = devDir
log.level = 'warn'
install(prog, [], (err) => {
t.ifError(err)
const prog = gyp()
prog.parseArgv([])
prog.devDir = devDir
log.level = 'warn'
await util.promisify(install)(prog, [])
fs.readFile(path.join(expectedDir, 'installVersion'), 'utf8', (err, data) => {
t.ifError(err)
t.strictEqual(data, '9\n', 'correct installVersion')
})
const data = await fs.promises.readFile(path.join(expectedDir, 'installVersion'), 'utf8')
t.strictEqual(data, '9\n', 'correct installVersion')
fs.readdir(path.join(expectedDir, 'include/node'), (err, list) => {
t.ifError(err)
const list = await fs.promises.readdir(path.join(expectedDir, 'include/node'))
t.ok(list.includes('common.gypi'))
t.ok(list.includes('config.gypi'))
t.ok(list.includes('node.h'))
t.ok(list.includes('node_version.h'))
t.ok(list.includes('openssl'))
t.ok(list.includes('uv'))
t.ok(list.includes('uv.h'))
t.ok(list.includes('v8-platform.h'))
t.ok(list.includes('v8.h'))
t.ok(list.includes('zlib.h'))
t.ok(list.includes('common.gypi'))
t.ok(list.includes('config.gypi'))
t.ok(list.includes('node.h'))
t.ok(list.includes('node_version.h'))
t.ok(list.includes('openssl'))
t.ok(list.includes('uv'))
t.ok(list.includes('uv.h'))
t.ok(list.includes('v8-platform.h'))
t.ok(list.includes('v8.h'))
t.ok(list.includes('zlib.h'))
})
const lines = (await fs.promises.readFile(path.join(expectedDir, 'include/node/node_version.h'), 'utf8')).split('\n')
fs.readFile(path.join(expectedDir, 'include/node/node_version.h'), 'utf8', (err, contents) => {
t.ifError(err)
// extract the 3 version parts from the defines to build a valid version string and
// and check them against our current env version
const version = ['major', 'minor', 'patch'].reduce((version, type) => {
const re = new RegExp(`^#define\\sNODE_${type.toUpperCase()}_VERSION`)
const line = lines.find((l) => re.test(l))
const i = line ? parseInt(line.replace(/^[^0-9]+([0-9]+).*$/, '$1'), 10) : 'ERROR'
return `${version}${type !== 'major' ? '.' : 'v'}${i}`
}, '')
const lines = contents.split('\n')
// extract the 3 version parts from the defines to build a valid version string and
// and check them against our current env version
const version = ['major', 'minor', 'patch'].reduce((version, type) => {
const re = new RegExp(`^#define\\sNODE_${type.toUpperCase()}_VERSION`)
const line = lines.find((l) => re.test(l))
const i = line ? parseInt(line.replace(/^[^0-9]+([0-9]+).*$/, '$1'), 10) : 'ERROR'
return `${version}${type !== 'major' ? '.' : 'v'}${i}`
}, '')
t.strictEqual(version, process.version)
})
})
})
t.strictEqual(version, process.version)
})

@@ -19,9 +19,4 @@ 'use strict'

t.strictEqual(err, null)
if (/Python 2/.test(stderr)) {
t.strictEqual(stdout, '')
t.ok(/Python 2/.test(stderr))
} else {
t.ok(/Python 3/.test(stdout))
t.strictEqual(stderr, '')
}
t.ok(/Python 3/.test(stdout))
t.strictEqual(stderr, '')
})

@@ -70,3 +65,3 @@ proc.stdout.setEncoding('utf-8')

t.ok(/sys\.version_info/.test(args[1]))
cb(null, '2.7.15')
cb(null, '3.9.1')
}

@@ -151,3 +146,3 @@ t.strictEqual(program,

test('find python - no python, use python launcher', function (t) {
t.plan(3)
t.plan(4)

@@ -159,2 +154,3 @@ var f = new TestPythonFinder(null, done)

if (program === 'py.exe') {
t.notEqual(args.indexOf('-3'), -1)
t.notEqual(args.indexOf('-c'), -1)

@@ -169,3 +165,3 @@ return cb(null, 'Z:\\snake.exe')

if (program === 'Z:\\snake.exe') {
cb(null, '2.7.14')
cb(null, '3.9.0')
} else {

@@ -189,5 +185,5 @@ t.fail()

var re = /C:[\\/]Python37[\\/]python[.]exe/
var f = new TestPythonFinder(null, done)
f.win = true
const expectedProgram = f.winDefaultLocations[0]

@@ -200,3 +196,3 @@ f.execFile = function (program, args, opts, cb) {

cb(new Error('not found'))
} else if (re.test(program) &&
} else if (program === expectedProgram &&
/sys\.version_info/.test(args[args.length - 1])) {

@@ -212,3 +208,3 @@ cb(null, '3.7.3')

t.strictEqual(err, null)
t.ok(re.test(python))
t.ok(python === expectedProgram)
}

@@ -215,0 +211,0 @@ })

'use strict'
const test = require('tap').test
const install = require('../lib/install').test.install
const { test } = require('tap')
const { test: { install } } = require('../lib/install')
const log = require('npmlog')
require('npmlog').level = 'error' // we expect a warning
log.level = 'error' // we expect a warning
test('EACCES retry once', function (t) {
test('EACCES retry once', async (t) => {
t.plan(3)
var fs = {}
fs.stat = function (path, cb) {
var err = new Error()
err.code = 'EACCES'
cb(err)
t.ok(true)
const fs = {
promises: {
stat (_) {
const err = new Error()
err.code = 'EACCES'
t.ok(true)
throw err
}
}
}
var gyp = {}
gyp.devDir = __dirname
gyp.opts = {}
gyp.opts.ensure = true
gyp.commands = {}
gyp.commands.install = function (argv, cb) {
install(fs, gyp, argv, cb)
const Gyp = {
devDir: __dirname,
opts: {
ensure: true
},
commands: {
install (argv, cb) {
install(fs, Gyp, argv).then(cb, cb)
},
remove (_, cb) {
cb()
}
}
}
gyp.commands.remove = function (argv, cb) {
cb()
}
gyp.commands.install([], function (err) {
try {
await install(fs, Gyp, [])
} catch (err) {
t.ok(true)
if (/"pre" versions of node cannot be installed/.test(err.message)) {
t.ok(true)
t.ok(true)
}
})
}
})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc