Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for distributing prebuilds as platform-specific packages #63

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,14 @@ module.exports = binding
An added benefit of this approach is that your native modules will work across multiple node and electron versions without having the user
need to reinstall or recompile them - as long as you produce prebuilds for all versions. With Node-API you only have to produce prebuilds for every runtime.

When publishing your module to npm remember to include the `./prebuilds` folder.

## Platform-specific Packages
As an alternate to including all prebuilds directly in your published package, you can use `--optional-packages` to setup the prebuilds for publishing as separate platform-specific packages. Using this option, each prebuild directory will also include a package.json that specifies the target platform and architectures along with some basic package files. Each of these prebuild directories can then be published as separate packages in NPM. In addition,
the main package should specify all the platform packages as `optionalDependencies`. When installed, NPM (or Yarn, etc.) will then only install the optional dependency with the platform/architecture matching the target machine.
kriszyp marked this conversation as resolved.
Show resolved Hide resolved

This provides both the efficiency of only needing to download/install the binary (or binaries) needed for the current platform, but also the key benefit of the prebuildify system in that binaries are downloaded and available as part of the normal NPM install process (no install scripts for extra downloads are necessary). When using this method, you should omit the prebuilds folder when publishing your package (since they will be separately downloaded).
kriszyp marked this conversation as resolved.
Show resolved Hide resolved

If you do not use this option, when publishing your module to npm, remember to include the `./prebuilds` folder.
kriszyp marked this conversation as resolved.
Show resolved Hide resolved

That's it! Happy native hacking.

Expand All @@ -94,6 +101,7 @@ Options can be provided via (in order of precedence) the programmatic API, the C
| `--tag-uv` | - | `false` | Tag prebuild with `uv`\*\*\*
| `--tag-armv` | - | `false` | Tag prebuild with `armv`\*\*\*
| `--tag-libc` | - | `false` | Tag prebuild with `libc`\*\*\*
| `--optional-dependencies`| - | `false` | Add package.json and basic files for package publishing
vweevers marked this conversation as resolved.
Show resolved Hide resolved
| `--preinstall` | - | - | Command to run before build
| `--postinstall` | - | - | Command to run after build
| `--shell` | `PREBUILD_SHELL` | `'sh'` on Android | Shell to spawn commands in
Expand Down
3 changes: 2 additions & 1 deletion bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ var argv = minimist(process.argv.slice(2), {
tagArmv: 'tag-armv',
tagLibc: 'tag-libc',
electronCompat: 'electron-compat',
optionalPackages: 'optional-packages',
cache: 'c'
},
boolean: ['quiet', 'strip', 'napi', 'debug', 'all', 'electron-compat']
boolean: ['quiet', 'optional-packages', 'strip', 'napi', 'debug', 'all', 'electron-compat']
})

argv.targets = [].concat(argv.target || [])
Expand Down
23 changes: 22 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ function prebuildify (opts, cb) {
if (opts.arch === 'ia32' && opts.platform === 'linux' && opts.arch !== os.arch()) {
opts.env.CFLAGS = '-m32'
}
var packageData
if (opts.optionalPackages) {
packageData = JSON.parse(fs.readFileSync(path.join(opts.cwd, 'package.json')))
}

// Since [email protected] npm adds its bundled node-gyp to PATH, taking precedence
// over the local .bin folder. Counter that by (again) adding .bin to PATH.
Expand All @@ -71,7 +75,24 @@ function prebuildify (opts, cb) {
if (err) return cb(err)
loop(opts, function (err) {
if (err) return cb(err)

if (opts.optionalPackages) {
var description = 'Platform specific binary for ' + packageData.name + ' on ' + opts.platform + ' OS with ' + opts.arch + ' architecture'
fs.writeFileSync(path.join(opts.builds, 'package.json'), JSON.stringify({
name: packageData.name + '-' + opts.platform + '-' + opts.arch,
vweevers marked this conversation as resolved.
Show resolved Hide resolved
version: packageData.version,
os: [opts.platform],
cpu: [opts.arch],
// copy some of the useful package metadata, if any of these are missing, should just be skipped when stringified
license: packageData.license,
author: packageData.author,
repository: packageData.repository,
bugs: packageData.bugs,
homepage: packageData.homepage,
description
}, null, 2))
vweevers marked this conversation as resolved.
Show resolved Hide resolved
fs.writeFileSync(path.join(opts.builds, 'index.js'), '') // needed to resolve package
fs.writeFileSync(path.join(opts.builds, 'README.md'), description)
}
if (opts.artifacts) return copyRecursive(opts.artifacts, opts.builds, cb)
return cb()
})
Expand Down