node-gyp-build-v2 4.6.2
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/bin.js +78 -0
- package/build-test.js +19 -0
- package/index.js +5 -0
- package/node-gyp-build.js +207 -0
- package/optional.js +7 -0
- package/package.json +30 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Mathias Buus
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# node-gyp-build
|
2
|
+
|
3
|
+
> Build tool and bindings loader for [`node-gyp`][node-gyp] that supports prebuilds.
|
4
|
+
|
5
|
+
```
|
6
|
+
npm install node-gyp-build
|
7
|
+
```
|
8
|
+
|
9
|
+
[![Test](https://github.com/prebuild/node-gyp-build/actions/workflows/test.yml/badge.svg)](https://github.com/prebuild/node-gyp-build/actions/workflows/test.yml)
|
10
|
+
|
11
|
+
Use together with [`prebuildify`][prebuildify] to easily support prebuilds for your native modules.
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
> **Note.** Prebuild names have changed in [`prebuildify@3`][prebuildify] and `node-gyp-build@4`. Please see the documentation below.
|
16
|
+
|
17
|
+
`node-gyp-build` works similar to [`node-gyp build`][node-gyp] except that it will check if a build or prebuild is present before rebuilding your project.
|
18
|
+
|
19
|
+
It's main intended use is as an npm install script and bindings loader for native modules that bundle prebuilds using [`prebuildify`][prebuildify].
|
20
|
+
|
21
|
+
First add `node-gyp-build` as an install script to your native project
|
22
|
+
|
23
|
+
``` js
|
24
|
+
{
|
25
|
+
...
|
26
|
+
"scripts": {
|
27
|
+
"install": "node-gyp-build"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
```
|
31
|
+
|
32
|
+
Then in your `index.js`, instead of using the [`bindings`](https://www.npmjs.com/package/bindings) module use `node-gyp-build` to load your binding.
|
33
|
+
|
34
|
+
``` js
|
35
|
+
var binding = require('node-gyp-build')(__dirname)
|
36
|
+
```
|
37
|
+
|
38
|
+
If you do these two things and bundle prebuilds with [`prebuildify`][prebuildify] your native module will work for most platforms
|
39
|
+
without having to compile on install time AND will work in both node and electron without the need to recompile between usage.
|
40
|
+
|
41
|
+
Users can override `node-gyp-build` and force compiling by doing `npm install --build-from-source`.
|
42
|
+
|
43
|
+
Prebuilds will be attempted loaded from `MODULE_PATH/prebuilds/...` and then next `EXEC_PATH/prebuilds/...` (the latter allowing use with `zeit/pkg`)
|
44
|
+
|
45
|
+
## Supported prebuild names
|
46
|
+
|
47
|
+
If so desired you can bundle more specific flavors, for example `musl` builds to support Alpine, or targeting a numbered ARM architecture version.
|
48
|
+
|
49
|
+
These prebuilds can be bundled in addition to generic prebuilds; `node-gyp-build` will try to find the most specific flavor first. Prebuild filenames are composed of _tags_. The runtime tag takes precedence, as does an `abi` tag over `napi`. For more details on tags, please see [`prebuildify`][prebuildify].
|
50
|
+
|
51
|
+
Values for the `libc` and `armv` tags are auto-detected but can be overridden through the `LIBC` and `ARM_VERSION` environment variables, respectively.
|
52
|
+
|
53
|
+
## License
|
54
|
+
|
55
|
+
MIT
|
56
|
+
|
57
|
+
[prebuildify]: https://github.com/prebuild/prebuildify
|
58
|
+
[node-gyp]: https://www.npmjs.com/package/node-gyp
|
package/bin.js
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
var proc = require('child_process')
|
4
|
+
var os = require('os')
|
5
|
+
var path = require('path')
|
6
|
+
|
7
|
+
if (!buildFromSource()) {
|
8
|
+
proc.exec('node-gyp-build-test', function (err, stdout, stderr) {
|
9
|
+
if (err) {
|
10
|
+
if (verbose()) console.error(stderr)
|
11
|
+
preinstall()
|
12
|
+
}
|
13
|
+
})
|
14
|
+
} else {
|
15
|
+
preinstall()
|
16
|
+
}
|
17
|
+
|
18
|
+
function build () {
|
19
|
+
var args = [os.platform() === 'win32' ? 'node-gyp.cmd' : 'node-gyp', 'rebuild']
|
20
|
+
|
21
|
+
try {
|
22
|
+
var pkg = require('node-gyp/package.json')
|
23
|
+
args = [
|
24
|
+
process.execPath,
|
25
|
+
path.join(require.resolve('node-gyp/package.json'), '..', typeof pkg.bin === 'string' ? pkg.bin : pkg.bin['node-gyp']),
|
26
|
+
'rebuild'
|
27
|
+
]
|
28
|
+
} catch (_) {}
|
29
|
+
|
30
|
+
proc.spawn(args[0], args.slice(1), { stdio: 'inherit' }).on('exit', function (code) {
|
31
|
+
if (code || !process.argv[3]) process.exit(code)
|
32
|
+
exec(process.argv[3]).on('exit', function (code) {
|
33
|
+
process.exit(code)
|
34
|
+
})
|
35
|
+
})
|
36
|
+
}
|
37
|
+
|
38
|
+
function preinstall () {
|
39
|
+
if (!process.argv[2]) return build()
|
40
|
+
exec(process.argv[2]).on('exit', function (code) {
|
41
|
+
if (code) process.exit(code)
|
42
|
+
build()
|
43
|
+
})
|
44
|
+
}
|
45
|
+
|
46
|
+
function exec (cmd) {
|
47
|
+
if (process.platform !== 'win32') {
|
48
|
+
var shell = os.platform() === 'android' ? 'sh' : '/bin/sh'
|
49
|
+
return proc.spawn(shell, ['-c', '--', cmd], {
|
50
|
+
stdio: 'inherit'
|
51
|
+
})
|
52
|
+
}
|
53
|
+
|
54
|
+
return proc.spawn(process.env.comspec || 'cmd.exe', ['/s', '/c', '"' + cmd + '"'], {
|
55
|
+
windowsVerbatimArguments: true,
|
56
|
+
stdio: 'inherit'
|
57
|
+
})
|
58
|
+
}
|
59
|
+
|
60
|
+
function buildFromSource () {
|
61
|
+
return hasFlag('--build-from-source') || process.env.npm_config_build_from_source === 'true'
|
62
|
+
}
|
63
|
+
|
64
|
+
function verbose () {
|
65
|
+
return hasFlag('--verbose') || process.env.npm_config_loglevel === 'verbose'
|
66
|
+
}
|
67
|
+
|
68
|
+
// TODO (next major): remove in favor of env.npm_config_* which works since npm
|
69
|
+
// 0.1.8 while npm_config_argv will stop working in npm 7. See npm/rfcs#90
|
70
|
+
function hasFlag (flag) {
|
71
|
+
if (!process.env.npm_config_argv) return false
|
72
|
+
|
73
|
+
try {
|
74
|
+
return JSON.parse(process.env.npm_config_argv).original.indexOf(flag) !== -1
|
75
|
+
} catch (_) {
|
76
|
+
return false
|
77
|
+
}
|
78
|
+
}
|
package/build-test.js
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
process.env.NODE_ENV = 'test'
|
4
|
+
|
5
|
+
var path = require('path')
|
6
|
+
var test = null
|
7
|
+
|
8
|
+
try {
|
9
|
+
var pkg = require(path.join(process.cwd(), 'package.json'))
|
10
|
+
if (pkg.name && process.env[pkg.name.toUpperCase().replace(/-/g, '_')]) {
|
11
|
+
process.exit(0)
|
12
|
+
}
|
13
|
+
test = pkg.prebuild.test
|
14
|
+
} catch (err) {
|
15
|
+
// do nothing
|
16
|
+
}
|
17
|
+
|
18
|
+
if (test) require(path.join(process.cwd(), test))
|
19
|
+
else require('./')()
|
package/index.js
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
var fs = require('fs')
|
2
|
+
var path = require('path')
|
3
|
+
var os = require('os')
|
4
|
+
|
5
|
+
// Workaround to fix webpack's build warnings: 'the request of a dependency is an expression'
|
6
|
+
var runtimeRequire = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require // eslint-disable-line
|
7
|
+
|
8
|
+
var vars = (process.config && process.config.variables) || {}
|
9
|
+
var prebuildsOnly = !!process.env.PREBUILDS_ONLY
|
10
|
+
var abi = process.versions.modules // TODO: support old node where this is undef
|
11
|
+
var runtime = isElectron() ? 'electron' : (isNwjs() ? 'node-webkit' : 'node')
|
12
|
+
|
13
|
+
var arch = process.env.npm_config_arch || os.arch()
|
14
|
+
var platform = process.env.npm_config_platform || os.platform()
|
15
|
+
var libc = process.env.LIBC || (isAlpine(platform) ? 'musl' : 'glibc')
|
16
|
+
var armv = process.env.ARM_VERSION || (arch === 'arm64' ? '8' : vars.arm_version) || ''
|
17
|
+
var uv = (process.versions.uv || '').split('.')[0]
|
18
|
+
|
19
|
+
module.exports = load
|
20
|
+
|
21
|
+
function load (dir) {
|
22
|
+
return runtimeRequire(load.resolve(dir))
|
23
|
+
}
|
24
|
+
|
25
|
+
load.resolve = load.path = function (dir) {
|
26
|
+
dir = path.resolve(dir || '.')
|
27
|
+
|
28
|
+
try {
|
29
|
+
var name = runtimeRequire(path.join(dir, 'package.json')).name.toUpperCase().replace(/-/g, '_')
|
30
|
+
if (process.env[name + '_PREBUILD']) dir = process.env[name + '_PREBUILD']
|
31
|
+
} catch (err) {}
|
32
|
+
|
33
|
+
if (!prebuildsOnly) {
|
34
|
+
var release = getFirst(path.join(dir, 'build/Release'), matchBuild)
|
35
|
+
if (release) return release
|
36
|
+
|
37
|
+
var debug = getFirst(path.join(dir, 'build/Debug'), matchBuild)
|
38
|
+
if (debug) return debug
|
39
|
+
}
|
40
|
+
|
41
|
+
var prebuild = resolve(dir)
|
42
|
+
if (prebuild) return prebuild
|
43
|
+
|
44
|
+
var nearby = resolve(path.dirname(process.execPath))
|
45
|
+
if (nearby) return nearby
|
46
|
+
|
47
|
+
var target = [
|
48
|
+
'platform=' + platform,
|
49
|
+
'arch=' + arch,
|
50
|
+
'runtime=' + runtime,
|
51
|
+
'abi=' + abi,
|
52
|
+
'uv=' + uv,
|
53
|
+
armv ? 'armv=' + armv : '',
|
54
|
+
'libc=' + libc,
|
55
|
+
'node=' + process.versions.node,
|
56
|
+
process.versions.electron ? 'electron=' + process.versions.electron : '',
|
57
|
+
typeof __webpack_require__ === 'function' ? 'webpack=true' : '' // eslint-disable-line
|
58
|
+
].filter(Boolean).join(' ')
|
59
|
+
|
60
|
+
throw new Error('No native build was found for ' + target + '\n loaded from: ' + dir + '\n')
|
61
|
+
|
62
|
+
function resolve (dir) {
|
63
|
+
// Find matching "prebuilds/<platform>-<arch>" directory
|
64
|
+
var tuples = readdirSync(path.join(dir, 'prebuilds')).map(parseTuple)
|
65
|
+
var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0]
|
66
|
+
if (!tuple) return
|
67
|
+
|
68
|
+
// Find most specific flavor first
|
69
|
+
var prebuilds = path.join(dir, 'prebuilds', tuple.name)
|
70
|
+
var parsed = readdirSync(prebuilds).map(parseTags)
|
71
|
+
var candidates = parsed.filter(matchTags(runtime, abi))
|
72
|
+
var winner = candidates.sort(compareTags(runtime))[0]
|
73
|
+
if (winner) return path.join(prebuilds, winner.file)
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
function readdirSync (dir) {
|
78
|
+
try {
|
79
|
+
return fs.readdirSync(dir)
|
80
|
+
} catch (err) {
|
81
|
+
return []
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
function getFirst (dir, filter) {
|
86
|
+
var files = readdirSync(dir).filter(filter)
|
87
|
+
return files[0] && path.join(dir, files[0])
|
88
|
+
}
|
89
|
+
|
90
|
+
function matchBuild (name) {
|
91
|
+
return /\.node$/.test(name)
|
92
|
+
}
|
93
|
+
|
94
|
+
function parseTuple (name) {
|
95
|
+
// Example: darwin-x64+arm64
|
96
|
+
var arr = name.split('-')
|
97
|
+
if (arr.length !== 2) return
|
98
|
+
|
99
|
+
var platform = arr[0]
|
100
|
+
var architectures = arr[1].split('+')
|
101
|
+
|
102
|
+
if (!platform) return
|
103
|
+
if (!architectures.length) return
|
104
|
+
if (!architectures.every(Boolean)) return
|
105
|
+
|
106
|
+
return { name, platform, architectures }
|
107
|
+
}
|
108
|
+
|
109
|
+
function matchTuple (platform, arch) {
|
110
|
+
return function (tuple) {
|
111
|
+
if (tuple == null) return false
|
112
|
+
if (tuple.platform !== platform) return false
|
113
|
+
return tuple.architectures.includes(arch)
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
function compareTuples (a, b) {
|
118
|
+
// Prefer single-arch prebuilds over multi-arch
|
119
|
+
return a.architectures.length - b.architectures.length
|
120
|
+
}
|
121
|
+
|
122
|
+
function parseTags (file) {
|
123
|
+
var arr = file.split('.')
|
124
|
+
var extension = arr.pop()
|
125
|
+
var tags = { file: file, specificity: 0 }
|
126
|
+
|
127
|
+
if (extension !== 'node') return
|
128
|
+
|
129
|
+
for (var i = 0; i < arr.length; i++) {
|
130
|
+
var tag = arr[i]
|
131
|
+
|
132
|
+
if (tag === 'node' || tag === 'electron' || tag === 'node-webkit') {
|
133
|
+
tags.runtime = tag
|
134
|
+
} else if (tag === 'napi') {
|
135
|
+
tags.napi = true
|
136
|
+
} else if (tag.slice(0, 3) === 'abi') {
|
137
|
+
tags.abi = tag.slice(3)
|
138
|
+
} else if (tag.slice(0, 2) === 'uv') {
|
139
|
+
tags.uv = tag.slice(2)
|
140
|
+
} else if (tag.slice(0, 4) === 'armv') {
|
141
|
+
tags.armv = tag.slice(4)
|
142
|
+
} else if (tag === 'glibc' || tag === 'musl') {
|
143
|
+
tags.libc = tag
|
144
|
+
} else {
|
145
|
+
continue
|
146
|
+
}
|
147
|
+
|
148
|
+
tags.specificity++
|
149
|
+
}
|
150
|
+
|
151
|
+
return tags
|
152
|
+
}
|
153
|
+
|
154
|
+
function matchTags (runtime, abi) {
|
155
|
+
return function (tags) {
|
156
|
+
if (tags == null) return false
|
157
|
+
if (tags.runtime !== runtime && !runtimeAgnostic(tags)) return false
|
158
|
+
if (tags.abi !== abi && !tags.napi) return false
|
159
|
+
if (tags.uv && tags.uv !== uv) return false
|
160
|
+
if (tags.armv && tags.armv !== armv) return false
|
161
|
+
if (tags.libc && tags.libc !== libc) return false
|
162
|
+
|
163
|
+
return true
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
function runtimeAgnostic (tags) {
|
168
|
+
return tags.runtime === 'node' && tags.napi
|
169
|
+
}
|
170
|
+
|
171
|
+
function compareTags (runtime) {
|
172
|
+
// Precedence: non-agnostic runtime, abi over napi, then by specificity.
|
173
|
+
return function (a, b) {
|
174
|
+
if (a.runtime !== b.runtime) {
|
175
|
+
return a.runtime === runtime ? -1 : 1
|
176
|
+
} else if (a.abi !== b.abi) {
|
177
|
+
return a.abi ? -1 : 1
|
178
|
+
} else if (a.specificity !== b.specificity) {
|
179
|
+
return a.specificity > b.specificity ? -1 : 1
|
180
|
+
} else {
|
181
|
+
return 0
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
function isNwjs () {
|
187
|
+
return !!(process.versions && process.versions.nw)
|
188
|
+
}
|
189
|
+
|
190
|
+
function isElectron () {
|
191
|
+
if (process.versions && process.versions.electron) return true
|
192
|
+
if (process.env.ELECTRON_RUN_AS_NODE) return true
|
193
|
+
return typeof window !== 'undefined' && window.process && window.process.type === 'renderer'
|
194
|
+
}
|
195
|
+
|
196
|
+
function isAlpine (platform) {
|
197
|
+
return platform === 'linux' && fs.existsSync('/etc/alpine-release')
|
198
|
+
}
|
199
|
+
|
200
|
+
// Exposed for unit tests
|
201
|
+
// TODO: move to lib
|
202
|
+
load.parseTags = parseTags
|
203
|
+
load.matchTags = matchTags
|
204
|
+
load.compareTags = compareTags
|
205
|
+
load.parseTuple = parseTuple
|
206
|
+
load.matchTuple = matchTuple
|
207
|
+
load.compareTuples = compareTuples
|
package/optional.js
ADDED
package/package.json
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
{
|
2
|
+
"name": "node-gyp-build-v2",
|
3
|
+
"version": "4.6.2",
|
4
|
+
"description": "Build tool and bindings loader for node-gyp that supports prebuilds",
|
5
|
+
"main": "index.js",
|
6
|
+
"devDependencies": {
|
7
|
+
"array-shuffle": "^1.0.1",
|
8
|
+
"standard": "^14.0.0",
|
9
|
+
"querystring-chain": "^0.2.6",
|
10
|
+
"tape": "^5.0.0"
|
11
|
+
},
|
12
|
+
"scripts": {
|
13
|
+
"test": "standard && node test"
|
14
|
+
},
|
15
|
+
"bin": {
|
16
|
+
"node-gyp-build": "./bin.js",
|
17
|
+
"node-gyp-build-optional": "./optional.js",
|
18
|
+
"node-gyp-build-test": "./build-test.js"
|
19
|
+
},
|
20
|
+
"repository": {
|
21
|
+
"type": "git",
|
22
|
+
"url": "https://github.com/prebuild/node-gyp-build.git"
|
23
|
+
},
|
24
|
+
"author": "Mathias Buus (@mafintosh)",
|
25
|
+
"license": "MIT",
|
26
|
+
"bugs": {
|
27
|
+
"url": "https://github.com/prebuild/node-gyp-build/issues"
|
28
|
+
},
|
29
|
+
"homepage": "https://github.com/prebuild/node-gyp-build"
|
30
|
+
}
|