diff --git a/bin/nexe b/bin/nexe index cd9a517..589ee2c 100755 --- a/bin/nexe +++ b/bin/nexe @@ -14,7 +14,7 @@ options('o', { demand: true, alias: 'output', desc: 'The output binary', - default: process.cwd() + '/release/' + path.basename(process.cwd()) + '.nex' + default: "..."+(process.cwd() + '/release/' + path.basename(process.cwd()) + '.nex').substr(-47) // cleaner for long directories }). options('r', { alias: 'runtime', @@ -39,6 +39,11 @@ options('p', { alias: 'python', description: 'Set path of python to use.', default: 'python' +}). +options('F', { + alias: 'framework', + description: 'Set the framework to use', + default: 'nodejs' }); var argv = cli.argv; @@ -64,7 +69,7 @@ require('../lib').compile({ flags : argv.f, nodeVersion : argv.r, python : argv.python, - nodeTempDir : toAbsolute(argv.t) }, function(error) { - - if(error) console.log(error.message); + nodeTempDir : toAbsolute(argv.t), + framework : argv.F }, function(error) { + if(error) console.log(error.message); }); diff --git a/lib/exe.js b/lib/exe.js index 82bba92..dabde8b 100644 --- a/lib/exe.js +++ b/lib/exe.js @@ -20,6 +20,8 @@ _monkeypatch = require("./monkeypatch"); var isWin = /^win/.test(process.platform); var isPy; +var framework; +var version; /** * Compiliation process. @@ -30,14 +32,15 @@ exports.compile = function (options, complete) { var nodeCompiler, nexeEntryPath; async.waterfall([ - /** check relevant options - * + /** + *check relevant options */ function checkOpts (next) { - /* + /** * Have we been given a custom flag for python executable? */ - if(options.python!=='python' && options.python!=="" && options.python!==undefined) { + if(options.python!=='python' && options.python!=="" + && options.python!==undefined) { if(isWin) { isPy=options.python.replace(/\//gm, "\\"); // use windows file paths, batch is sensitive. } else { @@ -49,14 +52,49 @@ exports.compile = function (options, complete) { isPy="python"; } - next(); + // remove dots + options.framework = options.framework.replace(/\./g, ""); + + // set outter-scope framework variable. + framework = options.framework; + _log("framework => "+framework); + + version = options.nodeVersion; // better framework vc + + // check iojs version + if (framework === "iojs" && version === "latest" ) { + _log("fetching iojs versions"); + mkdirp(options.nodeTempDir); // make temp dir, probably repetive. + + // create write stream so we have control over events + var output = fs.createWriteStream(path.join(options.nodeTempDir, + "iojs-versions.json")); + + request.get("https://iojs.org/dist/index.json") + .pipe(output); + + output.on('close', function() { + _log("done"); + var f = fs.readFileSync(path.join(options.nodeTempDir, + "iojs-versions.json")); + f = JSON.parse(f); + version = f[0].version.replace("v", ""); + + _log("iojs latest => "+version); + + // continue down along the async road + next(); + }) + } else { + next(); + } }, /** * first download node */ function downloadNode (next) { - _downloadNode(options.nodeVersion, options.nodeTempDir, next); + _downloadNode(version, options.nodeTempDir, next); }, /** @@ -162,12 +200,17 @@ exports.compile = function (options, complete) { } /** + * Download a version of node + * + * @param {string} version, version of node to download + * @param {string} directory, where to store the downloaded src + * @param {function} complete, callback */ function _downloadNode (version, directory, complete) { - var nodeFileDir = path.resolve(path.join(process.cwd(), directory, version)), - nodeFilePath = path.resolve(path.join(nodeFileDir, "node-" + version + ".tar.gz")); + var nodeFileDir = path.resolve(path.join(directory, framework, version)), // fixes #107, was process.cwd(), + rest. + nodeFilePath = path.resolve(path.join(nodeFileDir, framework + "-" + version + ".tar.gz")); // might already be downloaded, and unzipped @@ -194,13 +237,16 @@ function _downloadNode (version, directory, complete) { function downloadNode (next) { if (fs.existsSync(nodeFilePath)) return next(); - var url, prefix = "https://nodejs.org/dist"; + var type = global.type; + var url, prefix = "https://"+framework+".org/dist"; // pick which url depending on the version + if(framework==="nodejs") framework = "node"; // cmon node why can't you stay the same + if (version === "latest") { - url = prefix + "/node-" + version + ".tar.gz"; + url = prefix + "/" + framework + "-" + version + ".tar.gz"; } else { - url = prefix + "/v" + version + "/node-v" + version + ".tar.gz"; + url = prefix + "/v" + version + "/"+framework+"-v" + version + ".tar.gz"; } _log("downloading %s", url); @@ -244,25 +290,37 @@ function _downloadNode (version, directory, complete) { * return the compiler object for the node version */ - function (next) { - _getNodeCompiler(nodeFileDir, next) + function (next, type) { + _getNodeCompiler(nodeFileDir, next, type) }, ], complete); } /** + * Get the compilier we will use for whatever platform we may be on and configure + * it. */ -function _getNodeCompiler (nodeFileDir, complete) { +function _getNodeCompiler (nodeFileDir, complete, type) { var dir = _getFirstDirectory(nodeFileDir); + // standard + var executable = "node.exe"; + var binary = "node"; + + // iojs specifics. + if(framework === "iojs") { + executable = "iojs.exe"; + binary = "iojs"; + } + if (dir) { if(isWin) { complete(null, { dir: dir, version: path.basename(nodeFileDir), - releasePath: path.join(dir, "Release", "node.exe"), + releasePath: path.join(dir, "Release", executable), make: function(next) { // create a new env with minimal impact on old one var newEnv = process.env @@ -288,7 +346,7 @@ function _getNodeCompiler (nodeFileDir, complete) { complete(null, { dir: dir, version: path.basename(nodeFileDir), - releasePath: path.join(dir, "out", "Release", "node"), + releasePath: path.join(dir, "out", "Release", binary), make: function (next) { var cfg = "./configure", configure; if(isPy !== "python") { @@ -297,9 +355,54 @@ function _getNodeCompiler (nodeFileDir, complete) { configure = spawn(cfg, [], { cwd: dir }); } + // local function, move to top eventually + function _loop(dir) { + /* eventually try every python file */ + var pdir = fs.readdirSync(dir); + + pdir.forEach(function(v, i) { + var stat = fs.statSync(dir+"/"+v); + if(stat.isFile()) { + // only process Makefiles and .mk targets. + if(v !== "Makefile" && path.extname(v) !== ".mk") { + return; + } + + _log("patching "+v); + + /* 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'}); + + delete pv; + } else if(stat.isDirectory()) { + // must be dir? + // skip tests because we don't need them here + if(v !== "test") { + _loop(dir+"/"+v) + } + } + }); + } + configure.stdout.pipe(process.stdout); configure.stderr.pipe(process.stderr); configure.on("close", function () { + if(isPy !== "python") { + /** + * Originally I thought this only applied to io.js, + * however I soon found out this affects node.js, + * so it is now mainstream. + */ + _log("preparing python"); + + // loop over depends + _loop(dir); + } var platformMake = "make"; if (os.platform().match(/bsd$/) != null) { platformMake = "gmake"; @@ -346,6 +449,7 @@ function _monkeyPatchNodeConfig (compiler, complete) { } /** + * patch the gyp file to allow our custom includes */ function _monkeyPatchGyp (compiler, complete) { @@ -453,7 +557,7 @@ function _logProgress (req) { complete: "=", incomplete: " ", total: len, - width: ((isWin) ? 100 : process.stdout.columns - 2) + width: ((isWin) ? 100 : process.stdout.columns - 2) // windows doesn't output colums correctly }); req.on("data", function (chunk) {