diff --git a/.travis.yml b/.travis.yml index 85af7dbf..4d7a5d64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ dist: trusty before_install: - sudo apt-get -qq update - sudo apt-get install lldb-3.9 liblldb-3.9-dev -y - - git clone https://chromium.googlesource.com/external/gyp.git tools/gyp node_js: - "4" - "6" diff --git a/Makefile b/Makefile index 3fc18011..ef90c5aa 100644 --- a/Makefile +++ b/Makefile @@ -31,11 +31,10 @@ format: .PHONY: configure configure: node scripts/configure.js - ./gyp_llnode .PHONY: plugin plugin: configure - $(MAKE) -C out/ + node-gyp rebuild node scripts/cleanup.js .PHONY: _travis @@ -47,7 +46,7 @@ _travis: .PHONY: clean clean: - $(RM) -r out - $(RM) options.gypi + $(RM) -r build + $(RM) config.gypi $(RM) lldb $(RM) llnode.so llnode.dylib diff --git a/README.md b/README.md index a64ea7fd..d26a4b30 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,9 @@ If you have `lldb` available on your `PATH`, simply run: npm install -g llnode ``` -To use a particular build of lldb, use the `--lldb_exe` option. For example, -on Linux the executable on the `PATH` might be `lldb-3.9`: +To build llnode against a specific lldb version matching an lldb executable, +use the `--lldb_exe` npm option. For example, on Linux the executable on the +`PATH` might be `lldb-3.9`: ```bash npm install --lldb_exe=`which lldb-3.9` -g llnode @@ -245,20 +246,20 @@ make plugin To configure the build yourself: ```bash -# Detect available LLDB installation and download headers if necessary +# Detect available lldb installation and download headers if necessary node scripts/configure.js -# To configure with the detected LLDB installation -./gyp_llnode -# To configure with a specified LLDB installation on OS X/macOS -./gyp_llnode -Dlldb_build_dir=/usr/local/Cellar/llvm/5.0.0 -# To configure with a specified LLDB installation on Linux -./gyp_llnode -Dlldb_dir=/usr/lib/llvm-3.9/ -# To configure with a specified LLDB installation on FreeBSD -./gyp_llnode -Dlldb_dir=/usr/local/llvm39/ - -# Build -make -C out/ -j9 +# To configure with the detected lldb installation +node-gyp configure +# To configure with a specified path to headers, where `$lldb_header_dir/include` +# contains the headers +node-gyp configure -- -Dlldb_header_dir=/usr/local/Cellar/llvm/5.0.0 +# To configure with a specified path to the libraries, where `$lldb_lib_dir/lib` +# contains `liblldb.so` or `liblldb.dylib` +node-gyp configure -- -Dlldb_lib_dir=/usr/lib/llvm-3.9 + +# Build the plugin +node-gyp build # Move the built plugin to the project directory node scripts/cleanup.js diff --git a/binding.gyp b/binding.gyp index 8706104b..aa1a2a5a 100644 --- a/binding.gyp +++ b/binding.gyp @@ -1,3 +1,72 @@ { - "targets": [{ "target_name": "none", "type": "none" }] + "includes": [ + "llnode.gypi", + "config.gypi" + ], + + "variables": { + # gyp does not appear to let you test for undefined variables, so define + # lldb_lib_dir as empty so we can test it later. + "lldb_lib_dir%": "" + }, + + "targets": [{ + "target_name": "plugin", + "type": "shared_library", + "product_prefix": "", + + "include_dirs": [ + ".", + "<(lldb_header_dir)/include", + ], + + "sources": [ + "src/llnode.cc", + "src/llv8.cc", + "src/llv8-constants.cc", + "src/llscan.cc", + ], + + "cflags" : [ "-std=c++11" ], + + "conditions": [ + [ "OS == 'mac'", { + # Necessary for node v4.x + "xcode_settings": { + "OTHER_CPLUSPLUSFLAGS" : [ "-std=c++11", "-stdlib=libc++" ], + "OTHER_LDFLAGS": [ "-stdlib=libc++" ], + }, + + "conditions": [ + [ "lldb_lib_dir == ''", { + "variables": { + "mac_shared_frameworks": "/Applications/Xcode.app/Contents/SharedFrameworks", + }, + "xcode_settings": { + "OTHER_LDFLAGS": [ + "-F<(mac_shared_frameworks)", + "-Wl,-rpath,<(mac_shared_frameworks)", + "-framework LLDB", + ], + }, + }, + # lldb_lib_dir != "" + { + "xcode_settings": { + "OTHER_LDFLAGS": [ + "-Wl,-rpath,<(lldb_lib_dir)/lib", + "-L<(lldb_lib_dir)/lib", + "-l<(lldb_lib)", + ], + }, + }], + ], + }], + ] + }, + { + "target_name": "install", + "type":"none", + "dependencies" : [ "plugin" ] + }], } diff --git a/gyp_llnode b/gyp_llnode deleted file mode 100755 index 2ced74cf..00000000 --- a/gyp_llnode +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python - -import glob -import platform -import os -import subprocess -import sys - -CC = os.environ.get('CC', 'cc') -script_dir = os.path.dirname(__file__) -root = os.path.normpath(script_dir) -output_dir = os.path.join(os.path.abspath(root), 'out') - -sys.path.insert(0, os.path.join(root, 'tools', 'gyp', 'pylib')) -try: - import gyp -except ImportError: - print('You need to install gyp in tools/gyp first, run:') - print(' svn co http://gyp.googlecode.com/svn/trunk tools/gyp'); - print('or') - print(' git clone https://chromium.googlesource.com/external/gyp.git ' + - 'tools/gyp') - sys.exit(42) - - -def host_arch(): - machine = platform.machine() - if machine == 'i386': return 'ia32' - if machine == 'x86_64': return 'x64' - if machine.startswith('arm'): return 'arm' - if machine.startswith('mips'): return 'mips' - return machine # Return as-is and hope for the best. - - -def compiler_version(): - proc = subprocess.Popen(CC.split() + ['--version'], stdout=subprocess.PIPE) - is_clang = 'clang' in proc.communicate()[0].split('\n')[0] - proc = subprocess.Popen(CC.split() + ['-dumpversion'], stdout=subprocess.PIPE) - version = proc.communicate()[0].split('.') - # Allow for (e.g.) gcc version 7 (not 7.0) - version.append('0') - version = map(int, version[:2]) - version = tuple(version) - return (version, is_clang) - - -def run_gyp(args): - rc = gyp.main(args) - if rc != 0: - print 'Error running GYP' - sys.exit(rc) - - -if __name__ == '__main__': - args = sys.argv[1:] - - # GYP bug. - # On msvs it will crash if it gets an absolute path. - # On Mac/make it will crash if it doesn't get an absolute path. - if sys.platform == 'win32': - args.append(os.path.join(root, 'llnode.gyp.json')) - common_fn = os.path.join(root, 'common.gypi') - options_fn = os.path.join(root, 'options.gypi') - # we force vs 2010 over 2008 which would otherwise be the default for gyp - if not os.environ.get('GYP_MSVS_VERSION'): - os.environ['GYP_MSVS_VERSION'] = '2010' - else: - args.append(os.path.join(os.path.abspath(root), 'llnode.gyp.json')) - common_fn = os.path.join(os.path.abspath(root), 'common.gypi') - options_fn = os.path.join(os.path.abspath(root), 'options.gypi') - - if os.path.exists(common_fn): - args.extend(['-I', common_fn]) - - if os.path.exists(options_fn): - args.extend(['-I', options_fn]) - - args.append('--depth=' + root) - - # There's a bug with windows which doesn't allow this feature. - if sys.platform != 'win32': - if '-f' not in args: - args.extend('-f make'.split()) - if 'ninja' not in args: - args.extend(['-Goutput_dir=' + output_dir]) - args.extend(['--generator-output', output_dir]) - (major, minor), is_clang = compiler_version() - args.append('-Dgcc_version=%d' % (10 * major + minor)) - args.append('-Dclang=%d' % int(is_clang)) - - if not any(a.startswith('-Dhost_arch=') for a in args): - args.append('-Dhost_arch=%s' % host_arch()) - - if not any(a.startswith('-Dtarget_arch=') for a in args): - args.append('-Dtarget_arch=%s' % host_arch()) - - gyp_args = list(args) - print gyp_args - run_gyp(gyp_args) diff --git a/llnode.gyp b/llnode.gyp deleted file mode 120000 index 8061de5a..00000000 --- a/llnode.gyp +++ /dev/null @@ -1 +0,0 @@ -llnode.gyp.json \ No newline at end of file diff --git a/llnode.gyp.json b/llnode.gyp.json deleted file mode 100644 index ce6bd42d..00000000 --- a/llnode.gyp.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "variables": { - # gyp does not appear to let you test for undefined variables, so define - # lldb_build_dir as empty so we can test it later. - "lldb_build_dir%": "" - }, - - "targets": [{ - "target_name": "llnode", - "type": "shared_library", - "product_prefix": "", - - "include_dirs": [ - ".", - "<(lldb_dir)/include", - ], - - "sources": [ - "src/llnode.cc", - "src/llv8.cc", - "src/llv8-constants.cc", - "src/llscan.cc", - ], - - "conditions": [ - [ "OS == 'mac'", { - "conditions": [ - [ "lldb_build_dir == ''", { - "variables": { - "mac_shared_frameworks": "/Applications/Xcode.app/Contents/SharedFrameworks", - }, - "xcode_settings": { - "OTHER_LDFLAGS": [ - "-F<(mac_shared_frameworks)", - "-Wl,-rpath,<(mac_shared_frameworks)", - "-framework LLDB", - ], - }, - }, - # lldb_builddir != "" - { - "xcode_settings": { - "OTHER_LDFLAGS": [ - "-Wl,-rpath,<(lldb_build_dir)/lib", - "-L<(lldb_build_dir)/lib", - "-l<(lldb_lib)", - ], - }, - }], - ], - }], - ] - }], -} diff --git a/common.gypi b/llnode.gypi similarity index 98% rename from common.gypi rename to llnode.gypi index f046df56..6e8c8ada 100644 --- a/common.gypi +++ b/llnode.gypi @@ -9,7 +9,7 @@ "msvs_multi_core_compile": "0", # we do enable multicore compiles, but not using the V8 way "gcc_version%": "unknown", "clang%": 1, - "lldb_dir%": "lldb", + "lldb_header_dir%": "lldb", "lldb_lib%": "lldb", "conditions": [ ["GENERATOR == 'ninja'", { diff --git a/package.json b/package.json index 4a6451d4..91dfb27c 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,9 @@ "bin": { "llnode": "llnode.sh" }, - "//": "(Blame C++)", "scripts": { "preinstall": "node scripts/configure.js", - "install": "./gyp_llnode && ( gmake -C out/ || make -C out/ )", + "install": "node-gyp rebuild", "postinstall": "node scripts/cleanup.js", "test": "tape test/*-test.js" }, @@ -22,9 +21,8 @@ }, "files": [ "Makefile", - "llnode.gyp.json", - "gyp_llnode", - "common.gypi", + "binding.gyp", + "llnode.gypi", "src/", "scripts/" ], diff --git a/scripts/cleanup.js b/scripts/cleanup.js index 6614c8d9..3739c742 100644 --- a/scripts/cleanup.js +++ b/scripts/cleanup.js @@ -2,6 +2,7 @@ const os = require('os'); const child_process = require('child_process'); +const fs = require('fs'); const cwd = process.cwd(); const osName = os.type(); @@ -11,12 +12,20 @@ if (osName === 'Darwin') { libExt = 'dylib'; } -const llnodeLib = `llnode.${libExt}`; +const llnodeLib = `plugin.${libExt}`; +const destLib = `llnode.${libExt}`; -// Move the library somewhere easy to remember. -console.log(`Copying ${cwd}/out/Release/${llnodeLib} to ${cwd}/${llnodeLib}`); -child_process.execSync(`mv ${cwd}/out/Release/${llnodeLib} ${cwd}/${llnodeLib}`); +let buildPath = `${cwd}/build/Release/${llnodeLib}`; + +if (!fs.existsSync(buildPath)) { + buildPath = `${cwd}/build/Debug/${llnodeLib}`; +} + +const destPath = `${cwd}/${destLib}`; + +console.log(`Moving ${buildPath} to ${destPath}`); +fs.renameSync(buildPath, destPath); console.log(`${os.EOL}llnode plugin installed, load in lldb with:`); -console.log(`(lldb) plugin load ${cwd}/${llnodeLib}`); +console.log(`(lldb) plugin load ${destPath}`); console.log(`or copy plugin to lldb system plugin directory, see www.npmjs.org/llnode${os.EOL}`); diff --git a/scripts/configure.js b/scripts/configure.js index c9c5b582..5941a456 100644 --- a/scripts/configure.js +++ b/scripts/configure.js @@ -6,15 +6,13 @@ const path = require('path'); const child_process = require('child_process'); const lldb = require('./lldb'); - function main() { const buildDir = process.cwd(); console.log('Build dir is: ' + buildDir); const osName = os.type(); const installation = configureInstallation(osName, buildDir); + writeConfig(installation.config); linkHeadersDir(installation.prefix); - const gypDir = getGypDir(buildDir); - linkGyp(gypDir); writeLlnodeScript(buildDir, installation.executable, osName); // Exit with success. process.exit(0); @@ -35,6 +33,8 @@ function configureInstallation(osName, buildDir) { // - If we need to download the headers. (Linux may have them installed) let installation; let prefix; // Similar to what `llvm-config --prefix` returns + // On Linux and BSD the config is always empty. + const config = {}; if (osName === 'Darwin') { const darwin = require('./darwin'); @@ -44,28 +44,21 @@ function configureInstallation(osName, buildDir) { prefix = lldb.cloneHeaders(installation.version, buildDir); } else { // Using custom installation // Need to configure with the custom prefix - const config = { - variables: { 'lldb_build_dir%': prefix } - }; - writeConfig(config); + config.variables = { 'lldb_lib_dir%': prefix }; } } else if (osName === 'Linux') { const linux = require('./linux'); installation = linux.getLldbInstallation(); - if (installation.prefix === undefined) + if (installation.prefix === undefined) { // Could not find the headers, need to download them prefix = lldb.cloneHeaders(installation.version, buildDir); - else + } else { prefix = installation.prefix; - - // ./lldb will always be linked to the prefix on Linux - writeConfig({}); + } } else if (osName === 'FreeBSD') { const freebsd = require('./freebsd'); installation = freebsd.getLldbInstallation(); prefix = installation.prefix; - // ./lldb will always be linked to the prefix - writeConfig({}); } else { console.log(`Unsupported OS: ${osName}`); process.exit(1); @@ -74,13 +67,14 @@ function configureInstallation(osName, buildDir) { return { executable: installation.executable, version: installation.version, - prefix + prefix, + config }; } /** - * Link to the headers file so we can run gyp_llnode directly and don't need to - * setup parameters to pass. + * Link to the headers file so we can run `node-gyp configure` directly + * and don't need to setup parameters to pass. * @param {string} lldbInstallDir The destination of the symlink */ function linkHeadersDir(lldbInstallDir) { @@ -93,47 +87,6 @@ function linkHeadersDir(lldbInstallDir) { fs.symlinkSync(lldbInstallDir, 'lldb'); } -/** - * Get the path to the GYP installation - * @param {string} buildDir Path of the project directory - */ -function getGypDir(buildDir) { - // npm explore has a different root folder when using -g - // So we are tacking on the extra the additional subfolders - let gypSubDir = 'node-gyp'; - if (process.env.npm_config_global) - gypSubDir = 'npm/node_modules/node-gyp'; - - // npm can be in a different location than the current - // location for global installs so we need find out where the npm is - let npmLocation = child_process.execFileSync('which', ['npm']); - let npmModules = path.join( - npmLocation.toString(), '../../lib/node_modules/npm'); - - // Initialize GYP - // We can use the node-gyp that comes with npm. - // We can locate it with npm -g explore npm npm explore node-gyp pwd - // It might have been neater to make node-gyp one of our dependencies - // *but* they don't get installed until after the install step has run. - let gypDir = child_process.execFileSync( - 'npm', - ['-g', 'explore', npmModules, 'npm', 'explore', gypSubDir, 'pwd'], - { cwd: buildDir } - ).toString().trim(); - return gypDir; -} - -/** - * Link tools/gyp to the GYP installation - * @param {string} gypDir path to the GYP installation - */ -function linkGyp(gypDir) { - child_process.execSync('rm -rf tools'); - fs.mkdirSync('tools'); - console.log(`Linking tools/gyp to ${gypDir}/gyp`); - fs.symlinkSync(`${gypDir}/gyp`, 'tools/gyp'); -} - /** * Generate the llnode shortcut script * @param {string} buildDir Path of the project directory @@ -153,8 +106,8 @@ function writeLlnodeScript(buildDir, lldbExe, osName) { */ function writeConfig(config) { const options = JSON.stringify(config, null, 2); - fs.writeFileSync('options.gypi', options, 'utf-8'); - console.log('Writing options.gypi:'); + fs.writeFileSync('config.gypi', options, 'utf-8'); + console.log('Writing config.gypi:'); console.log(options); }