exe: fixes #122, implement base nexe package field

This commit is contained in:
Jared Allard
2015-06-26 18:27:26 -07:00
parent 882c838cb5
commit d4be3712cd
9 changed files with 297 additions and 49 deletions
+4 -1
View File
@@ -1,4 +1,7 @@
node_modules
.DS_Store
*.nex
npm-debug.log
src
nexe.exe
nexe
npm-debug.log
+23 -5
View File
@@ -1,7 +1,7 @@
### Nexe
[![Join the chat at https://gitter.im/crcn/nexe](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/crcn/nexe?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Dependency Status](https://david-dm.org/crcn/nexe.svg)](https://david-dm.org/crcn/nexe)
[![Stories in Ready](https://badge.waffle.io/crcn/nexe.svg?label=ready&title=Ready)](http://waffle.io/crcn/nexe)
[![Stories in Ready](https://badge.waffle.io/crcn/nexe.svg?label=ready&title=Ready)](http://waffle.io/crcn/nexe)
Nexe is a command-line utility that compiles your Node.js application into a single executable file.
@@ -116,9 +116,9 @@ Usage: nexe -i [sources] -o [binary] [options]
Options:
-i, --input The entry javascript files [default: cwd]
-o, --output The output binary [default: cwd/release/app.nex]
-o, --output The output binary [default: out.nex]
-r, --runtime The node.js runtime to use [default: "latest"]
-t, --temp The path to store node.js sources [default: cwd/tmp/nexe]
-t, --temp The path to store node.js sources [default: ./tmp/nexe]
-f, --flags Don't parse node and v8 flags, pass through app flags [default: false]
-v, --version Display version number
-p, --python Set path of python to use. [default: "python"]
@@ -136,8 +136,8 @@ var nexe = require('nexe');
nexe.compile({
input: 'input.js',
output: 'path/to/bin',
nodeVersion: '0.12.0',
nodeTempDir: __dirname,
nodeVersion: '0.12.5',
nodeTempDir: 'src',
python: 'path/to/python',
resourceFiles: [ 'path/to/a/file' ],
flags: true,
@@ -148,6 +148,24 @@ nexe.compile({
```
### package.json inclusion
As of 0.4.0 you can now embed nexe options into package.json. Note that this Format
is still in works, so it is likely to change.
```
"nexe": {
"input": "./bin/nexe",
"output": "nexe^$",
"temp": "src",
"runtime": {
"framework": "iojs",
"version": "2.3.1",
"ignoreFlags": true
}
}
```
## Maintainers
* __Jared Allard__ ([@jaredallard](https://github.com/jaredallard)) <[jaredallard@outlook.com](mailto:jaredallard@outlook.com)> (Active)
+35 -17
View File
@@ -1,8 +1,10 @@
#!/usr/bin/env node
var path = require('path');
var cli = require('yargs').
var path = require('path'),
fs = require('fs'),
nexe = require('../lib'),
_log = require("../lib/log"),
cli = require('yargs').
usage('Usage: $0 -i [sources] -o [binary]').
options('i', {
demand: true,
@@ -14,7 +16,7 @@ options('o', {
demand: true,
alias: 'output',
desc: 'The output binary',
default: "..."+(process.cwd() + '/release/' + path.basename(process.cwd()) + '.nex').substr(-47) // cleaner for long directories
default: "out.nex"
}).
options('r', {
alias: 'runtime',
@@ -23,7 +25,7 @@ options('r', {
}).
options('t', {
alias: 'temp',
default: '/tmp/nexe',
default: './tmp/nexe',
description: 'The path to store node.js sources'
}).
options('f', {
@@ -47,7 +49,6 @@ options('F', {
});
var argv = cli.argv;
if(argv.h || argv.help) {
cli.showHelp();
process.exit();
@@ -57,19 +58,36 @@ if(argv.h || argv.help) {
process.exit();
}
function toAbsolute(pt) {
if(pt.substr(0, 1) == "/") return pt;
return path.join(process.cwd(), pt);
}
require('../lib').compile({
input : require.resolve(toAbsolute(argv.i)),
output : toAbsolute(argv.o),
flags : argv.f,
nodeVersion : argv.r,
python : argv.python,
nodeTempDir : toAbsolute(argv.t),
framework : argv.F }, function(error) {
if(error) console.log(error.message);
});
if(fs.lstatSync(argv.i).isDirectory()) {
_log("log", "checking package.json");
opts = nexe.package(path.join(argv.i, "package.json"), argv);
nexe.compile(opts, function(error) {
if(error) {
console.log(error.message);
}
});
} else {
/**
* Call the core
**/
nexe.compile({
input : require.resolve(toAbsolute(argv.i)),
output : toAbsolute(argv.o),
flags : argv.f,
nodeVersion : argv.r,
python : argv.python,
nodeTempDir : toAbsolute(argv.t),
framework : argv.F
},
function(error) {
if(error) {
console.log(error.message);
}
}
);
}
+23
View File
@@ -1,3 +1,26 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
var mdeps = require("module-deps"),
through = require("through"),
async = require("async"),
+23
View File
@@ -1,3 +1,26 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
var path = require("path"),
fs = require("fs");
+110 -15
View File
@@ -1,3 +1,26 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
var async = require("async"),
outcome = require("outcome"),
mkdirp = require("mkdirp"),
@@ -12,17 +35,25 @@ bundle = require("./bundle"),
embed = require("./embed"),
os = require("os"),
targz = require('tar.gz'),
_log = require("./log"),
_monkeypatch = require("./monkeypatch"),
spawn = child_process.spawn;
var _log = require("./log"),
_monkeypatch = require("./monkeypatch");
var isWin = /^win/.test(process.platform);
var isPy;
var framework;
var version;
option_list = [
"python",
"input",
"output",
"nodeTempDir",
"flags",
"framework",
"nodeVersion"
]
/**
* Compiliation process.
*/
@@ -36,6 +67,19 @@ exports.compile = function (options, complete) {
*check relevant options
*/
function checkOpts (next) {
/* failsafe */
if(options === undefined) {
_log("error", "no options given to .compile()");
process.exit()
}
option_list.forEach(function(v) {
if(options[v] === undefined) {
_log("error", "option "+v+" was empty")
process.exit();
}
});
/**
* Have we been given a custom flag for python executable?
*/
@@ -372,11 +416,8 @@ function _getNodeCompiler (nodeFileDir, complete, type) {
/* patch the file */
var py = fs.readFileSync(dir+"/"+v, {encoding: 'utf8'});
//py = py.replace(/^#!\/usr\/bin\/env python$/gm, "#!"+isPy); // may not be needed
//py = py.replace(/^#!\/usr\/bin\/python$/gm, "#!"+isPy); // may not be needed
py = py.replace(/([a-z]|\/)*python(\w|)/gm, isPy); // this is definently needed
//py = py.replace(/^PYTHON \?= python$/gm, "PYTHON ?= "+isPy); // may not be needed (pre-hook)
fs.writeFileSync(dir+"/"+v, py, {encoding: 'utf8'});
fs.writeFileSync(dir+"/"+v, py, {encoding: 'utf8'}); // write to file
delete pv;
} else if(stat.isDirectory()) {
@@ -428,11 +469,9 @@ function _getNodeCompiler (nodeFileDir, complete, type) {
function _monkeyPatchNodeConfig (compiler, complete) {
async.waterfall([
/**
* monkeypatch the gyp file to include the nexe.js and nexeres.js files
*/
function (next) {
_monkeyPatchGyp(compiler, next)
},
@@ -440,11 +479,9 @@ function _monkeyPatchNodeConfig (compiler, complete) {
/**
* monkeypatch main entry point
*/
function (next) {
_monkeyPatchMainJs(compiler, next)
}
], complete);
}
@@ -504,6 +541,7 @@ function _monkeyPatchChildProcess(compiler, complete) {
}
/**
* Patch node.cc to not check the internal arguments.
*/
function _monkeyPatchMainCc(compiler, complete) {
@@ -515,15 +553,23 @@ function _monkeyPatchMainCc(compiler, complete) {
},
function (content, next) {
var lines = content.split('\n');
/* These lines exist until v0.11.6 */
var startLine = lines.indexOf(' // TODO use parse opts');
/* pre 0.11.6 compat? */
var endLine = lines.indexOf(' option_end_index = i;');
lines[endLine] = ' option_end_index = 1;';
/**
* This is the new method of passing the args. Tested on node.js 0.12.5
* and iojs 2.3.1
**/
var startLine = lines.indexOf(' while (index < nargs && argv[index][0] == \'-\') {');
var endLine = lines.indexOf(' // Copy remaining arguments.');
endLine = endLine-1; // space, then it's at the }
for (var i = startLine; i < endLine; i++) {
lines[i] = '//' + lines[i];
}
lines[endLine] = ' option_end_index = 1;';
lines = lines.join('\n');
next(null, lines);
},
@@ -567,3 +613,52 @@ function _logProgress (req) {
return req;
}
/**
* Attempt to parse the package.json for nexe information.
*
* @param {string} path - path to package.json
* @param {object} options - fallback options
*
* @return {object} nexe.compile options object
**/
exports.package = function(path, options) {
var _package; // scope
// check if the file exists
if(fs.existsSync(path)===false) {
_log("warn", "no package.json found.");
} else {
_package = require(path);
}
// replace ^$ w/ os specific extension on output
if(isWin) {
_package.nexe.output = _package.nexe.output.replace(/\^\$/, '.exe') // exe
} else {
_package.nexe.output = _package.nexe.output.replace(/\^\$/, '') // none
}
// construct the object
var obj = {
input: (_package.nexe.input || options.i),
output: (_package.nexe.output || options.o),
flags: (_package.nexe.runtime.ignoreFlags || options.f),
resourceFiles: (_package.nexe.resourceFiles),
nodeVersion: (_package.nexe.runtime.version || options.r),
python: (_package.nexe.python || options.p),
nodeTempDir: (_package.nexe.temp || options.t),
framework: (_package.nexe.runtime.framework || options.f)
}
Object.keys(_package.nexe).forEach(function(v,i) {
if(v!=="runtime") {
_log("log", v+" => '"+_package.nexe[v]+"'");
}
});
Object.keys(_package.nexe.runtime).forEach(function(v,i) {
_log("log", "runtime."+v+" => '"+_package.nexe.runtime[v]+"'");
});
return obj;
}
+32 -4
View File
@@ -1,9 +1,34 @@
module.exports = _log;
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
/**
* logging aka stdout wrapper
*/
* standard output, takes 3 different types.
* log, error, and warn
*
* @param {any} arguments - Text to output.
* @return undefined
**/
function _log () {
var colors = require('colors');
@@ -26,3 +51,6 @@ function _log () {
console[level].apply(console, args);
}
// export the log function, for require()
module.exports = _log;
+36 -6
View File
@@ -1,14 +1,41 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
var async = require("async"),
fs = require("fs"),
_log = require("./log");
module.exports = _monkeypatch;
/**
* Monkey patch a file.
*
* @param {string} filePath - path to file.
* @param {function} monkeyPatched - function to process contents
* @param {function} processor - TODO: detail what this is
* @param {function} complete - callback
*
* @return undefined
*/
function _monkeypatch (filePath, monkeyPatched, processor, complete) {
async.waterfall([
@@ -30,4 +57,7 @@ function _monkeypatch (filePath, monkeyPatched, processor, complete) {
fs.writeFile(filePath, content, "utf8", next);
}
], complete);
}
}
// export the function for require()
module.exports = _monkeypatch;
+11 -1
View File
@@ -3,7 +3,7 @@
"name": "nexe",
"description": "Roll node.js applications into a single executable",
"license": "MIT",
"version": "0.3.9",
"version": "0.4.0",
"repository": {
"type": "git",
"url": "git://github.com/crcn/nexe.git"
@@ -26,6 +26,16 @@
"through": "^2.3.6",
"yargs": "^3.2.1"
},
"nexe": {
"input": "./bin/nexe",
"output": "nexe^$",
"temp": "src",
"runtime": {
"framework": "iojs",
"version": "1.0.1",
"ignoreFlags": true
}
},
"preferGlobal": "true",
"bin": {
"nexe": "./bin/nexe"