Merge pull request #1 from kitcambridge/master

lodash: Replace the Makefile with a JavaScript-based build system. [kitcambridge]
Former-commit-id: d4d014cfd7fcacc49f8e4e17fc91c3bf70544a26
This commit is contained in:
John-David Dalton
2012-04-22 20:34:50 -07:00
4 changed files with 356 additions and 245 deletions

View File

@@ -1,39 +0,0 @@
BUILD_DIR = ${CURDIR}/build
DIST_DIR = ${CURDIR}/dist
VENDOR_DIR = ${CURDIR}/vendor
JS_ENGINE ?= `which node nodejs 2>/dev/null`
LODASH_TMP = ${BUILD_DIR}/lodash.tmp.js
LODASH_COMPILER = ${DIST_DIR}/lodash.compiler.js
LODASH_UGLIFY = ${DIST_DIR}/lodash.uglify.js
UGLIFY = ${VENDOR_DIR}/uglifyjs/bin/uglifyjs
CLOSURE_COMPILER = java -jar ${VENDOR_DIR}/closure-compiler/compiler.jar
PRE_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/pre-compile.js
POST_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/post-compile.js
core:
mkdir -p ${DIST_DIR}
cp ${CURDIR}/lodash.js ${LODASH_TMP}
${PRE_COMPILER} ${LODASH_TMP}
${CLOSURE_COMPILER} \
--compilation_level=ADVANCED_OPTIMIZATIONS \
--language_in=ECMASCRIPT5_STRICT \
--warning_level=QUIET \
--js ${LODASH_TMP} \
--js_output_file ${LODASH_COMPILER}
${POST_COMPILER} ${LODASH_COMPILER}
gzip -9f -c ${LODASH_COMPILER} > ${LODASH_COMPILER}.gz
${UGLIFY} \
--unsafe \
--max-line-len 500 \
-o ${LODASH_UGLIFY} \
${LODASH_TMP}
${POST_COMPILER} ${LODASH_UGLIFY}
gzip -9f -c ${LODASH_UGLIFY} > ${LODASH_UGLIFY}.gz
rm -f ${LODASH_TMP}

136
build.js Executable file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env node
;(function () {
'use strict';
/* Load the Node file system, path, and child process modules. */
var fs = require('fs'), path = require('path'), spawn = require('child_process').spawn,
/* Load the UglifyJS compressor. */
uglifyJS = require(path.join(__dirname, 'vendor', 'uglifyjs', 'uglify-js')),
/* The `build` directory, containing the build scripts. */
buildPath = path.join(__dirname, 'build'),
/* The distribution directory. */
distPath = path.join(__dirname, 'dist'),
/* Load the pre- and post-processors. */
preprocess = require(path.join(buildPath, 'pre-compile')),
postprocess = require(path.join(buildPath, 'post-compile')),
/* The pre-processed Lo-Dash source. */
source = preprocess(fs.readFileSync(path.join(__dirname, 'lodash.js'), 'utf8'));
/* Create the destination directory if it doesn't exist. */
if (!path.existsSync(distPath)) {
fs.mkdirSync(distPath);
}
/* Compress and `gzip` Lo-Dash using the Closure Compiler. */
compile(source, function (exception, results) {
if (exception) {
throw exception;
}
// Post-process the minified source.
var source = postprocess(results);
// Save the final minified version.
fs.writeFileSync(path.join(distPath, 'lodash.compiler.js'), source);
gzip(source, function (exception, results) {
if (exception) {
throw exception;
}
// Save the `gzip`-ed version. The explicit `binary` encoding is
// necessary to ensure that the stream is written correctly.
fs.writeFileSync(path.join(distPath, 'lodash.compiler.js.gz'), results, 'binary');
});
});
/* Compress and `gzip` Lo-Dash using UglifyJS. */
uglify(source, function (results) {
var source = postprocess(results);
fs.writeFileSync(path.join(distPath, 'lodash.uglify.js'), source);
gzip(source, function (exception, results) {
if (exception) {
throw exception;
}
fs.writeFileSync(path.join(distPath, 'lodash.uglify.js.gz'), results, 'binary');
});
});
/* Compresses a `source` string using UglifyJS. Yields the result to a
* `callback` function. This function is synchronous; the `callback` is used
* for symmetry.
*/
function uglify(source, callback) {
var results = uglifyJS.uglify.gen_code(
// Enable unsafe transformations.
uglifyJS.uglify.ast_squeeze_more(
uglifyJS.uglify.ast_squeeze(
// Munge variable and function names, excluding the special `define`
// function exposed by asynchronous module loaders.
uglifyJS.uglify.ast_mangle(uglifyJS.parser.parse(source), {
'except': ['define']
}
))), {
'ascii_only': true
});
callback(uglifyJS.uglify.split_lines(results, 500));
}
/* Compresses a `source` string using the Closure Compiler. Yields the
* minified result to a `callback` function.
*/
function compile(source, callback) {
var compiler = spawn('java', [
// Load the Closure Compiler and set the compression options.
'-jar', path.join(__dirname, 'vendor', 'closure-compiler', 'compiler.jar'),
'--compilation_level=ADVANCED_OPTIMIZATIONS',
'--language_in=ECMASCRIPT5_STRICT',
'--warning_level=QUIET'
]), stdout = '', stderr = '';
// Explicitly set the encoding of the output and error streams.
compiler.stdout.setEncoding('utf8');
compiler.stderr.setEncoding('utf8');
compiler.stdout.on('data', function (data) {
stdout += data;
});
compiler.stderr.on('data', function (data) {
stderr += data;
});
compiler.on('exit', function (status) {
var exception = null;
if (status) {
exception = new Error(stderr);
exception.status = status;
}
callback(exception, stdout);
});
compiler.stdin.end(source);
}
/* Compresses a `source` string using the Unix `gzip` commands. Yields the
* result, and any exceptions encountered, to a `callback` function.
*/
function gzip(source, callback) {
var compressor = spawn('gzip', ['-9f', '-c']), stdout = '', stderr = '';
compressor.stdout.setEncoding('binary');
compressor.stderr.setEncoding('utf8');
compressor.stdout.on('data', function (data) {
stdout += data;
});
compressor.stderr.on('data', function (data) {
stderr += data;
});
compressor.on('exit', function (status) {
var exception = null;
if (status) {
exception = new Error(stderr);
exception.status = status;
}
callback(exception, stdout);
});
// Proxy the source string to the `gzip` executable.
compressor.stdin.end(source);
}
}());

