Modify readme, implement cross-plat --python <loc> closes #94

This commit is contained in:
RainbowDashDC
2015-02-14 01:50:32 -08:00
parent 3144ae8d6f
commit 86fa69920c
5 changed files with 128 additions and 56 deletions
+43 -36
View File
@@ -1,5 +1,3 @@
## This repository is not actively maintained.
### Nexe
Nexe is a command-line utility that compiles your Node.js application into a single executable file.
@@ -9,7 +7,7 @@ Nexe is a command-line utility that compiles your Node.js application into a sin
### Motivation
- Ability to run multiple applications with *different* node.js runtimes.
- Ability to run multiple applications with *different* node.js runtimes.
- Distributable binaries without needing node / npm.
- Starts faster.
- Lockdown specific application versions, and easily rollback.
@@ -20,69 +18,73 @@ Nexe is a command-line utility that compiles your Node.js application into a sin
- Linux / Mac / BSD / Windows
- Windows: Python 2.6 or 2.7 (in PATH), Visual Studio 2010 or 2012
##Caveats
## Caveats
### Doesn't support native modules
- Use the techniques below for working around dynamic require statments to exclude the module from the bundling, and deploy along side the executable in a node_module folder so your app can find it. Note: On windows you may need to have your app be named node.exe if .node file depends on node.
###Doesn't support dynamic require statments
- Use the techniques below for working around dynamic require statements to exclude the module from the bundling, and deploy along side the executable in a node_module folder so your app can find it. Note: On windows you may need to have your app be named node.exe if .node file depends on node.
### Doesn't support dynamic require statements
Such As:
```
```javascript
var x = require(someVar);
```
In this case nexe won't bundle the file
```
```javascript
var x;
if (someCheck) {
x = require("./ver1.js");
}
else {
} else {
x = require("./var2.js");
}
```
In this case nexe will bundle both files.
Workarounds:
1) for dyanmic requires that you want bundled add the following into your project
```
1) for dynamic requires that you want bundled add the following into your project
```javascript
var dummyToForceIncludeForBundle = false;
if (dummyToForceIncludeForBundle) {
require("./loadedDynamicallyLater.js");
...
// ...
}
```
this will trick the bundler into including them.
2) for dynamic files getting included that you don't want to be
```
```javascript
var moduleName = "./ver2.js";
if (someCheck) {
moduleName = "./ver1.js";
}
var x = require(moduleName)
var x = require(moduleName);
```
Note: neither file will be bundled.
Using these two techniques you can change your application code so mdoules are not bundles, and generate a includes.js file as part of your build process so that the right files get bundled for your build configuration.
### __dirname
Using these two techniques you can change your application code so modules are not bundles, and generate a includes.js file as part of your build process so that the right files get bundled for your build configuration.
Once the module is budnled it is part of the executable. __dirname is therefore the executable dir (process.execPath). Thus if you put resources on a realtive path from the the executable your app will be able to access them.
### &#95;&#95;dirname
If you had a data file at /dev/myNodeApp/stateManager/handler/data/some.csv
and a file at /dev/myNodeApp/stateManager/handler/loader.js
```
Once the module is bundled it is part of the executable. &#95;&#95;dirname is therefore the executable dir (process.execPath). Thus if you put resources on a relative path from the the executable your app will be able to access them.
If you had a data file at `/dev/myNodeApp/stateManager/handler/data/some.csv`
and a file at `/dev/myNodeApp/stateManager/handler/loader.js`
```javascript
module.exports = fw.readFileSync(path.join(__dirname, "./data/some.csv"));
```
you would need to deploy some.csv in a sub dir data/ along side your executable
You would need to deploy some.csv in a sub dir `data/` along side your executable
There are potential use cases for __dirname where the executable path is not the correct substitution, and could result in a silent error (possibly even in a dependciey that you are unaware of).
There are potential use cases for &#95;&#95;dirname where the executable path is not the correct substitution, and could result in a silent error (possibly even in a dependency that you are unaware of).
Note: __filename will be 'undefined'
Note: &#95;&#95;filename will be 'undefined'
### child_process.fork
@@ -99,13 +101,13 @@ Via NPM:
Or git:
```bash
git clone
git clone
```
### CLI Usage
````text
```text
Usage: nexe -i [sources] -o [binary]
Options:
@@ -115,12 +117,12 @@ Options:
-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]
````
```
### Code Usage
````javascript
```javascript
var nexe = require('nexe');
@@ -131,7 +133,12 @@ nexe.compile({
nodeTempDir: __dirname,
flags: true
}, function(err) {
});
````
```
## Maintainers
* __Jared Allard__ ([@rainbowdashdc](https://github.com/RainbowDashDC)) &lt;[rainbowdashdc@mezgrman.de](mailto:rainbowdashdc@mezgrman.de)&gt; (Active)
* __Craig Jefferds__ ([@crcn](https://github.com/crcn)) &lt;[craig.j.condon@gmail.com](mailto:craig.j.condon@gmail.com)&gt; (Not Active)
+9 -4
View File
@@ -34,6 +34,11 @@ options('f', {
options('v', {
alias: 'version',
description: 'Display version number'
}).
options('p', {
alias: 'python',
description: 'Set path of python to use.',
default: 'python'
});
var argv = cli.argv;
@@ -54,12 +59,12 @@ function toRelative(pt) {
return path.join(process.cwd(), pt);
}
require('../lib').compile({
require('../lib').compile({
input : require.resolve(toRelative(argv.i)),
output : toRelative(argv.o),
output : toRelative(argv.o),
flags : argv.f,
nodeVersion : argv.r,
nodeVersion : argv.r,
python : argv.python,
nodeTempDir : toRelative(argv.t) }, function(error) {
if(error) console.log(error.message);
+3 -2
View File
@@ -3,9 +3,10 @@ var nexe = require('nexe');
nexe.compile(
{
input: "./index.js",
output: "./helloWorld.exe",
output: "",
nodeVersion: "0.10.33",
nodeTempDir: "",
python: "C:\\Python27\\python.exe",
flags: true,
resourceFiles: ["./message.txt"]
},
@@ -14,4 +15,4 @@ nexe.compile(
console.log(err);
}
}
);
);
+73 -12
View File
@@ -19,8 +19,10 @@ var _log = require("./log"),
_monkeypatch = require("./monkeypatch");
var isWin = /^win/.test(process.platform);
var isPy;
/**
* Compiliation process.
*/
exports.compile = function (options, complete) {
@@ -28,11 +30,31 @@ exports.compile = function (options, complete) {
var nodeCompiler, nexeEntryPath;
async.waterfall([
/** check relevant options
*
*/
function checkOpts (next) {
/*
* Have we been given a custom flag for python executable?
*/
if(options.python!=='python' && options.python!=="") {
if(isWin) {
isPy=options.python.replace(/\//gm, "\\"); // use windows file paths, batch is sensitive.
} else {
isPy=options.python;
}
_log("set python as "+isPy);
} else {
isPy="python";
}
next();
},
/**
* first download node
*/
function downloadNode (next) {
_downloadNode(options.nodeVersion, options.nodeTempDir, next);
},
@@ -104,11 +126,16 @@ exports.compile = function (options, complete) {
*/
function makeExe (next) {
_log("make");
if(isWin) {
_log("vcbuild [make stage]");
} else {
_log("make");
}
nodeCompiler.make(next);
},
/**
* we create the output directory if needed
*/
function makeOutputDirectory (next) {
@@ -116,11 +143,20 @@ exports.compile = function (options, complete) {
},
/**
* Copy the compilied binary to the output specified.
*/
function copyBinaryToOutput (next) {
_log("cp %s %s", nodeCompiler.releasePath, options.output);
ncp(nodeCompiler.releasePath, options.output, next);
ncp(nodeCompiler.releasePath, options.output, function (err) {
if (err) {
console.log("* NOTICE * Failed to copy binary. Did the build fail?");
throw err; // dump raw error object
}
_log('copied');
next();
});
}
], complete);
}
@@ -228,7 +264,27 @@ function _getNodeCompiler (nodeFileDir, complete) {
version: path.basename(nodeFileDir),
releasePath: path.join(dir, "Release", "node.exe"),
make: function(next) {
var vcbuild = spawn("vcbuild.bat", ["nosign", "release"], { cwd: dir });
// create a new env with minimal impact on old one
var newEnv = process.env
if(isPy!=="python") {
_log("vcbuild: python => "+isPy);
// replace vcbuild contents
var data = fs.readFileSync(dir+"\\vcbuild.bat", 'utf8');
var result = data.replace(/[\s]python/gm, isPy); // I can't regex
var err = fs.writeFileSync(dir+"\\vcbuild.bat", result, 'utf8');
if(err) throw err;
// temporary fix, should edit whatever is gening the project files at somepoint.
newEnv.path = process.env.PATH+";"+path.dirname(isPy)
}
// spawn a vcbuild process with our custom enviroment.
var vcbuild = spawn("vcbuild.bat", ["nosign", "release"], {
cwd: dir,
env: newEnv
});
vcbuild.stdout.pipe(process.stdout);
vcbuild.stderr.pipe(process.stderr);
vcbuild.on("close", function() {
@@ -242,7 +298,13 @@ function _getNodeCompiler (nodeFileDir, complete) {
version: path.basename(nodeFileDir),
releasePath: path.join(dir, "out", "Release", "node"),
make: function (next) {
var configure = spawn("./configure", [], { cwd: dir });
var cfg = "./configure", configure;
if(isPy !== "python") {
configure = spawn(isPy, [cfg], { cwd: dir });
} else {
configure = spawn(cfg, [], { cwd: dir });
}
configure.stdout.pipe(process.stdout);
configure.stderr.pipe(process.stderr);
configure.on("close", function () {
@@ -281,7 +343,7 @@ function _monkeyPatchNodeConfig (compiler, complete) {
},
/**
* monkeypatch main entry point
* monkeypatch main entry point
*/
function (next) {
@@ -299,7 +361,7 @@ function _monkeyPatchGyp (compiler, complete) {
var gypPath = path.join(compiler.dir, "node.gyp");
_monkeypatch(
gypPath,
gypPath,
function (content) {
return ~content.indexOf("nexe.js");
},
@@ -317,7 +379,7 @@ function _monkeyPatchMainJs (compiler, complete) {
var mainPath = path.join(compiler.dir, "src", "node.js");
_monkeypatch(
mainPath,
mainPath,
function (content) {
return ~content.indexOf("nexe");
},
@@ -395,9 +457,9 @@ function _logProgress (req) {
req.on("response", function (resp) {
var len = parseInt(resp.headers["content-length"], 10),
bar = new ProgressBar("[:bar]", {
complete: "=",
incomplete: " ",
bar = new ProgressBar("[:bar]", {
complete: "=",
incomplete: " ",
total: len,
width: process.stdout.columns - 2
});
@@ -409,4 +471,3 @@ function _logProgress (req) {
return req;
}
-2
View File
@@ -1,3 +1 @@
module.exports = require("./exe");