node-gyp-build-v2 4.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,5 @@
1
+ if (typeof process.addon === 'function') { // if the platform supports native resolving prefer that
2
+ module.exports = process.addon.bind(process)
3
+ } else { // else use the runtime version here
4
+ module.exports = require('./node-gyp-build.js')
5
+ }
@@ -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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+
3
+ /*
4
+ I am only useful as an install script to make node-gyp not compile for purely optional native deps
5
+ */
6
+
7
+ process.exit(0)
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
+ }