View File

@@ -2,12 +2,8 @@
;(function() { ;(function() {
'use strict'; 'use strict';
/** The filesystem module */ /* Post-processes a compressed `src` string. */
var fs = require('fs'); var postprocess = module.exports = function postprocess(src) {
/** The JavaScript source */
var src = fs.readFileSync(process.argv[2], 'utf8');
/** The minimal license/copyright header */ /** The minimal license/copyright header */
var license = var license =
'/*!\n' + '/*!\n' +
@@ -18,7 +14,7 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
// set the version // set the version
license = license.replace('@VERSION', /VERSION:([\'"])(.*?)\1/.exec(src).pop()); license = license.replace('@VERSION', (/VERSION:([\'"])(.*?)\1/).exec(src).pop());
// move vars exposed by Closure Compiler into the IIFE // move vars exposed by Closure Compiler into the IIFE
src = src.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1'); src = src.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
@@ -27,8 +23,20 @@
src = src.replace(/'use strict'/, '"use strict"'); src = src.replace(/'use strict'/, '"use strict"');
// add license // add license
src = license + '\n;' + src; return license + '\n;' + src;
};
/*--------------------------------------------------------------------------*/
/** The filesystem module */
var fs = require('fs'), src;
if (module == require.main) {
// read the JavaScript source file from the first argument if the script
// was invoked directly (i.e., `node post-compile.js source.js`)
src = fs.readFileSync(process.argv[2], 'utf8');
// write to the same file // write to the same file
fs.writeFileSync(process.argv[2], src, 'utf8'); fs.writeFileSync(process.argv[2], postprocess(src), 'utf8');
}
}()); }());

View File

@@ -2,12 +2,7 @@
;(function() { ;(function() {
'use strict'; 'use strict';
/** The filesystem module */ var preprocess = module.exports = function preprocess(src) {
var fs = require('fs');
/** The JavaScript source */
var src = fs.readFileSync(process.argv[2], 'utf8');
/** Used to minify variables embedded in compiled strings */ /** Used to minify variables embedded in compiled strings */
var compiledVars = [ var compiledVars = [
'accumulator', 'accumulator',
@@ -196,9 +191,20 @@
// replace with modified snippet // replace with modified snippet
src = src.replace(snippet, result); src = src.replace(snippet, result);
}); });
return src;
};
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** The filesystem module */
var fs = require('fs'), src;
if (module == require.main) {
// read the JavaScript source file from the first argument if the script
// was invoked directly (i.e., `node pre-compile.js source.js`)
src = fs.readFileSync(process.argv[2], 'utf8');
// write to the same file // write to the same file
fs.writeFileSync(process.argv[2], src, 'utf8'); fs.writeFileSync(process.argv[2], preprocess(src), 'utf8');
}
}()); }());