|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +const os = require('os'); |
| 4 | +const fs = require('fs'); |
| 5 | +const child_process = require('child_process'); |
| 6 | + |
| 7 | +const lldbReleases = { |
| 8 | + '4.0': 'master', |
| 9 | + '3.9': 'release_39', |
| 10 | + '3.8': 'release_38', |
| 11 | + '3.7': 'release_37', |
| 12 | + '3.6': 'release_36', |
| 13 | + '3.5': 'release_35', |
| 14 | + '3.4': 'release_34', |
| 15 | +}; |
| 16 | + |
| 17 | +const buildDir = process.cwd(); |
| 18 | + |
| 19 | +console.log('Build dir is: ' + buildDir); |
| 20 | + |
| 21 | +const osName = os.type(); |
| 22 | + |
| 23 | +var lldbVersion; |
| 24 | +var lldbHeadersBranch; |
| 25 | +var lldbIncludeDir; |
| 26 | + |
| 27 | +// Need to determine: |
| 28 | +// - What level of lldb we are running. |
| 29 | +// - If we need the headers. (Linux may have them installed) |
| 30 | +var lldbExe = 'lldb'; |
| 31 | + |
| 32 | +if (osName === 'Darwin') { |
| 33 | + |
| 34 | + lldbVersion = getDarwinRelease(); |
| 35 | + |
| 36 | + if (lldbVersion === undefined) { |
| 37 | + console.log('Unable to locate lldb binary. llnode installation failed.'); |
| 38 | + process.exit(1); |
| 39 | + } |
| 40 | + |
| 41 | + lldbHeadersBranch = lldbReleases[lldbVersion]; |
| 42 | + lldbIncludeDir = 'lldb-' + lldbVersion; |
| 43 | + |
| 44 | +} else if (osName === 'Linux') { |
| 45 | + |
| 46 | + lldbExe = getLldbExecutable(); |
| 47 | + lldbVersion = getLinuxVersion(lldbExe); |
| 48 | + |
| 49 | + if (lldbVersion === undefined) { |
| 50 | + console.log('Unable to locate lldb binary. llnode installation failed.'); |
| 51 | + process.exit(1); |
| 52 | + } |
| 53 | + |
| 54 | + // console.log('lldb_version is ' + lldb_version) |
| 55 | + var installedHeadersDir = getLinuxHeadersDir(lldbVersion); |
| 56 | + // console.log('installed_headers_dir is ' + installed_headers_dir); |
| 57 | + if (installedHeadersDir === undefined) { |
| 58 | + // Initialising lldb_headers_branch will cause us to clone them. |
| 59 | + lldbHeadersBranch = lldbReleases[lldbVersion]; |
| 60 | + lldbIncludeDir = 'lldb-' + lldbVersion; |
| 61 | + } else { |
| 62 | + lldbIncludeDir = installedHeadersDir; |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +console.log(`Installing llnode for ${lldbExe}, lldb version ${lldbVersion}`); |
| 67 | + |
| 68 | +// Check out source code of the LLDB that is compatible with OS X's default lldb |
| 69 | +// TODO: The llvm project is probably moving to github soon at that point we |
| 70 | +// should stop using the mirror. |
| 71 | +if (lldbHeadersBranch != undefined) { |
| 72 | + console.log('Cloning lldb from ' + lldbHeadersBranch); |
| 73 | + child_process.execFileSync('git', |
| 74 | + ['clone', '--depth=1', '-b', lldbHeadersBranch, |
| 75 | + 'https://github.com/llvm-mirror/lldb.git', lldbIncludeDir], |
| 76 | + {cwd: buildDir}); |
| 77 | +} |
| 78 | + |
| 79 | +// Link to the headers file so we can run gyp_llnode directly and don't need to |
| 80 | +// setup parameters to pass it. |
| 81 | +console.log(`Linking lldb to include directory ${lldbIncludeDir}`); |
| 82 | +fs.symlinkSync(lldbIncludeDir, 'lldb'); |
| 83 | + |
| 84 | +// Initialize GYP |
| 85 | +// We can use the node-gyp that comes with npm. |
| 86 | +// We can locate it with npm -g explore npm npm explore node-gyp pwd |
| 87 | +// It might have been neater to make node-gyp one of our dependencies |
| 88 | +// *but* they don't get installed until after the install step has run. |
| 89 | +var gypDir = child_process.execFileSync('npm', |
| 90 | + ['-g', 'explore', 'npm', 'npm', 'explore', 'node-gyp', 'pwd'], |
| 91 | + {cwd: buildDir}).toString().trim(); |
| 92 | +fs.mkdirSync('tools'); |
| 93 | +console.log(`Linking tools/gyp to ${gypDir}/gyp`); |
| 94 | +fs.symlinkSync(`${gypDir}/gyp`, 'tools/gyp'); |
| 95 | + |
| 96 | +// Exit with success. |
| 97 | +process.exit(0); |
| 98 | + |
| 99 | +// On Mac the lldb version string doesn't match the original lldb versions. |
| 100 | +function getDarwinRelease() { |
| 101 | + var xcodeStr; |
| 102 | + try { |
| 103 | + xcodeStr = child_process.execFileSync('xcodebuild', ['-version']) |
| 104 | + .toString(); |
| 105 | + } catch (err) { |
| 106 | + return undefined; |
| 107 | + } |
| 108 | + var versionStr = ''; |
| 109 | + var splitStr = xcodeStr.split(os.EOL); |
| 110 | + for (var str of splitStr) { |
| 111 | + if (str.indexOf('Xcode') != -1) { |
| 112 | + versionStr = str.split(' ')[1]; |
| 113 | + break; |
| 114 | + } |
| 115 | + } |
| 116 | + // console.log('Xcode version is ' + version_str) |
| 117 | + |
| 118 | + var version = parseFloat(versionStr); |
| 119 | + if (version > 8.0) { |
| 120 | + return '3.8'; |
| 121 | + } else { |
| 122 | + return '3.4'; |
| 123 | + } |
| 124 | +} |
| 125 | + |
| 126 | +// Find the 'best' lldb to use. Either: |
| 127 | +// - the one specified by the user using npm --llnode_exe=... install llnode |
| 128 | +// - the default lldb executable |
| 129 | +// - the higest known lldb version |
| 130 | +function getLldbExecutable() { |
| 131 | + var lldbExe = process.env.npm_config_lldb_exe; |
| 132 | + if (lldbExe === undefined) { |
| 133 | + var lldbExeNames = ['lldb', 'lldb-4.0', 'lldb-3.9', |
| 134 | + 'lldb-3.8', 'lldb-3.7', 'lldb-3.6']; |
| 135 | + for (var lldbExeVersion of lldbExeNames) { |
| 136 | + try { |
| 137 | + lldbExe = child_process.execSync('which ' + |
| 138 | + lldbExeVersion).toString().trim(); |
| 139 | + // If the result starts with '/' `which` found a path. |
| 140 | + if (lldbExe.startsWith('/')) { |
| 141 | + break; |
| 142 | + } |
| 143 | + } catch (err) { |
| 144 | + // Do nothing - we expect not to find some of these. |
| 145 | + } |
| 146 | + } |
| 147 | + } |
| 148 | + return lldbExe; |
| 149 | +} |
| 150 | + |
| 151 | +// There are multiple versions of lldb available for the various linux distos. |
| 152 | +// Use the default unless --llnode_exe= has been set on the command line. |
| 153 | +function getLinuxVersion(lldbExe) { |
| 154 | + |
| 155 | + var lldbStr; |
| 156 | + try { |
| 157 | + lldbStr = child_process.execFileSync(lldbExe, ['-v']).toString(); |
| 158 | + } catch (err) { |
| 159 | + return undefined; |
| 160 | + } |
| 161 | + // Ignore minor revisions like 3.8.1 |
| 162 | + if (lldbStr.indexOf('version 4.0') > 0) { |
| 163 | + return '4.0'; |
| 164 | + } else if (lldbStr.indexOf('version 3.9') > 0) { |
| 165 | + return '3.9'; |
| 166 | + } else if (lldbStr.indexOf('version 3.8') > 0) { |
| 167 | + return '3.8'; |
| 168 | + } else if (lldbStr.indexOf('version 3.7') > 0) { |
| 169 | + return '3.7'; |
| 170 | + } if (lldbStr.indexOf('version 3.6') > 0) { |
| 171 | + return '3.6'; |
| 172 | + } if (lldbStr.indexOf('version 3.5') > 0) { |
| 173 | + return '3.5'; |
| 174 | + } |
| 175 | + return undefined; |
| 176 | +} |
| 177 | + |
| 178 | +function getLinuxHeadersDir(version) { |
| 179 | + // Get the directory which should contain the headers and |
| 180 | + // check if they are present. |
| 181 | + // (Using the installed headers will ensure we have the correct ones.) |
| 182 | + console.log('Checking for headers, version is ' + version); |
| 183 | + try { |
| 184 | + var includeDir = child_process.execFileSync('llvm-config-' + version, |
| 185 | + ['--prefix']).toString().trim(); |
| 186 | + // console.log('Checking for directory ' + include_dir); |
| 187 | + // Include directory doesn't need include/lldb on the end but the llvm |
| 188 | + // headers can be installed without the lldb headers so check for them. |
| 189 | + if (fs.existsSync(includeDir + '/include/lldb')) { |
| 190 | + // console.log('Found ' + include_dir); |
| 191 | + return includeDir; |
| 192 | + } |
| 193 | + } catch (err) { |
| 194 | + // Return undefined, we will download the headers. |
| 195 | + } |
| 196 | + // On Redhat the headers are just installed in /usr/include |
| 197 | + if (fs.existsSync('/usr/include/lldb')) { |
| 198 | + return '/usr'; |
| 199 | + } |
| 200 | + return undefined; |
| 201 | +} |
0 commit comments