Skip to content

Commit 611afbe

Browse files
committed
src: add support for locally installed headers
Some linux distros allow headers to be installed through tools like rpm. If the runtime sets process.config.variables.use_prefix_to_find_headers, look for matching headers based on the directory set for the prefix in process.config.variables.prefix Signed-off-by: Michael Dawson <[email protected]>
1 parent cff9ac2 commit 611afbe

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

lib/configure.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22

33
const { promises: fs } = require('graceful-fs')
4+
const fsSync = require('graceful-fs')
45
const path = require('path')
56
const log = require('./log')
67
const os = require('os')
@@ -13,6 +14,10 @@ const { findAccessibleSync } = require('./util')
1314
const { findPython } = require('./find-python')
1415
const { findVisualStudio } = win ? require('./find-visualstudio') : {}
1516

17+
const majorRe = /^#define NODE_MAJOR_VERSION (\d+)/m
18+
const minorRe = /^#define NODE_MINOR_VERSION (\d+)/m
19+
const patchRe = /^#define NODE_PATCH_VERSION (\d+)/m
20+
1621
async function configure (gyp, argv) {
1722
const buildDir = path.resolve('build')
1823
const configNames = ['config.gypi', 'common.gypi']
@@ -27,6 +32,28 @@ async function configure (gyp, argv) {
2732
// 'python' should be set by now
2833
process.env.PYTHON = python
2934

35+
const prefix = process.config.variables.node_prefix
36+
if (!gyp.opts.nodedir &&
37+
process.config.variables.use_prefix_to_find_headers) {
38+
// check if the headers can be found using the prefix specified
39+
// at build time. Use them if they match the version expected
40+
let availVersion
41+
try {
42+
const nodeVersionH = fsSync.readFileSync(path.join(prefix,
43+
'include', 'node', 'node_version.h'), { encoding: 'utf8' })
44+
const major = nodeVersionH.match(majorRe)[1]
45+
const minor = nodeVersionH.match(minorRe)[1]
46+
const patch = nodeVersionH.match(patchRe)[1]
47+
availVersion = major + '.' + minor + '.' + patch
48+
} catch {}
49+
if (availVersion === release.version) {
50+
// ok version matches, use the headers
51+
gyp.opts.nodedir = prefix
52+
log.verbose('using local node headers based on prefix',
53+
'setting nodedir to ' + gyp.opts.nodedir)
54+
}
55+
}
56+
3057
if (gyp.opts.nodedir) {
3158
// --nodedir was specified. use that for the dev files
3259
nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir())

test/test-configure-nodedir.js

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
'use strict'
2+
3+
const { describe, it } = require('mocha')
4+
const assert = require('assert')
5+
const path = require('path')
6+
const gyp = require('../lib/node-gyp')
7+
const requireInject = require('require-inject')
8+
const semver = require('semver')
9+
10+
const versionSemver = semver.parse(process.version)
11+
12+
const configure = requireInject('../lib/configure', {
13+
'graceful-fs': {
14+
openSync: () => 0,
15+
closeSync: () => {},
16+
existsSync: () => true,
17+
readFileSync: () => '#define NODE_MAJOR_VERSION ' + versionSemver.major + '\n' +
18+
'#define NODE_MINOR_VERSION ' + versionSemver.minor + '\n' +
19+
'#define NODE_PATCH_VERSION ' + versionSemver.patch + '\n',
20+
promises: {
21+
stat: async () => ({}),
22+
mkdir: async () => {},
23+
writeFile: async () => {}
24+
}
25+
}
26+
})
27+
28+
const configure2 = requireInject('../lib/configure', {
29+
'graceful-fs': {
30+
openSync: () => 0,
31+
closeSync: () => {},
32+
existsSync: () => true,
33+
readFileSync: () => '#define NODE_MAJOR_VERSION 8\n' +
34+
'#define NODE_MINOR_VERSION 0\n' +
35+
'#define NODE_PATCH_VERSION 0\n',
36+
promises: {
37+
stat: async () => ({}),
38+
mkdir: async () => {},
39+
writeFile: async () => {}
40+
}
41+
}
42+
})
43+
44+
const SPAWN_RESULT = cb => ({ on: function () { cb() } })
45+
46+
describe('configure-nodedir', function () {
47+
it('configure nodedir with node-gyp command line', function (done) {
48+
const prog = gyp()
49+
prog.parseArgv(['dummy_prog', 'dummy_script', '--nodedir=/usr'])
50+
51+
prog.spawn = function (program, args) {
52+
for (let i = 0; i < args.length; i++) {
53+
if (path.join(path.sep, 'usr', 'include', 'node',
54+
'common.gypi').localeCompare(args[i]) === 0) {
55+
return SPAWN_RESULT(done)
56+
}
57+
};
58+
assert.fail()
59+
}
60+
configure(prog, [], assert.fail)
61+
})
62+
63+
if (process.config.variables.use_prefix_to_find_headers) {
64+
it('use-prefix-to-find-headers build time option - match', function (done) {
65+
const prog = gyp()
66+
prog.parseArgv(['dummy_prog', 'dummy_script'])
67+
68+
prog.spawn = function (program, args) {
69+
for (let i = 0; i < args.length; i++) {
70+
const nodedir = process.config.variables.node_prefix
71+
if (path.join(path.sep, nodedir, 'include', 'node',
72+
'common.gypi').localeCompare(args[i]) === 0) {
73+
return SPAWN_RESULT(done)
74+
}
75+
};
76+
assert.fail()
77+
}
78+
configure(prog, [], assert.fail)
79+
})
80+
81+
it('use-prefix-to-find-headers build time option - no match', function (done) {
82+
const prog = gyp()
83+
prog.parseArgv(['dummy_prog', 'dummy_script'])
84+
85+
prog.spawn = function (program, args) {
86+
for (let i = 0; i < args.length; i++) {
87+
const nodedir = process.config.variables.node_prefix
88+
if (path.join(path.sep, nodedir, 'include', 'node',
89+
'common.gypi').localeCompare(args[i]) === 0) {
90+
assert.fail()
91+
}
92+
};
93+
return SPAWN_RESULT(done)
94+
}
95+
configure2(prog, [], assert.fail)
96+
})
97+
98+
it('use-prefix-to-find-headers build time option, target specified', function (done) {
99+
const prog = gyp()
100+
prog.parseArgv(['dummy_prog', 'dummy_script', '--target=8.0.0'])
101+
102+
prog.spawn = function (program, args) {
103+
for (let i = 0; i < args.length; i++) {
104+
const nodedir = process.config.variables.node_prefix
105+
if (path.join(path.sep, nodedir, 'include', 'node',
106+
'common.gypi').localeCompare(args[i]) === 0) {
107+
assert.fail()
108+
}
109+
};
110+
return SPAWN_RESULT(done)
111+
}
112+
configure(prog, [], assert.fail)
113+
})
114+
}
115+
})

test/test-configure-python.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const configure = requireInject('../lib/configure', {
1111
'graceful-fs': {
1212
openSync: () => 0,
1313
closeSync: () => {},
14+
existsSync: () => {},
1415
promises: {
1516
stat: async () => ({}),
1617
mkdir: async () => {},

0 commit comments

Comments
 (0)