mirror of
https://github.com/Llewellynvdm/nativefier.git
synced 2024-12-22 18:18:55 +00:00
Implement multi-target options and refactor code
This adds support for --all, --platform=all, and --arch=all. In order to accommodate outputting multiple directories for multiple platforms and architectures, this also implements a new directory structure under the output folder (distinguished by both platform and arch). This structure is applied even to OS X distributions, which formerly were output directly to an .app folder. This could be considered a backwards-incompatible change. One other backwards-incompatible change is the value that the packager function passes to the callback, which is now always an array of paths, rather than just a single path. The behavior of the icon option has also been modified to use its basename and apply .ico or .icns depending on platform, to make it usable with --all and --platform=all. This attempts to maximize backwards compatibility, by allowing a full filename to be specified, but replacing the filename's extension with what is appropriate for each target platform. Alternatively, the extension can now be omitted. In the process of implementing this, it became evident that some things were being done in 3 different places, and weren't always being done consistently, so I've deduplicated everything I could. This also includes a few other changes to improve stability for multi-target runs, and other fixes: * Avoid targeting darwin if the environment doesn't support symlinks, to avoid the process bailing out on Windows * Implement --overwrite centrally in index.js such that it explicitly skips if an output directory already exists, for consistency with all target platforms and to avoid any possible errors that would halt operation during one target of a multi-target run * Use ncp instead of mv to move to finalPath, which avoids flakiness I noticed when testing on Windows 8 especially with multi-target runs * Simplify temp directory logic by using a nested structure, so there is only one top-level directory to clean up * Reinstate fix from #55 which seems to have been clobbered by a later merge * linux.createApp now resolves to the final output directory; it was formerly resolving to the executable path * mac.createApp now replaces space with underscore in bundle IDs * Only the platform modules that are needed are loaded * The win32 module only loads rcedit if needed This also fixes a couple of missing updates to docs (readme/usage). This commit addresses the following issues: * Resolves #40 * Resolves #38 * Resolves #70 * Works around #71 * Resolves #84 by reinstating #55
This commit is contained in:
parent
cff6ab50ee
commit
a157f716a5
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
downloaded/*.zip
|
|
||||||
node_modules
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
test/dist
|
test/dist
|
9
cli.js
9
cli.js
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
var fs = require('fs')
|
var fs = require('fs')
|
||||||
var args = require('minimist')(process.argv.slice(2), {boolean: ['prune', 'asar', 'overwrite']})
|
var args = require('minimist')(process.argv.slice(2), {boolean: ['prune', 'asar', 'all', 'overwrite']})
|
||||||
var packager = require('./')
|
var packager = require('./')
|
||||||
var usage = fs.readFileSync(__dirname + '/usage.txt').toString()
|
var usage = fs.readFileSync(__dirname + '/usage.txt').toString()
|
||||||
|
|
||||||
@ -16,17 +16,18 @@ if (protocolSchemes && protocolNames && protocolNames.length === protocolSchemes
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.dir || !args.name || !args.platform || !args.arch || !args.version) {
|
if (!args.dir || !args.name || !args.version || (!args.all && (!args.platform || !args.arch))) {
|
||||||
console.error(usage)
|
console.error(usage)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
packager(args, function done (err, appPath) {
|
packager(args, function done (err, appPaths) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.message) console.error(err.message)
|
if (err.message) console.error(err.message)
|
||||||
else console.error(err, err.stack)
|
else console.error(err, err.stack)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error('Wrote new app to', appPath)
|
if (appPaths.length > 1) console.error('Wrote new apps to:\n' + appPaths.join('\n'))
|
||||||
|
else if (appPaths.length === 1) console.error('Wrote new app to', appPaths[0])
|
||||||
})
|
})
|
||||||
|
159
common.js
159
common.js
@ -1,50 +1,139 @@
|
|||||||
var asar = require('asar')
|
|
||||||
var child = require('child_process')
|
var child = require('child_process')
|
||||||
|
var fs = require('fs')
|
||||||
|
var os = require('os')
|
||||||
var path = require('path')
|
var path = require('path')
|
||||||
|
|
||||||
|
var asar = require('asar')
|
||||||
|
var mkdirp = require('mkdirp')
|
||||||
|
var ncp = require('ncp').ncp
|
||||||
var rimraf = require('rimraf')
|
var rimraf = require('rimraf')
|
||||||
|
var series = require('run-series')
|
||||||
|
|
||||||
|
function asarApp (appPath, cb) {
|
||||||
|
var src = path.join(appPath)
|
||||||
|
var dest = path.join(appPath, '..', 'app.asar')
|
||||||
|
asar.createPackage(src, dest, function (err) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
rimraf(src, function (err) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
cb(null, dest)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateFinalBasename (opts) {
|
||||||
|
return opts.name + '-' + opts.platform + '-' + opts.arch
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateFinalPath (opts) {
|
||||||
|
return path.join(opts.out || process.cwd(), generateFinalBasename(opts))
|
||||||
|
}
|
||||||
|
|
||||||
|
function userIgnoreFilter (opts) {
|
||||||
|
return function filter (file) {
|
||||||
|
file = file.split(path.resolve(opts.dir))[1]
|
||||||
|
|
||||||
|
if (path.sep === '\\') {
|
||||||
|
// convert slashes so unix-format ignores work
|
||||||
|
file = file.replace(/\\/g, '/')
|
||||||
|
}
|
||||||
|
|
||||||
|
var ignore = opts.ignore || []
|
||||||
|
if (!Array.isArray(ignore)) ignore = [ignore]
|
||||||
|
for (var i = 0; i < ignore.length; i++) {
|
||||||
|
if (file.match(ignore[i])) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
asarApp: function asarApp (finalDir, cb) {
|
generateFinalPath: generateFinalPath,
|
||||||
var src = path.join(finalDir, 'app')
|
|
||||||
var dest = path.join(finalDir, 'app.asar')
|
initializeApp: function initializeApp (opts, templatePath, appRelativePath, callback) {
|
||||||
asar.createPackage(src, dest, function (err) {
|
// Performs the following initial operations for an app:
|
||||||
if (err) return cb(err)
|
// * Creates temporary directory
|
||||||
rimraf(src, function (err) {
|
// * Copies template into temporary directory
|
||||||
if (err) return cb(err)
|
// * Copies user's app into temporary directory
|
||||||
cb(null, dest)
|
// * Prunes non-production node_modules (if opts.prune is set)
|
||||||
|
// * Creates an asar (if opts.asar is set)
|
||||||
|
|
||||||
|
var tempParent = path.join(os.tmpdir(), 'electron-packager', opts.platform + '-' + opts.arch)
|
||||||
|
var tempPath = path.join(tempParent, generateFinalBasename(opts))
|
||||||
|
// Path to `app` directory
|
||||||
|
var appPath = path.join(tempPath, appRelativePath)
|
||||||
|
|
||||||
|
var operations = [
|
||||||
|
function (cb) {
|
||||||
|
rimraf(tempParent, function () {
|
||||||
|
// Ignore errors (e.g. directory didn't exist anyway)
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
function (cb) {
|
||||||
|
mkdirp(tempPath, cb)
|
||||||
|
},
|
||||||
|
function (cb) {
|
||||||
|
ncp(templatePath, tempPath, cb)
|
||||||
|
},
|
||||||
|
function (cb) {
|
||||||
|
ncp(opts.dir, appPath, {filter: userIgnoreFilter(opts), dereference: true}, cb)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// Prune and asar are now performed before platform-specific logic, primarily so that
|
||||||
|
// appPath is predictable (e.g. before .app is renamed for mac)
|
||||||
|
if (opts.prune) {
|
||||||
|
operations.push(function (cb) {
|
||||||
|
child.exec('npm prune --production', {cwd: appPath}, cb)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.asar) {
|
||||||
|
operations.push(function (cb) {
|
||||||
|
asarApp(path.join(appPath), cb)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
series(operations, function (err) {
|
||||||
|
if (err) return callback(err)
|
||||||
|
// Resolve to path to temporary app folder for platform-specific processes to use
|
||||||
|
callback(null, tempPath)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
prune: function prune (opts, cwd, cb, nextStep) {
|
moveApp: function finalizeApp (opts, tempPath, callback) {
|
||||||
if (opts.prune) {
|
var finalPath = generateFinalPath(opts)
|
||||||
child.exec('npm prune --production', { cwd: cwd }, function pruned (err) {
|
// Prefer ncp over mv (which seems to cause issues on Win8)
|
||||||
if (err) return cb(err)
|
series([
|
||||||
nextStep()
|
function (cb) {
|
||||||
})
|
mkdirp(finalPath, cb)
|
||||||
} else {
|
},
|
||||||
nextStep()
|
function (cb) {
|
||||||
}
|
ncp(tempPath, finalPath, cb)
|
||||||
|
}
|
||||||
|
], function (err) {
|
||||||
|
callback(err, finalPath)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
userIgnoreFilter: function userIgnoreFilter (opts, finalDir) {
|
normalizeExt: function normalizeExt (filename, targetExt, cb) {
|
||||||
return function filter (file) {
|
// Forces a filename to a given extension and fires the given callback with the normalized filename,
|
||||||
if (path.sep === '\\') {
|
// if it exists. Otherwise reports the error from the fs.stat call.
|
||||||
// convert slashes so unix-format ignores work
|
// (Used for resolving icon filenames, particularly during --all runs.)
|
||||||
file = file.replace(/\\/g, '/')
|
|
||||||
}
|
|
||||||
|
|
||||||
var ignore = opts.ignore || []
|
// This error path is used by win32.js if no icon is specified
|
||||||
if (!Array.isArray(ignore)) ignore = [ignore]
|
if (!filename) return cb(new Error('No filename specified to normalizeExt'))
|
||||||
if (typeof finalDir !== 'undefined') {
|
|
||||||
ignore = ignore.concat([finalDir])
|
var ext = path.extname(filename)
|
||||||
}
|
if (ext !== targetExt) {
|
||||||
for (var i = 0; i < ignore.length; i++) {
|
filename = filename.slice(0, filename.length - ext.length) + targetExt
|
||||||
if (file.match(ignore[i])) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs.stat(filename, function (err) {
|
||||||
|
cb(err, err ? null : filename)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
190
index.js
190
index.js
@ -1,59 +1,169 @@
|
|||||||
var path = require('path')
|
var path = require('path')
|
||||||
|
var fs = require('fs')
|
||||||
var os = require('os')
|
var os = require('os')
|
||||||
|
|
||||||
var download = require('electron-download')
|
var download = require('electron-download')
|
||||||
var extract = require('extract-zip')
|
var extract = require('extract-zip')
|
||||||
var mkdirp = require('mkdirp')
|
var mkdirp = require('mkdirp')
|
||||||
var rimraf = require('rimraf')
|
var rimraf = require('rimraf')
|
||||||
|
var series = require('run-series')
|
||||||
|
var common = require('./common')
|
||||||
|
|
||||||
var mac = require('./mac.js')
|
var supportedArchs = {
|
||||||
var linux = require('./linux.js')
|
ia32: 1,
|
||||||
var win32 = require('./win32.js')
|
x64: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var supportedPlatforms = {
|
||||||
|
// Maps to module ID for each platform (lazy-required if used)
|
||||||
|
darwin: './mac',
|
||||||
|
linux: './linux',
|
||||||
|
win32: './win32'
|
||||||
|
}
|
||||||
|
|
||||||
|
var tempBase = path.join(os.tmpdir(), 'electron-packager')
|
||||||
|
|
||||||
|
function testSymlink (cb) {
|
||||||
|
var testPath = path.join(tempBase, 'symlink-test')
|
||||||
|
var testFile = path.join(testPath, 'test')
|
||||||
|
var testLink = path.join(testPath, 'testlink')
|
||||||
|
series([
|
||||||
|
function (cb) {
|
||||||
|
mkdirp(testPath, cb)
|
||||||
|
},
|
||||||
|
function (cb) {
|
||||||
|
fs.writeFile(testFile, '', cb)
|
||||||
|
},
|
||||||
|
function (cb) {
|
||||||
|
fs.symlink(testFile, testLink, cb)
|
||||||
|
}
|
||||||
|
], function (err) {
|
||||||
|
var result = !err
|
||||||
|
rimraf(testPath, function () {
|
||||||
|
cb(result) // ignore errors on cleanup
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateList (list, supported, name) {
|
||||||
|
// Validates list of architectures or platforms.
|
||||||
|
// Returns a normalized array if successful, or an error message string otherwise.
|
||||||
|
|
||||||
|
if (!list) return 'Must specify ' + name
|
||||||
|
if (list === 'all') return Object.keys(supported)
|
||||||
|
|
||||||
|
if (!Array.isArray(list)) list = list.split(',')
|
||||||
|
for (var i = list.length; i--;) {
|
||||||
|
if (!supported[list[i]]) {
|
||||||
|
return 'Unsupported ' + name + ' ' + list[i] + '; must be one of: ' + Object.keys(supported).join(', ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSeries (opts, archs, platforms) {
|
||||||
|
var combinations = []
|
||||||
|
archs.forEach(function (arch) {
|
||||||
|
platforms.forEach(function (platform) {
|
||||||
|
// Electron does not have 32-bit releases for Mac OS X, so skip that combination
|
||||||
|
if (platform === 'darwin' && arch === 'ia32') return
|
||||||
|
combinations.push({
|
||||||
|
platform: platform,
|
||||||
|
arch: arch,
|
||||||
|
version: opts.version
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return [
|
||||||
|
function (cb) {
|
||||||
|
rimraf(tempBase, cb)
|
||||||
|
}
|
||||||
|
].concat(combinations.map(function (combination) {
|
||||||
|
var arch = combination.arch
|
||||||
|
var platform = combination.platform
|
||||||
|
var version = combination.version
|
||||||
|
|
||||||
|
return function (callback) {
|
||||||
|
download(combination, function (err, zipPath) {
|
||||||
|
if (err) return callback(err)
|
||||||
|
|
||||||
|
var tmpDir = path.join(tempBase, platform + '-' + arch + '-template')
|
||||||
|
|
||||||
|
var operations = [
|
||||||
|
function (cb) {
|
||||||
|
mkdirp(tmpDir, cb)
|
||||||
|
},
|
||||||
|
function (cb) {
|
||||||
|
extract(zipPath, {dir: tmpDir}, cb)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
function createApp (comboOpts) {
|
||||||
|
console.error('Packaging app for platform', platform + ' ' + arch, 'using electron v' + version)
|
||||||
|
series(operations, function () {
|
||||||
|
require(supportedPlatforms[platform]).createApp(comboOpts, tmpDir, callback)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkOverwrite () {
|
||||||
|
// Create delegated options object with specific platform and arch, for output directory naming
|
||||||
|
var comboOpts = Object.create(opts)
|
||||||
|
comboOpts.arch = arch
|
||||||
|
comboOpts.platform = platform
|
||||||
|
|
||||||
|
var finalPath = common.generateFinalPath(comboOpts)
|
||||||
|
fs.exists(finalPath, function (exists) {
|
||||||
|
if (exists) {
|
||||||
|
if (opts.overwrite) {
|
||||||
|
rimraf(finalPath, function () {
|
||||||
|
createApp(comboOpts)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.error('Skipping ' + platform + ' ' + arch +
|
||||||
|
' (output dir already exists, use --overwrite to force)')
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
createApp(comboOpts)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (combination.platform === 'darwin') {
|
||||||
|
testSymlink(function (result) {
|
||||||
|
if (result) return checkOverwrite()
|
||||||
|
|
||||||
|
console.error('Cannot create symlinks; skipping darwin platform')
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
checkOverwrite()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = function packager (opts, cb) {
|
module.exports = function packager (opts, cb) {
|
||||||
var platformPackager
|
var archs = validateList(opts.all ? 'all' : opts.arch, supportedArchs, 'arch')
|
||||||
var platform = opts.platform
|
var platforms = validateList(opts.all ? 'all' : opts.platform, supportedPlatforms, 'platform')
|
||||||
var arch = opts.arch
|
if (!opts.version) return cb(new Error('Must specify version'))
|
||||||
var version = opts.version
|
if (!Array.isArray(archs)) return cb(new Error(archs))
|
||||||
|
if (!Array.isArray(platforms)) return cb(new Error(platforms))
|
||||||
if (!platform || !arch || !version) cb(new Error('Must specify platform, arch and version'))
|
|
||||||
|
|
||||||
switch (arch) {
|
|
||||||
case 'ia32': break
|
|
||||||
case 'x64': break
|
|
||||||
default: return cb(new Error('Unsupported arch. Must be either ia32 or x64'))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (platform) {
|
|
||||||
case 'darwin': platformPackager = mac; break
|
|
||||||
case 'linux': platformPackager = linux; break
|
|
||||||
case 'win32': platformPackager = win32; break
|
|
||||||
default: return cb(new Error('Unsupported platform. Must be either darwin, linux, or win32'))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore this and related modules by default
|
// Ignore this and related modules by default
|
||||||
var defaultIgnores = ['/node_modules/electron-prebuilt($|/)', '/node_modules/electron-packager($|/)', '/\.git($|/)']
|
var defaultIgnores = ['/node_modules/electron-prebuilt($|/)', '/node_modules/electron-packager($|/)', '/\.git($|/)']
|
||||||
if (opts.ignore && !Array.isArray(opts.ignore)) opts.ignore = [opts.ignore]
|
if (opts.ignore && !Array.isArray(opts.ignore)) opts.ignore = [opts.ignore]
|
||||||
opts.ignore = (opts.ignore) ? opts.ignore.concat(defaultIgnores) : defaultIgnores
|
opts.ignore = (opts.ignore) ? opts.ignore.concat(defaultIgnores) : defaultIgnores
|
||||||
|
|
||||||
download({
|
series(createSeries(opts, archs, platforms), function (err, appPaths) {
|
||||||
platform: platform,
|
|
||||||
arch: arch,
|
|
||||||
version: version
|
|
||||||
}, function (err, zipPath) {
|
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
console.error('Packaging app for platform', platform + ' ' + arch, 'using electron v' + version)
|
|
||||||
// extract zip into tmp so that packager can use it as a template
|
cb(null, appPaths.filter(function (appPath) {
|
||||||
var tmpDir = path.join(os.tmpdir(), 'electron-packager-' + platform + '-template')
|
// Remove falsy entries (e.g. skipped platforms)
|
||||||
rimraf(tmpDir, function (err) {
|
return appPath
|
||||||
if (err) {} // ignore err
|
}))
|
||||||
mkdirp(tmpDir, function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
extract(zipPath, {dir: tmpDir}, function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
platformPackager.createApp(opts, tmpDir, cb)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
71
linux.js
71
linux.js
@ -1,70 +1,15 @@
|
|||||||
var path = require('path')
|
var path = require('path')
|
||||||
var fs = require('fs')
|
var mv = require('mv')
|
||||||
var mkdirp = require('mkdirp')
|
|
||||||
var ncp = require('ncp').ncp
|
|
||||||
var rimraf = require('rimraf')
|
|
||||||
var common = require('./common')
|
var common = require('./common')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createApp: function createApp (opts, templateApp, cb) {
|
createApp: function createApp (opts, templatePath, callback) {
|
||||||
var finalDir = path.join(opts.out || process.cwd(), opts.name + '-linux')
|
common.initializeApp(opts, templatePath, path.join('resources', 'app'), function buildLinuxApp (err, tempPath) {
|
||||||
var userAppDir = path.join(finalDir, 'resources', 'default_app')
|
if (err) return callback(err)
|
||||||
var originalBinary = path.join(finalDir, 'electron')
|
mv(path.join(tempPath, 'electron'), path.join(tempPath, opts.name), function (err) {
|
||||||
var finalBinary = path.join(finalDir, opts.name)
|
if (err) return callback(err)
|
||||||
|
common.moveApp(opts, tempPath, callback)
|
||||||
function copyApp () {
|
|
||||||
var createApp = function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
mkdirp(finalDir, function AppFolderCreated (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
copyAppTemplate()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (opts.overwrite) {
|
|
||||||
fs.exists(finalDir, function (exists) {
|
|
||||||
if (exists) {
|
|
||||||
console.log('Overwriting existing ' + finalDir + ' ...')
|
|
||||||
rimraf(finalDir, createApp)
|
|
||||||
} else {
|
|
||||||
createApp()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
createApp()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyAppTemplate () {
|
|
||||||
ncp(templateApp, finalDir, {filter: appFilter}, function AppCreated (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
copyUserApp()
|
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
|
|
||||||
function copyUserApp () {
|
|
||||||
ncp(opts.dir, userAppDir, {filter: common.userIgnoreFilter(opts, finalDir), dereference: true}, function copied (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
common.prune(opts, userAppDir, cb, renameElectronBinary)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function renameElectronBinary () {
|
|
||||||
fs.rename(originalBinary, finalBinary, function electronRenamed (err) {
|
|
||||||
var asarDir
|
|
||||||
if (err) return cb(err)
|
|
||||||
if (opts.asar) {
|
|
||||||
asarDir = path.join(finalDir, 'resources')
|
|
||||||
common.asarApp(asarDir, cb)
|
|
||||||
} else {
|
|
||||||
cb(null, finalBinary)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function appFilter (file) {
|
|
||||||
return file.match(/default_app/) === null
|
|
||||||
}
|
|
||||||
|
|
||||||
copyApp()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
213
mac.js
213
mac.js
@ -1,160 +1,87 @@
|
|||||||
var os = require('os')
|
|
||||||
var path = require('path')
|
var path = require('path')
|
||||||
var fs = require('fs')
|
var fs = require('fs')
|
||||||
var child = require('child_process')
|
var child = require('child_process')
|
||||||
|
|
||||||
var plist = require('plist')
|
var plist = require('plist')
|
||||||
var mkdirp = require('mkdirp')
|
|
||||||
var rimraf = require('rimraf')
|
|
||||||
var mv = require('mv')
|
var mv = require('mv')
|
||||||
var ncp = require('ncp').ncp
|
var ncp = require('ncp').ncp
|
||||||
|
var series = require('run-series')
|
||||||
var common = require('./common')
|
var common = require('./common')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createApp: function createApp (opts, electronPath, cb) {
|
createApp: function createApp (opts, templatePath, callback) {
|
||||||
var electronApp = path.join(electronPath, 'Electron.app')
|
var appRelativePath = path.join('Electron.app', 'Contents', 'Resources', 'app')
|
||||||
var tmpDir = path.join(os.tmpdir(), 'electron-packager-mac')
|
common.initializeApp(opts, templatePath, appRelativePath, function buildMacApp (err, tempPath) {
|
||||||
|
if (err) return callback(err)
|
||||||
|
|
||||||
var newApp = path.join(tmpDir, opts.name + '.app')
|
var contentsPath = path.join(tempPath, 'Electron.app', 'Contents')
|
||||||
|
var helperPath = path.join(contentsPath, 'Frameworks', 'Electron Helper.app')
|
||||||
|
var appPlistFilename = path.join(contentsPath, 'Info.plist')
|
||||||
|
var helperPlistFilename = path.join(helperPath, 'Contents', 'Info.plist')
|
||||||
|
var appPlist = plist.parse(fs.readFileSync(appPlistFilename).toString())
|
||||||
|
var helperPlist = plist.parse(fs.readFileSync(helperPlistFilename).toString())
|
||||||
|
|
||||||
// reset build folders + copy template app
|
// Update plist files
|
||||||
rimraf(tmpDir, function rmrfd () {
|
var defaultBundleName = 'com.electron.' + opts.name.toLowerCase().replace(/ /g, '_')
|
||||||
// ignore errors
|
var appVersion = opts['app-version']
|
||||||
mkdirp(newApp, function mkdirpd () {
|
|
||||||
// ignore errors
|
appPlist.CFBundleDisplayName = opts.name
|
||||||
// copy .app folder and use as template (this is exactly what Atom editor does)
|
appPlist.CFBundleIdentifier = opts['app-bundle-id'] || defaultBundleName
|
||||||
ncp(electronApp, newApp, function copied (err) {
|
appPlist.CFBundleName = opts.name
|
||||||
if (err) return cb(err)
|
helperPlist.CFBundleIdentifier = opts['helper-bundle-id'] || defaultBundleName + '.helper'
|
||||||
buildMacApp(opts, cb, newApp)
|
helperPlist.CFBundleName = opts.name
|
||||||
|
|
||||||
|
if (appVersion) {
|
||||||
|
appPlist.CFBundleVersion = appVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.protocols) {
|
||||||
|
helperPlist.CFBundleURLTypes = appPlist.CFBundleURLTypes = opts.protocols.map(function (protocol) {
|
||||||
|
return {
|
||||||
|
CFBundleURLName: protocol.name,
|
||||||
|
CFBundleURLSchemes: [].concat(protocol.schemes)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(appPlistFilename, plist.build(appPlist))
|
||||||
|
fs.writeFileSync(helperPlistFilename, plist.build(helperPlist))
|
||||||
|
|
||||||
|
var operations = []
|
||||||
|
|
||||||
|
if (opts.icon) {
|
||||||
|
operations.push(function (cb) {
|
||||||
|
common.normalizeExt(opts.icon, '.icns', function (err, icon) {
|
||||||
|
if (err) {
|
||||||
|
// Ignore error if icon doesn't exist, in case it's only available for other OS
|
||||||
|
cb(null)
|
||||||
|
} else {
|
||||||
|
ncp(icon, path.join(contentsPath, 'Resources', 'atom.icns'), cb)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move Helper binary, then Helper.app, then top-level .app
|
||||||
|
var finalAppPath = path.join(tempPath, opts.name + '.app')
|
||||||
|
operations.push(function (cb) {
|
||||||
|
var helperBinaryPath = path.join(helperPath, 'Contents', 'MacOS')
|
||||||
|
mv(path.join(helperBinaryPath, 'Electron Helper'), path.join(helperBinaryPath, opts.name + ' Helper'), cb)
|
||||||
|
}, function (cb) {
|
||||||
|
mv(helperPath, path.join(path.dirname(helperPath), opts.name + ' Helper.app'), cb)
|
||||||
|
}, function (cb) {
|
||||||
|
mv(path.dirname(contentsPath), finalAppPath, cb)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (opts.sign) {
|
||||||
|
operations.push(function (cb) {
|
||||||
|
child.exec('codesign --deep --force --sign "' + opts.sign + '" ' + finalAppPath, cb)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
series(operations, function () {
|
||||||
|
common.moveApp(opts, tempPath, callback)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMacApp (opts, cb, newApp) {
|
|
||||||
var paths = {
|
|
||||||
info1: path.join(newApp, 'Contents', 'Info.plist'),
|
|
||||||
info2: path.join(newApp, 'Contents', 'Frameworks', 'Electron Helper.app', 'Contents', 'Info.plist'),
|
|
||||||
app: path.join(newApp, 'Contents', 'Resources', 'app'),
|
|
||||||
helper: path.join(newApp, 'Contents', 'Frameworks', 'Electron Helper.app')
|
|
||||||
}
|
|
||||||
|
|
||||||
// update plist files
|
|
||||||
var pl1 = plist.parse(fs.readFileSync(paths.info1).toString())
|
|
||||||
var pl2 = plist.parse(fs.readFileSync(paths.info2).toString())
|
|
||||||
|
|
||||||
var bundleId = opts['app-bundle-id'] || 'com.electron.' + opts.name.toLowerCase()
|
|
||||||
var bundleHelperId = opts['helper-bundle-id'] || 'com.electron.' + opts.name.toLowerCase() + '.helper'
|
|
||||||
var appVersion = opts['app-version']
|
|
||||||
|
|
||||||
pl1.CFBundleDisplayName = opts.name
|
|
||||||
pl1.CFBundleIdentifier = bundleId
|
|
||||||
pl1.CFBundleName = opts.name
|
|
||||||
pl2.CFBundleIdentifier = bundleHelperId
|
|
||||||
pl2.CFBundleName = opts.name
|
|
||||||
|
|
||||||
if (appVersion) {
|
|
||||||
pl1.CFBundleVersion = appVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.protocols) {
|
|
||||||
pl2.CFBundleURLTypes = pl1.CFBundleURLTypes = opts.protocols.map(function (protocol) {
|
|
||||||
return {
|
|
||||||
CFBundleURLName: protocol.name,
|
|
||||||
CFBundleURLSchemes: [].concat(protocol.schemes)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(paths.info1, plist.build(pl1))
|
|
||||||
fs.writeFileSync(paths.info2, plist.build(pl2))
|
|
||||||
|
|
||||||
// copy users app into .app
|
|
||||||
ncp(opts.dir, paths.app, {filter: common.userIgnoreFilter(opts), dereference: true}, function copied (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
|
|
||||||
function moveHelper () {
|
|
||||||
// Move helper binary before moving the parent helper app directory itself
|
|
||||||
var helperDestination = path.join(path.dirname(paths.helper), opts.name + ' Helper.app')
|
|
||||||
var helperBinary = path.join(paths.helper, 'Contents', 'MacOS', 'Electron Helper')
|
|
||||||
var helperBinaryDestination = path.join(path.dirname(helperBinary), opts.name + ' Helper')
|
|
||||||
|
|
||||||
fs.rename(helperBinary, helperBinaryDestination, function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
fs.rename(paths.helper, helperDestination, function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
moveApp()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveApp () {
|
|
||||||
// finally, move app into cwd
|
|
||||||
var outdir = opts.out || process.cwd()
|
|
||||||
var finalPath = path.join(outdir, opts.name + '.app')
|
|
||||||
|
|
||||||
mkdirp(outdir, function mkoutdirp () {
|
|
||||||
if (err) return cb(err)
|
|
||||||
if (opts.overwrite) {
|
|
||||||
fs.exists(finalPath, function (exists) {
|
|
||||||
if (exists) {
|
|
||||||
console.log('Overwriting existing ' + finalPath + ' ...')
|
|
||||||
rimraf(finalPath, deploy)
|
|
||||||
} else {
|
|
||||||
deploy()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
deploy()
|
|
||||||
}
|
|
||||||
|
|
||||||
function deploy (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
mv(newApp, finalPath, function moved (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
if (opts.asar) {
|
|
||||||
var finalPath = path.join(opts.out || process.cwd(), opts.name + '.app', 'Contents', 'Resources')
|
|
||||||
common.asarApp(finalPath, function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
updateMacIcon(function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
codesign()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
updateMacIcon(function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
codesign()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateMacIcon (cb) {
|
|
||||||
var finalPath = path.join(opts.out || process.cwd(), opts.name + '.app')
|
|
||||||
|
|
||||||
if (!opts.icon) {
|
|
||||||
return cb(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
ncp(opts.icon, path.join(finalPath, 'Contents', 'Resources', 'atom.icns'), function copied (err) {
|
|
||||||
cb(err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function codesign () {
|
|
||||||
var appPath = path.join(opts.out || process.cwd(), opts.name + '.app')
|
|
||||||
|
|
||||||
if (!opts.sign) return cb(null, appPath)
|
|
||||||
|
|
||||||
child.exec('codesign --deep --force --sign "' + opts.sign + '" ' + appPath, function (err, stdout, stderr) {
|
|
||||||
cb(err, appPath)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
common.prune(opts, paths.app, cb, moveHelper)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"plist": "^1.1.0",
|
"plist": "^1.1.0",
|
||||||
"rcedit": "^0.3.0",
|
"rcedit": "^0.3.0",
|
||||||
"rimraf": "^2.3.2"
|
"rimraf": "^2.3.2",
|
||||||
|
"run-series": "^1.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"standard": "^3.3.2",
|
"standard": "^3.3.2",
|
||||||
|
33
readme.md
33
readme.md
@ -25,14 +25,15 @@ Usage: electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arc
|
|||||||
|
|
||||||
Required options
|
Required options
|
||||||
|
|
||||||
platform linux, win32, darwin
|
platform all, or one or more of: linux, win32, darwin (comma-delimited if multiple)
|
||||||
arch ia32, x64
|
arch all, ia32, x64
|
||||||
version see https://github.com/atom/electron/releases
|
version see https://github.com/atom/electron/releases
|
||||||
|
|
||||||
Example electron-packager ./ FooBar --platform=darwin --arch=x64 --version=0.25.1
|
Example electron-packager ./ FooBar --platform=darwin --arch=x64 --version=0.25.1
|
||||||
|
|
||||||
Optional options
|
Optional options
|
||||||
|
|
||||||
|
all equivalent to --platform=all --arch=all
|
||||||
out the dir to put the app into at the end. defaults to current working dir
|
out the dir to put the app into at the end. defaults to current working dir
|
||||||
icon the icon file to use as the icon for the app
|
icon the icon file to use as the icon for the app
|
||||||
app-bundle-id bundle identifier to use in the app plist
|
app-bundle-id bundle identifier to use in the app plist
|
||||||
@ -40,6 +41,7 @@ app-version version to set for the app
|
|||||||
helper-bundle-id bundle identifier to use in the app helper plist
|
helper-bundle-id bundle identifier to use in the app helper plist
|
||||||
ignore do not copy files into App whose filenames regex .match this string
|
ignore do not copy files into App whose filenames regex .match this string
|
||||||
prune runs `npm prune --production` on the app
|
prune runs `npm prune --production` on the app
|
||||||
|
overwrite if output directory for a platform already exists, replaces it rather than skipping it
|
||||||
asar packages the source code within your app into an archive
|
asar packages the source code within your app into an archive
|
||||||
sign should contain the identity to be used when running `codesign` (OS X only)
|
sign should contain the identity to be used when running `codesign` (OS X only)
|
||||||
version-string should contain a hash of the application metadata to be embedded into the executable (Windows only). Keys supported
|
version-string should contain a hash of the application metadata to be embedded into the executable (Windows only). Keys supported
|
||||||
@ -58,7 +60,7 @@ version-string should contain a hash of the application metadata to be embed
|
|||||||
This will:
|
This will:
|
||||||
|
|
||||||
- Find or download the correct release of Electron
|
- Find or download the correct release of Electron
|
||||||
- Use that version of electron to create a app in `<out>/<appname>-<platform>`
|
- Use that version of electron to create a app in `<out>/<appname>-<platform>-<arch>`
|
||||||
|
|
||||||
You should be able to launch the app on the platform you built for. If not, check your settings and try again.
|
You should be able to launch the app on the platform you built for. If not, check your settings and try again.
|
||||||
|
|
||||||
@ -80,15 +82,21 @@ The source directory.
|
|||||||
The application name.
|
The application name.
|
||||||
|
|
||||||
`platform` - *String*
|
`platform` - *String*
|
||||||
Allowed values: *linux, win32, darwin*
|
Allowed values: *linux, win32, darwin, all*
|
||||||
|
Not required if `all` is used.
|
||||||
|
Arbitrary combinations of individual platforms are also supported via a comma-delimited string or array of strings.
|
||||||
|
|
||||||
`arch` - *String*
|
`arch` - *String*
|
||||||
Allowed values: *ia32, x64*
|
Allowed values: *ia32, x64, all*
|
||||||
|
Not required if `all` is used.
|
||||||
|
|
||||||
`version` - *String*
|
`version` - *String*
|
||||||
Electron version (without the 'v'). See https://github.com/atom/electron/releases
|
Electron version (without the 'v'). See https://github.com/atom/electron/releases
|
||||||
|
|
||||||
**Optional**
|
**Optional**
|
||||||
|
`all` - *Boolean*
|
||||||
|
Shortcut for `--arch=all --platform=all`
|
||||||
|
|
||||||
`out` - *String*
|
`out` - *String*
|
||||||
|
|
||||||
`icon` - *String*
|
`icon` - *String*
|
||||||
@ -103,10 +111,23 @@ Electron version (without the 'v'). See https://github.com/atom/electron/release
|
|||||||
|
|
||||||
`prune` - *Boolean*
|
`prune` - *Boolean*
|
||||||
|
|
||||||
|
`overwrite` - *Boolean*
|
||||||
|
|
||||||
`asar` - *Boolean*
|
`asar` - *Boolean*
|
||||||
|
|
||||||
`sign` - *String*
|
`sign` - *String*
|
||||||
|
|
||||||
|
`version-string` - *Object*
|
||||||
|
Object hash of application metadata to embed into the executable (Windows only):
|
||||||
|
* `CompanyName`
|
||||||
|
* `LegalCopyright`
|
||||||
|
* `FileDescription`
|
||||||
|
* `OriginalFilename`
|
||||||
|
* `FileVersion`
|
||||||
|
* `ProductVersion`
|
||||||
|
* `ProductName`
|
||||||
|
* `InternalName`
|
||||||
|
|
||||||
##### callback
|
##### callback
|
||||||
|
|
||||||
`err` - *Error*
|
`err` - *Error*
|
||||||
@ -121,4 +142,4 @@ If you run this on windows and you want to set the icon for your app using the `
|
|||||||
|
|
||||||
### related
|
### related
|
||||||
|
|
||||||
- [grunt-electron](https://github.com/sindresorhus/grunt-electron) - grunt plugin for electron-packager
|
- [grunt-electron](https://github.com/sindresorhus/grunt-electron) - grunt plugin for electron-packager
|
15
usage.txt
15
usage.txt
@ -1,15 +1,16 @@
|
|||||||
Usage: electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> --version=<version>
|
Usage: electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> --version=<version>
|
||||||
|
|
||||||
Required options
|
Required options
|
||||||
|
|
||||||
platform linux, win32, darwin
|
platform all, or one or more of: linux, win32, darwin (comma-delimited if multiple)
|
||||||
arch ia32, x64
|
arch all, ia32, x64
|
||||||
version see https://github.com/atom/electron/releases
|
version see https://github.com/atom/electron/releases
|
||||||
|
|
||||||
Example electron-packager ./ FooBar --platform=darwin --arch=x64 --version=0.25.1
|
Example electron-packager ./ FooBar --platform=darwin --arch=x64 --version=0.28.2
|
||||||
|
|
||||||
Optional options
|
Optional options
|
||||||
|
|
||||||
|
all equivalent to --platform=all --arch=all
|
||||||
out the dir to put the app into at the end. defaults to current working dir
|
out the dir to put the app into at the end. defaults to current working dir
|
||||||
icon the icon file to use as the icon for the app
|
icon the icon file to use as the icon for the app
|
||||||
app-bundle-id bundle identifier to use in the app plist
|
app-bundle-id bundle identifier to use in the app plist
|
||||||
@ -17,4 +18,6 @@ app-version version to set for the app
|
|||||||
helper-bundle-id bundle identifier to use in the app helper plist
|
helper-bundle-id bundle identifier to use in the app helper plist
|
||||||
ignore do not copy files into App whose filenames regex .match this string
|
ignore do not copy files into App whose filenames regex .match this string
|
||||||
prune runs `npm prune --production` on the app
|
prune runs `npm prune --production` on the app
|
||||||
asar packages the source code within your app into an archive
|
overwrite if output directory for a platform already exists, replaces it rather than skipping it
|
||||||
|
asar packages the source code within your app into an archive
|
||||||
|
sign should contain the identity to be used when running `codesign` (OS X only)
|
104
win32.js
104
win32.js
@ -1,92 +1,40 @@
|
|||||||
var os = require('os')
|
|
||||||
var path = require('path')
|
var path = require('path')
|
||||||
|
|
||||||
var mkdirp = require('mkdirp')
|
|
||||||
var rimraf = require('rimraf')
|
|
||||||
var ncp = require('ncp').ncp
|
|
||||||
var mv = require('mv')
|
var mv = require('mv')
|
||||||
var rcedit = require('rcedit')
|
var series = require('run-series')
|
||||||
var common = require('./common')
|
var common = require('./common')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createApp: function createApp (opts, electronApp, cb) {
|
createApp: function createApp (opts, templatePath, callback) {
|
||||||
var tmpDir = path.join(os.tmpdir(), 'electron-packager-windows')
|
common.initializeApp(opts, templatePath, path.join('resources', 'app'), function buildWinApp (err, tempPath) {
|
||||||
|
if (err) return callback(err)
|
||||||
|
|
||||||
var newApp = path.join(tmpDir, opts.name + '-win32')
|
var newExePath = path.join(tempPath, opts.name + '.exe')
|
||||||
// reset build folders + copy template app
|
var operations = [
|
||||||
rimraf(tmpDir, function rmrfd () {
|
function (cb) {
|
||||||
// ignore errors
|
mv(path.join(tempPath, 'electron.exe'), newExePath, cb)
|
||||||
mkdirp(newApp, function mkdirpd () {
|
}
|
||||||
// ignore errors
|
]
|
||||||
// copy app folder and use as template (this is exactly what Atom editor does)
|
|
||||||
ncp(electronApp, newApp, function copied (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
// rename electron.exe
|
|
||||||
mv(path.join(newApp, 'electron.exe'), path.join(newApp, opts.name + '.exe'), function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
|
|
||||||
buildWinApp(opts, cb, newApp)
|
if (opts.icon || opts['version-string']) {
|
||||||
|
operations.push(function (cb) {
|
||||||
|
common.normalizeExt(opts.icon, '.ico', function (err, icon) {
|
||||||
|
var rcOpts = {}
|
||||||
|
if (opts['version-string']) rcOpts['version-string'] = opts['version-string']
|
||||||
|
|
||||||
|
// Icon might be omitted or only exist in one OS's format, so skip it if normalizeExt reports an error
|
||||||
|
if (!err) {
|
||||||
|
rcOpts.icon = icon
|
||||||
|
}
|
||||||
|
|
||||||
|
require('rcedit')(newExePath, rcOpts, cb)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
series(operations, function () {
|
||||||
|
common.moveApp(opts, tempPath, callback)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function copy (from, to, cb) {
|
|
||||||
rimraf(to, function () {
|
|
||||||
mkdirp(to, function () {
|
|
||||||
ncp(from, to, function (err) {
|
|
||||||
if (err) { return cb(err) }
|
|
||||||
cb()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildWinApp (opts, cb, newApp) {
|
|
||||||
var paths = {
|
|
||||||
app: path.join(newApp, 'resources', 'app')
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy users app into destination path
|
|
||||||
ncp(opts.dir, paths.app, {filter: common.userIgnoreFilter(opts), dereference: true}, function copied (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
|
|
||||||
function moveApp () {
|
|
||||||
// finally, move app into cwd
|
|
||||||
var finalPath = path.join(opts.out || process.cwd(), opts.name + '-win32')
|
|
||||||
copy(newApp, finalPath, function moved (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
if (opts.asar) {
|
|
||||||
var finalPath = path.join(opts.out || process.cwd(), opts.name + '-win32', 'resources')
|
|
||||||
common.asarApp(finalPath, function (err) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
updateResourceData()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
updateResourceData()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateResourceData () {
|
|
||||||
var finalPath = path.join(opts.out || process.cwd(), opts.name + '-win32')
|
|
||||||
|
|
||||||
if (!opts.icon && !opts['version-string']) {
|
|
||||||
return cb(null, finalPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
var exePath = path.join(opts.out || process.cwd(), opts.name + '-win32', opts.name + '.exe')
|
|
||||||
var rcOptions = {
|
|
||||||
icon: opts.icon,
|
|
||||||
'version-string': opts['version-string']
|
|
||||||
}
|
|
||||||
rcedit(exePath, rcOptions, function (err) {
|
|
||||||
cb(err, finalPath)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
common.prune(opts, paths.app, cb, moveApp)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user