Skip to content

Commit

Permalink
lib: add gyp.js support
Browse files Browse the repository at this point in the history
See: nodejs#960

Added initial `gyp.js` support with --gypjs command line option.
Environment variable `npm_config_gypjs` also turns this option on.

Update configure and build usage strings depending on `npm_config_gypjs`
environment variable.

Set `npm_config_gypjs` env variable if `--gypjs` command-line option
was set to affect usage text for `configure` and `build` commands.

Update usage strings if `--gypjs` command-line option was supplied

Trying to load gyp.js module only if --gypjs command-line option was supplied.
  • Loading branch information
pmed authored and indutny committed Jan 20, 2017
1 parent ff9a6fa commit d16ae14
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 122 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,37 @@ you can require the `.node` file with Node and run your tests!
__Note:__ To create a _Debug_ build of the bindings file, pass the `--debug` (or
`-d`) switch when running either the `configure`, `build` or `rebuild` command.

#### Usage without Python

There is a [`gyp.js`](https://github.com/indutny/gyp.js/) project, a GYP
implementation in JavaScript. It generates [`Ninja`](https://ninja-build.org/)
build files and requires no Python installation.

In this case you will need to install [`Ninja`](https://ninja-build.org/) build
tool and a C/C++ compiler toolchain.

To generate projects files with `gyp.js` instead of `gyp` and to build them with
`ninja`, please supply a command-line option `--gypjs` in `node-gyp` command.

``` bash
$ node-gyp configure --gypjs
```

It is also possible to set `npm_config_gypjs` environment variable to turn on
the `gyp.js` usage.

``` bash
$ npm_config_gypjs=1 node-gyp build
```

Path to an existing `ninja` installation can be set with a `--ninja` command-line
option or in a `NINJA` environment variable.

``` bash
$ node-gyp configure --gypjs --ninja=/my/path/to/ninja
$ npm_config_gypjs=1 NINJA=/my/path/to/ninja node-gyp build
```


The "binding.gyp" file
----------------------
Expand Down Expand Up @@ -184,6 +215,8 @@ Command Options
| `--python=$path` | Set path to the python (2) binary
| `--msvs_version=$version` | Set Visual Studio version (win)
| `--solution=$solution` | Set Visual Studio Solution version (win)
| `--gypjs` | Use gyp.js instead of gyp
| `--ninja=$ninja` | Override ninja command (with --gypjs)


License
Expand Down
2 changes: 1 addition & 1 deletion addon.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
'-luuid.lib',
'-lodbc32.lib',
'-lDelayImp.lib',
'-l"<(node_root_dir)/$(ConfigurationName)/<(node_lib_file)"'
'-l"<(node_lib_file)"'
],
'msvs_disabled_warnings': [
# warning C4251: 'node::ObjectWrap::handle_' : class 'v8::Persistent<T>'
Expand Down
136 changes: 64 additions & 72 deletions lib/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ var fs = require('graceful-fs')
, glob = require('glob')
, log = require('npmlog')
, which = require('which')
, mkdirp = require('mkdirp')
, exec = require('child_process').exec
, processRelease = require('./process-release')
, win = process.platform == 'win32'

exports.usage = 'Invokes `' + (win ? 'msbuild' : 'make') + '` and builds the module'
exports.usage = 'Invokes `' + (process.env.npm_config_gypjs ? 'ninja' :
(win ? 'msbuild' : 'make')) + '` and builds the module'

function build (gyp, argv, callback) {
var platformMake = 'make'
Expand All @@ -36,8 +36,10 @@ function build (gyp, argv, callback) {
, config
, arch
, nodeDir
, copyDevLib

if (gyp.opts.gypjs) {
command = gyp.opts.ninja || process.env.NINJA || 'ninja'
}
loadConfigGypi()

/**
Expand All @@ -60,7 +62,6 @@ function build (gyp, argv, callback) {
buildType = config.target_defaults.default_configuration
arch = config.variables.target_arch
nodeDir = config.variables.nodedir
copyDevLib = config.variables.copy_dev_lib == 'true'

if ('debug' in gyp.opts) {
buildType = gyp.opts.debug ? 'Debug' : 'Release'
Expand All @@ -73,7 +74,7 @@ function build (gyp, argv, callback) {
log.verbose('architecture', arch)
log.verbose('node dev dir', nodeDir)

if (win) {
if (win && !gyp.opts.gypjs) {
findSolutionFile()
} else {
doWhich()
Expand Down Expand Up @@ -105,7 +106,7 @@ function build (gyp, argv, callback) {
// First make sure we have the build command in the PATH
which(command, function (err, execPath) {
if (err) {
if (win && /not found/.test(err.message)) {
if (win && !gyp.opts.gypjs && /not found/.test(err.message)) {
// On windows and no 'msbuild' found. Let's guess where it is
findMsbuild()
} else {
Expand All @@ -115,7 +116,7 @@ function build (gyp, argv, callback) {
return
}
log.verbose('`which` succeeded for `' + command + '`', execPath)
copyNodeLib()
doBuild()
})
}

Expand Down Expand Up @@ -173,36 +174,12 @@ function build (gyp, argv, callback) {
return
}
command = msbuildPath
copyNodeLib()
doBuild()
})
})()
})
}

/**
* Copies the node.lib file for the current target architecture into the
* current proper dev dir location.
*/

function copyNodeLib () {
if (!win || !copyDevLib) return doBuild()

var buildDir = path.resolve(nodeDir, buildType)
, archNodeLibPath = path.resolve(nodeDir, arch, release.name + '.lib')
, buildNodeLibPath = path.resolve(buildDir, release.name + '.lib')

mkdirp(buildDir, function (err, isNew) {
if (err) return callback(err)
log.verbose('"' + buildType + '" dir needed to be created?', isNew)
var rs = fs.createReadStream(archNodeLibPath)
, ws = fs.createWriteStream(buildNodeLibPath)
log.verbose('copying "' + release.name + '.lib" for ' + arch, buildNodeLibPath)
rs.pipe(ws)
rs.on('error', callback)
ws.on('error', callback)
rs.on('end', doBuild)
})
}

/**
* Actually spawn the process and compile the module.
Expand All @@ -212,57 +189,72 @@ function build (gyp, argv, callback) {

// Enable Verbose build
var verbose = log.levels[log.level] <= log.levels.verbose
if (!win && verbose) {
argv.push('V=1')
}
if (win && !verbose) {
argv.push('/clp:Verbosity=minimal')
}
if (!gyp.opts.gypjs) {
if (!win && verbose) {
argv.push('V=1')
}
if (win && !verbose) {
argv.push('/clp:Verbosity=minimal')
}

if (win) {
// Turn off the Microsoft logo on Windows
argv.push('/nologo')
}
if (win) {
// Turn off the Microsoft logo on Windows
argv.push('/nologo')
}

// Specify the build type, Release by default
if (win) {
var p = arch === 'x64' ? 'x64' : 'Win32'
argv.push('/p:Configuration=' + buildType + ';Platform=' + p)
if (jobs) {
var j = parseInt(jobs, 10)
if (!isNaN(j) && j > 0) {
argv.push('/m:' + j)
} else if (jobs.toUpperCase() === 'MAX') {
argv.push('/m:' + require('os').cpus().length)
// Specify the build type, Release by default
if (win) {
var p = arch === 'x64' ? 'x64' : 'Win32'
argv.push('/p:Configuration=' + buildType + ';Platform=' + p)
if (jobs) {
var j = parseInt(jobs, 10)
if (!isNaN(j) && j > 0) {
argv.push('/m:' + j)
} else if (jobs.toUpperCase() === 'MAX') {
argv.push('/m:' + require('os').cpus().length)
}
}
} else {
argv.push('BUILDTYPE=' + buildType)
// Invoke the Makefile in the 'build' dir.
argv.push('-C')
argv.push('build')
if (jobs) {
var j = parseInt(jobs, 10)
if (!isNaN(j) && j > 0) {
argv.push('--jobs')
argv.push(j)
} else if (jobs.toUpperCase() === 'MAX') {
argv.push('--jobs')
argv.push(require('os').cpus().length)
}
}
}

if (win) {
// did the user specify their own .sln file?
var hasSln = argv.some(function (arg) {
return path.extname(arg) == '.sln'
})
if (!hasSln) {
argv.unshift(gyp.opts.solution || guessedSolution)
}
}
} else {
argv.push('BUILDTYPE=' + buildType)
// Invoke the Makefile in the 'build' dir.
argv.push('-C')
argv.push('build')
// build with ninja
if (verbose) {
argv.push('-v')
}
// Specify the build type, Release by default
argv.push('-C', path.join('build', buildType))
if (jobs) {
var j = parseInt(jobs, 10)
var j = jobs.toUpperCase() === 'MAX'? require('os').cpus().length : parseInt(jobs, 10)
if (!isNaN(j) && j > 0) {
argv.push('--jobs')
argv.push(j)
} else if (jobs.toUpperCase() === 'MAX') {
argv.push('--jobs')
argv.push(require('os').cpus().length)
argv.push('-j' + j)
}
}
}

if (win) {
// did the user specify their own .sln file?
var hasSln = argv.some(function (arg) {
return path.extname(arg) == '.sln'
})
if (!hasSln) {
argv.unshift(gyp.opts.solution || guessedSolution)
}
}

var proc = gyp.spawn(command, argv)
proc.on('exit', onExit)
}
Expand Down
Loading

0 comments on commit d16ae14

Please sign in to comment.