Skip to content

Commit efa4f8e

Browse files
authored
Try to use the version from llvm-config on MacOS (#141)
Try to use the version from llvm-config on MacOS
1 parent bfa5ff7 commit efa4f8e

2 files changed

Lines changed: 111 additions & 56 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ build/
77
out/
88
npm-debug.log
99
node_modules/
10+
options.gypi

scripts/configure.js

Lines changed: 110 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,34 @@ console.log('Build dir is: ' + buildDir);
1111

1212
const osName = os.type();
1313

14-
var lldbVersion;
15-
var lldbHeadersBranch;
16-
var lldbIncludeDir;
14+
var lldbVersion; // Similar to what `llvm-config --version` returns
15+
var lldbInstallDir; // Where the lldb installation is, `llvm-config --prefix`
1716

1817
// Need to determine:
1918
// - What level of lldb we are running.
2019
// - If we need the headers. (Linux may have them installed)
2120
var lldbExe = 'lldb';
2221

2322
if (osName === 'Darwin') {
24-
2523
lldbVersion = getDarwinRelease();
2624

2725
if (lldbVersion === undefined) {
2826
console.log('Unable to locate lldb binary. llnode installation failed.');
2927
process.exit(1);
3028
}
3129

32-
lldbHeadersBranch = lldbVersionToBranch(lldbVersion);
33-
lldbIncludeDir = 'lldb-' + lldbVersion;
34-
30+
console.log(`Installing llnode for ${lldbExe}, lldb version ${lldbVersion}`);
31+
const installedDir = getDarwinInstallDir();
32+
if (installedDir === undefined) {
33+
const lldbHeadersBranch = lldbVersionToBranch(lldbVersion);
34+
lldbInstallDir = 'lldb-' + lldbVersion;
35+
cloneHeaders(lldbHeadersBranch, lldbInstallDir, buildDir);
36+
fs.writeFileSync('options.gypi', '{}', 'utf-8');
37+
} else {
38+
lldbInstallDir = installedDir;
39+
setDarwinBuildDir();
40+
}
3541
} else if (osName === 'Linux') {
36-
3742
lldbExe = getLldbExecutable();
3843
lldbVersion = getLinuxVersion(lldbExe);
3944

@@ -42,18 +47,17 @@ if (osName === 'Darwin') {
4247
process.exit(1);
4348
}
4449

45-
// console.log('lldb_version is ' + lldb_version)
46-
const installedHeadersDir = getLinuxHeadersDir(lldbVersion);
47-
// console.log('installed_headers_dir is ' + installed_headers_dir);
48-
if (installedHeadersDir === undefined) {
49-
// Initialising lldb_headers_branch will cause us to clone them.
50-
lldbHeadersBranch = lldbVersionToBranch(lldbVersion);
51-
lldbIncludeDir = 'lldb-' + lldbVersion;
50+
console.log(`Installing llnode for ${lldbExe}, lldb version ${lldbVersion}`);
51+
const installedDir = getLinuxInstallDir(lldbVersion);
52+
if (installedDir === undefined) {
53+
const lldbHeadersBranch = lldbVersionToBranch(lldbVersion);
54+
lldbInstallDir = 'lldb-' + lldbVersion;
55+
cloneHeaders(lldbHeadersBranch, lldbInstallDir, buildDir);
56+
fs.writeFileSync('options.gypi', '{}', 'utf-8');
5257
} else {
53-
lldbIncludeDir = installedHeadersDir;
58+
lldbInstallDir = installedDir;
5459
}
5560
} else if (osName === 'FreeBSD') {
56-
5761
lldbExe = getLldbExecutable();
5862
lldbVersion = getFreeBSDVersion(lldbExe);
5963

@@ -62,43 +66,53 @@ if (osName === 'Darwin') {
6266
process.exit(1);
6367
}
6468

65-
const installedHeadersDir = getFreeBSDHeadersDir(lldbVersion);
66-
if (installedHeadersDir === undefined) {
69+
console.log(`Installing llnode for ${lldbExe}, lldb version ${lldbVersion}`);
70+
const installedDir = getFreeBSDInstallDir(lldbVersion);
71+
if (installedDir === undefined) {
6772
// As this is a BSD we know this system is in an improper state
6873
// So we can exit with an error
6974
console.log('The system isn\'t set up correcly.');
7075
console.log('Try `pkg install llvm39');
7176
console.log('And `ln -s /usr/local/bin/lldb39 /usr/bin/lldb`');
7277
process.exit(1);
7378
} else {
74-
lldbIncludeDir = installedHeadersDir;
79+
lldbInstallDir = installedDir;
7580
}
76-
7781
}
7882

79-
console.log(`Installing llnode for ${lldbExe}, lldb version ${lldbVersion}`);
83+
// This should be equivalent to `llvm-config --includedir`/lldb
84+
function getLldbHeadersPath(lldbInstallDir) {
85+
return path.join(lldbInstallDir, 'include', 'lldb');
86+
}
8087

81-
// Check out source code of the LLDB that is compatible with OS X's default lldb
88+
// Check out source code of the LLDB for headers
8289
// TODO: The llvm project is probably moving to github soon at that point we
8390
// should stop using the mirror.
84-
if (lldbHeadersBranch != undefined) {
85-
console.log('Cloning lldb from ' + lldbHeadersBranch);
86-
child_process.execSync(`rm -rf ${lldbIncludeDir}`);
87-
child_process.execFileSync('git',
88-
['clone', '--depth=1', '-b', lldbHeadersBranch,
89-
'https://github.com/llvm-mirror/lldb.git', lldbIncludeDir],
90-
{cwd: buildDir});
91+
function cloneHeaders(lldbHeadersBranch, lldbInstallDir, buildDir) {
92+
const lldbHeaders = getLldbHeadersPath(lldbInstallDir);
93+
if (!fs.existsSync(lldbInstallDir)) {
94+
console.log(`Cloning lldb from ${lldbHeadersBranch} to ${lldbInstallDir}`);
95+
child_process.execFileSync('git',
96+
['clone', '--depth=1', '-b', lldbHeadersBranch,
97+
'https://github.com/llvm-mirror/lldb.git', lldbInstallDir],
98+
{
99+
cwd: buildDir,
100+
stdio: 'inherit' // show progress
101+
});
102+
} else {
103+
console.log(`Skip cloning lldb headers because ${lldbHeaders} exists`);
104+
}
91105
}
92106

93107
// Link to the headers file so we can run gyp_llnode directly and don't need to
94108
// setup parameters to pass it.
95-
console.log(`Linking lldb to include directory ${lldbIncludeDir}`);
109+
console.log(`Linking lldb to installation directory ${lldbInstallDir}`);
96110
try {
97111
fs.unlinkSync('lldb');
98112
} catch (error) {
99113
// File does not exist, no need to handle.
100114
}
101-
fs.symlinkSync(lldbIncludeDir, 'lldb');
115+
fs.symlinkSync(lldbInstallDir, 'lldb');
102116

103117
// npm explore has a different root folder when using -g
104118
// So we are tacking on the extra the additional subfolders
@@ -107,10 +121,10 @@ if (process.env.npm_config_global) {
107121
gypSubDir = 'npm/node_modules/node-gyp';
108122
}
109123

110-
// npm can be in a different location than the current
111-
// location for global installs so we need find out where the npm is
112-
var npmLocation = child_process.execFileSync('which', ['npm']);
113-
var npmModules = path.join(npmLocation.toString(), '../../lib/node_modules/npm');
124+
// npm can be in a different location than the current
125+
// location for global installs so we need find out where the npm is
126+
var npmLocation = child_process.execFileSync('which', ['npm']);
127+
var npmModules = path.join(npmLocation.toString(), '../../lib/node_modules/npm');
114128

115129
// Initialize GYP
116130
// We can use the node-gyp that comes with npm.
@@ -136,17 +150,30 @@ function lldbVersionToBranch(version) {
136150

137151
// On Mac the lldb version string doesn't match the original lldb versions.
138152
function getDarwinRelease() {
153+
var versionFromConfig;
154+
try {
155+
versionFromConfig = child_process.execFileSync('llvm-config', [
156+
'--version'
157+
]).toString().trim();
158+
} catch (err) {
159+
// No llvm-config, try to get the version from xcodebuild
160+
}
161+
if (versionFromConfig !== undefined) {
162+
return versionFromConfig.split('.').slice(0, 2).join('.');
163+
}
164+
139165
var xcodeStr;
140166
try {
141-
xcodeStr = child_process.execFileSync('xcodebuild', ['-version'])
142-
.toString();
167+
xcodeStr = child_process.execFileSync('xcodebuild', [
168+
'-version'
169+
]).toString();
143170
} catch (err) {
144171
return undefined;
145172
}
146173
var versionStr = '';
147174
var splitStr = xcodeStr.split(os.EOL);
148175
for (var str of splitStr) {
149-
if (str.indexOf('Xcode') != -1) {
176+
if (str.includes('Xcode')) {
150177
versionStr = str.split(' ')[1];
151178
break;
152179
}
@@ -163,6 +190,34 @@ function getDarwinRelease() {
163190
}
164191
}
165192

193+
function setDarwinBuildDir() {
194+
const prefix = child_process.execFileSync('llvm-config', [
195+
'--prefix'
196+
]).toString().trim();
197+
const options = JSON.stringify({
198+
variables: { 'lldb_build_dir%': prefix }
199+
}, null, 2);
200+
fs.writeFileSync('options.gypi', options, 'utf-8');
201+
console.log('Overwriting options.gypi with output from llvm-config:');
202+
console.log(options);
203+
}
204+
205+
function getDarwinInstallDir() {
206+
var installedDir;
207+
try {
208+
installedDir = child_process.execFileSync('llvm-config', [
209+
'--prefix'
210+
]).toString().trim();
211+
} catch (err) {
212+
// Return undefined, we will download the headers.
213+
}
214+
if (installedDir !== undefined &&
215+
fs.existsSync(getLldbHeadersPath(installedDir))) {
216+
return installedDir;
217+
}
218+
return undefined;
219+
}
220+
166221
// Find the 'best' lldb to use. Either:
167222
// - the one specified by the user using npm --lldb_exe=... install llnode
168223
// - the default lldb executable
@@ -171,8 +226,10 @@ function getDarwinRelease() {
171226
function getLldbExecutable() {
172227
var lldbExe = process.env.npm_config_lldb_exe;
173228
if (lldbExe === undefined) {
174-
var lldbExeNames = ['lldb', 'lldb-5.0', 'lldb-4.0',
175-
'lldb-3.9', 'lldb-3.8', 'lldb-3.7', 'lldb-3.6'];
229+
var lldbExeNames = [
230+
'lldb', 'lldb-5.0', 'lldb-4.0',
231+
'lldb-3.9', 'lldb-3.8', 'lldb-3.7', 'lldb-3.6'
232+
];
176233
for (var lldbExeVersion of lldbExeNames) {
177234
try {
178235
lldbExe = child_process.execSync('which ' +
@@ -192,7 +249,6 @@ function getLldbExecutable() {
192249
// There are multiple versions of lldb available for the various linux distos.
193250
// Use the default unless --llnode_exe= has been set on the command line.
194251
function getLinuxVersion(lldbExe) {
195-
196252
var lldbStr;
197253
try {
198254
lldbStr = child_process.execFileSync(lldbExe, ['-v']).toString();
@@ -209,42 +265,42 @@ function getLinuxVersion(lldbExe) {
209265

210266
// Shim this for consistancy in OS naming
211267
function getFreeBSDVersion(lldbExe) {
212-
//Strip the dots for BSD
213-
return getLinuxVersion(lldbExe).replace('.','');
268+
// Strip the dots for BSD
269+
return getLinuxVersion(lldbExe).replace('.', '');
214270
}
215271

216-
function getFreeBSDHeadersDir(version) {
217-
272+
function getFreeBSDInstallDir(version) {
218273
console.log('Checking for headers, version is ' + version);
219274

220275
try {
221-
var includeDir = child_process.execFileSync('llvm-config' + version,
276+
var installDir = child_process.execFileSync('llvm-config' + version,
222277
['--prefix']).toString().trim();
223-
if (fs.existsSync(includeDir + '/include/lldb')) {
224-
return includeDir;
278+
if (fs.existsSync(installDir + '/include/lldb')) {
279+
return installDir;
225280
}
226281
} catch (err) {
227-
console.log(includeDir + '/include/lldb doesn\'nt exist');
282+
console.log(installDir + '/include/lldb doesn\'nt exist');
228283
console.log('Please see README.md');
229284
console.log(err);
230285
process.exit(1);
231286
}
232287
return undefined;
233288
}
234-
function getLinuxHeadersDir(version) {
289+
290+
function getLinuxInstallDir(version) {
235291
// Get the directory which should contain the headers and
236292
// check if they are present.
237293
// (Using the installed headers will ensure we have the correct ones.)
238294
console.log('Checking for headers, version is ' + version);
239295
try {
240-
var includeDir = child_process.execFileSync('llvm-config-' + version,
296+
var installDir = child_process.execFileSync('llvm-config-' + version,
241297
['--prefix']).toString().trim();
242298
// console.log('Checking for directory ' + include_dir);
243299
// Include directory doesn't need include/lldb on the end but the llvm
244300
// headers can be installed without the lldb headers so check for them.
245-
if (fs.existsSync(includeDir + '/include/lldb')) {
301+
if (fs.existsSync(installDir + '/include/lldb')) {
246302
// console.log('Found ' + include_dir);
247-
return includeDir;
303+
return installDir;
248304
}
249305
} catch (err) {
250306
// Return undefined, we will download the headers.
@@ -257,7 +313,6 @@ function getLinuxHeadersDir(version) {
257313
}
258314

259315
function scriptText(lldbExe) {
260-
261316
let lib = 'llnode.so';
262317
if (osName === 'Darwin') {
263318
lib = 'llnode.dylib';
@@ -278,5 +333,4 @@ fi
278333
279334
${lldbExe} --one-line "plugin load $LLNODE_PLUGIN" --one-line "settings set prompt '(llnode) '" $@
280335
`;
281-
282336
}

0 commit comments

Comments
 (0)