From 60589db2482633017a4bdebe52bd8f6c58b79744 Mon Sep 17 00:00:00 2001 From: shmyga Date: Fri, 6 Apr 2018 16:29:05 +0300 Subject: [PATCH] big update --- haxetool/core.js | 2 + haxetool/debug.js | 64 +++---------- haxetool/flashplayer.js | 7 +- haxetool/haxe.js | 104 +++++++-------------- haxetool/neko.js | 35 -------- haxetool/project.js | 85 +++++++++++++----- haxetool/tail.js | 22 +++-- index.js | 1 - package.json | 7 +- run/command.js | 195 ++++++++++++++++++++++++++++++++++++++++ run/index.js | 70 +++++++++++++++ template/project.hxml | 9 ++ template/project.xml | 12 +-- 13 files changed, 412 insertions(+), 201 deletions(-) delete mode 100644 haxetool/neko.js create mode 100644 run/command.js create mode 100644 run/index.js create mode 100644 template/project.hxml diff --git a/haxetool/core.js b/haxetool/core.js index 34db546..01dcc83 100644 --- a/haxetool/core.js +++ b/haxetool/core.js @@ -27,6 +27,7 @@ class Config { this.sources = []; this.assets = []; this.libs = []; + this.macros = []; this.meta = { title: null, version: null, @@ -46,6 +47,7 @@ class Config { if (params.sources !== undefined) this.sources = this.sources.concat(params.sources.map(item => path.resolve(cwd, item))); if (params.assets !== undefined) this.assets = this.assets.concat(params.assets.map(item => path.resolve(cwd, item))); if (params.libs !== undefined) this.libs = this.libs.concat(Array.isArray(params.libs) ? params.libs : Object.entries(params.libs).map(([k, v]) => ({name: k, version: v}))); + if (params.macros !== undefined) this.macros = this.macros.concat(params.macros); if (params.meta !== undefined) this.meta = {...this.meta, ...params.meta}; } diff --git a/haxetool/debug.js b/haxetool/debug.js index cdd4671..9b8babc 100755 --- a/haxetool/debug.js +++ b/haxetool/debug.js @@ -1,13 +1,11 @@ -const net = require('net'); -const through = require('through2'); const colors = require('ansi-colors'); -const log = require('fancy-log'); const _colors = { '[DEBUG]': colors.white, '[INFO]': colors.cyan, '[ERROR]': colors.red, + 'Called from ': colors.red, '[WARNING]': colors.yellow, }; @@ -23,58 +21,20 @@ const getColor = (line) => { class Debug { - static log (line, color) { - if (color === undefined) { - color = getColor(line) || colors.white; - } - if (line[0] === '\t') { - console.log(color(line)); - } else { - const result = line.split(' '); - console.log(colors.gray(result.slice(0, 4).join(' ')) + ' ' + color(result.slice(4).join(' '))); - } - }; - constructor() { - this.host = 'localhost'; - this.port = 6000 + Math.floor(Math.random() * 1000); + this.color = colors.white; + this.log = this.log.bind(this); } - macro() { - return [ - `CompilationOption.set('debug.address','${this.host}')`, - `CompilationOption.set('debug.port','${this.port}')`, - ]; - }; - - run() { - const debug = this; - return through.obj(function (file, enc, callback) { - if (this.disabled) { - this.emit('end'); - callback(); - return; - } - let color = colors.white; - const server = net.createServer((socket) => { - socket.on("data", (data) => { - const lines = data.toString().split('\n'); - for (let line of lines) if (line.length > 2) { - const newColor = getColor(line); - if (newColor != null) color = newColor; - Debug.log(line, color); - } - }); - socket.on("close", () => { - socket.destroy(); - server.close(); - this.emit('end'); - callback(); - }); - }); - log(colors.green('[debug]'), colors.cyan('listen on'), colors.magenta(`${debug.host}:${debug.port}`)); - server.listen(debug.port, debug.host); - }) + log(line) { + const newColor = getColor(line); + if (newColor) this.color = newColor; + if (line[0] === '\t' || line.startsWith('Called from ')) { + console.log(this.color(line)); + } else { + const result = line.split(' '); + console.log(colors.gray(result.slice(0, 4).join(' ')) + ' ' + this.color(result.slice(4).join(' '))); + } } } diff --git a/haxetool/flashplayer.js b/haxetool/flashplayer.js index 5a52b78..02073e5 100755 --- a/haxetool/flashplayer.js +++ b/haxetool/flashplayer.js @@ -9,6 +9,7 @@ const PluginError = require('plugin-error'); const colors = require('ansi-colors'); const log = require('fancy-log'); const tar = require('tar'); +const Vinyl = require('vinyl'); class FlashPlayer extends Sdk { @@ -129,10 +130,10 @@ class FlashPlayer extends Sdk { //stream.push(file); // ToDo: watch when file is exists // or create log file in FlashPlayer.enableLog()? - /*stream.push(new Vinyl({ + stream.push(new Vinyl({ path: FlashPlayer.log - }));*/ - stream.push(file); + })); + //stream.push(file); }; return stream = through.obj(bufferContents); diff --git a/haxetool/haxe.js b/haxetool/haxe.js index 7b52ee3..1bc1d71 100755 --- a/haxetool/haxe.js +++ b/haxetool/haxe.js @@ -56,7 +56,9 @@ class Haxe extends Sdk { process.env.HAXE_VERSION = this.version; process.env.HAXE_STD_PATH = `${this.binPath}/std`; process.env.HAXE_HOME = this.binPath; - process.env.PATH = `${process.env.PATH}:${this.binPath}`; + if (process.env.PATH.indexOf(this.binPath) === -1) { + process.env.PATH = `${process.env.PATH}:${this.binPath}`; + } } prepare() { @@ -81,7 +83,7 @@ class Haxe extends Sdk { } openfl(command, platform, config, debug=false) { - log(this.tag, colors.cyan('openfl', platform)); + log(this.tag, colors.cyan(`openfl build ${platform}`)); const buildDir = path.join(os.tmpdir(), 'build', config.name); mkdirp.sync(buildDir); @@ -98,8 +100,33 @@ class Haxe extends Sdk { return this.haxelib(args).then(() => vfs.src(`${target}/**/*`)); } - build(platform, config) { + build(platform, config, debug=false) { + log(this.tag, colors.cyan(`build ${platform}`)); + const buildDir = path.join(os.tmpdir(), 'build', config.name); + mkdirp.sync(buildDir); + const projectTemplate = template(fs.readFileSync(path.resolve(__dirname, '..', 'template/project.hxml'))); + + const ext = { + flash: '.swf', + neko: '.n', + }[platform] || ''; + + const out = { + flash: 'swf' + }[platform] || platform; + + const project = projectTemplate({...config, buildDir: buildDir, platform: platform, ext: ext, out: out}); + const projectHXML = path.resolve(buildDir, 'project.hxml'); + fs.writeFileSync(projectHXML, project); + + const args = [projectHXML]; + if (debug) { + args.push('-debug'); + } + const target = path.resolve(buildDir, platform, 'bin'); + rmdir(target); + return this.haxe(args).then(() => vfs.src(`${target}/**/*`)); } install(packages) { @@ -151,77 +178,6 @@ class Haxe extends Sdk { promise = promise.then(() => this.haxelib(['upgrade', '--always'])); return promise; } - - - _build(params) { - params = Object.assign({ - version: null, - values: {}, - lib: [], - macro: [], - debug: false, - }, params); - - const files = []; - let stream = null; - - const bufferContents = (file, enc, callback) => { - // ToDo: check file not stream - files.push(file); - callback(); - }; - - const endStream = (callback) => { - log(this.tag, colors.cyan("haxe", params.platform), '=>', colors.magenta(params.outputFile)); - const args = []; - // main - args.push('-main', params.main); - // lib - let lib = params.lib; - if (!Array.isArray(lib)) { - lib = Object.entries(lib).map(([k, v]) => `${k}:${v.split('@')[0]}`); - } - for (const item of lib) { - args.push('-lib', item); - } - // cp - for (const cp of params.cp) { - args.push('-cp', cp); - } - // macro - for (const macro of params.macro) { - args.push('--macro', `"${macro}"`); - } - for (let key of Object.keys(params.values)) { - const value = params.values[key]; - if (value === true) { - args.push(`-D ${key}`); - } else if (value) { - args.push(`-D ${key}="${value}"`); - } - } - const tmpFile = tmp.generateFile(); - args.push(`-${params.platform}`, tmpFile.path); - if (params.debug) { - args.push('-debug'); - } - //console.log('haxe', args.join(' ')); - this.haxe(args).then(() => { - const out = new Vinyl({ - path: params.outputFile, - //contents: fs.createReadStream(tmpFile.path), - contents: fs.readFileSync(tmpFile.path), - }); - stream.push(out); - callback(); - }).catch((error) => { - stream.emit('error', new PluginError({plugin: this.name, message: error})); - callback(); - }); - }; - - return stream = through.obj(bufferContents, endStream); - } } Haxe.ID = 'haxe'; diff --git a/haxetool/neko.js b/haxetool/neko.js deleted file mode 100644 index 5ff1e42..0000000 --- a/haxetool/neko.js +++ /dev/null @@ -1,35 +0,0 @@ -const exec = require('./exec'); -const through = require('through2'); -const PluginError = require('plugin-error'); -const colors = require('ansi-colors'); -const log = require('fancy-log'); - -class Neko { - - constructor() { - this.tag = 'Neko'; - } - - run(...args) { - let stream = null; - const bufferContents = (file, enc, callback) => { - log(this.tag, colors.cyan("run"), colors.magenta(file.path)); - - exec('.', ['neko', file.path].concat(args).join(' ')) - .then(() => { - stream.emit('end'); - callback(); - }) - .catch((error) => { - stream.emit('error', new PluginError({plugin: this.tag, message: error})); - callback(); - }); - - stream.push(file); - }; - - return stream = through.obj(bufferContents); - } -} - -module.exports = Neko; \ No newline at end of file diff --git a/haxetool/project.js b/haxetool/project.js index acb8477..75c45f6 100644 --- a/haxetool/project.js +++ b/haxetool/project.js @@ -1,28 +1,52 @@ const gulp = require('gulp'); +const path = require('path'); +const fs = require('fs'); //const concat = require('gulp-concat'); //const uglify = require('gulp-uglify'); //const babel = require('gulp-babel'); //const template = require('gulp-template'); const Haxe = require('./haxe'); const FlashPlayer = require('./flashplayer'); -const Neko = require('./neko'); const Debug = require('./debug'); const webserver = require('gulp-webserver'); -const run = require('gulp-run'); +const run = require('../run/index'); const tail = require('./tail'); //const deb = require('gulp-debian'); const {BuildSystem, Platform, Config} = require('./core'); const vfs = require('vinyl-fs'); +const rename = require('gulp-rename'); + + +const streamToPromise = (stream) => { + return new Promise((resolve, reject) => { + stream.on("end", resolve); + stream.on("error", reject); + }); +}; /** * */ -class Builder { +class Target { + + constructor() { + this.target = 'target'; + } + + targetPath(name, platform) { + return path.resolve(this.target, name, platform); + } +} + +/** + * + */ +class Builder extends Target { constructor(buildSystem) { + super(); this.buildSystem = buildSystem; - this.target = 'target'; } prepare() { @@ -59,10 +83,14 @@ class HaxeBuilder extends Builder { } call(platform, config, debug) { + const target = this.targetPath(config.name, platform); switch (this.buildSystem) { case BuildSystem.OPENFL: return this.haxe.openfl('build', platform, config, debug) - .then(result => result.pipe(vfs.dest(`${this.target}/${platform}`))); + .then(result => streamToPromise(result.pipe(vfs.dest(target)))); + case BuildSystem.HAXE: + return this.haxe.build(platform, config, debug) + .then(result => streamToPromise(result.pipe(vfs.dest(target)))); } } } @@ -73,12 +101,12 @@ Builder.register(BuildSystem.OPENFL, HaxeBuilder); /** * */ -class Runner { +class Runner extends Target { constructor(platform, name) { + super(); this.platform = platform; this.name = name; - this.target = 'target'; } prepare() { @@ -89,6 +117,17 @@ class Runner { throw 'Not Implemented'; } + targetPath() { + return super.targetPath(this.name, this.platform); + } + + log(stream) { + stream + .pipe(tail(new Debug().log)) + .pipe(rename('out.log')) + .pipe(gulp.dest(this.targetPath())); + } + static register(platform, builder) { Runner.factory[platform] = builder; } @@ -115,9 +154,13 @@ class FlashRunner extends Runner { } call(debug) { - return gulp.src(`${this.target}/${this.platform}/${this.name}.swf`) - .pipe(this.player.run(true)) - .pipe(debug.run()); + const target = this.targetPath(); + const filename = path.resolve(target, this.name+'.swf'); + const player = this.player.flashPlayerBin(debug); + FlashPlayer.trust(filename); + fs.writeFileSync(FlashPlayer.log, ''); + const result = gulp.src(filename).pipe(run(player + " <%=file.basename%>", {cwd: target})); + return this.log(gulp.src(FlashPlayer.log)); } } @@ -129,7 +172,7 @@ Runner.register(Platform.FLASH, FlashRunner); class Html5Runner extends Runner { call(debug) { - return gulp.src(`${this.target}/${this.platform}`) + return gulp.src(this.targetPath()) .pipe(webserver({ host: 'localhost', port: 3000, open: true, @@ -146,9 +189,10 @@ Runner.register(Platform.HTML5, Html5Runner); class LinuxRunner extends Runner { call(debug) { - return gulp.src(`${this.target}/${this.platform}/${this.name}`) - .pipe(run(`./${this.name}`, {cwd: `target/${this.platform}`, verbosity: 1})) - .pipe(tail(Debug.log)); + const target = this.targetPath(); + const filename = path.resolve(target, this.name); + const result = gulp.src(filename).pipe(run("./<%=file.basename%>", {cwd: target})); + return this.log(result); } } @@ -160,9 +204,10 @@ Runner.register(Platform.LINUX, LinuxRunner); class NekoRunner extends Runner { call(debug) { - return gulp.src(`${this.target}/${this.platform}/${this.name}.n`) - .pipe(new Neko().run()) - .pipe(debug.run()); + const target = this.targetPath(); + const filename = path.resolve(target, this.name+'.n'); + const result = gulp.src(filename).pipe(run("neko <%=file.path%>", {cwd: target})); + return this.log(result); } } @@ -200,10 +245,10 @@ class Project { ]; } - bind(module, gulp /* ToDo: spike */) { + bind(module, external_gulp /* ToDo: spike */) { for (const platform of this.platforms) { - module.exports[`${this.config.name}:${platform}:build`] = gulp.series(this.build(platform)); - module.exports[`${this.config.name}:${platform}:run`] = gulp.series(this.run(platform)); + module.exports[`${this.config.name}:${platform}:build`] = (external_gulp || gulp).series(this.build(platform)); + module.exports[`${this.config.name}:${platform}:run`] = (external_gulp || gulp).series(this.run(platform)); } return this; } diff --git a/haxetool/tail.js b/haxetool/tail.js index b4ddeed..d326ea6 100644 --- a/haxetool/tail.js +++ b/haxetool/tail.js @@ -1,15 +1,11 @@ const through = require('through2'); -const colors = require('ansi-colors'); -const log = require('fancy-log'); - -const TAG = colors.green('[tail]'); - - -const { Writable } = require('stream'); -const { StringDecoder } = require('string_decoder'); +const {Tail} = require('tail'); +const {Writable} = require('stream'); +const {StringDecoder} = require('string_decoder'); class StringWritable extends Writable { + constructor(handler, options) { super(options); this.handler = handler; @@ -17,6 +13,7 @@ class StringWritable extends Writable { this._decoder = new StringDecoder(state.defaultEncoding); this.data = ''; } + _write(chunk, encoding, callback) { if (encoding === 'buffer') { chunk = this._decoder.write(chunk); @@ -27,6 +24,7 @@ class StringWritable extends Writable { this.data += chunk; callback(); } + _final(callback) { this.data += this._decoder.end(); callback(); @@ -36,7 +34,13 @@ class StringWritable extends Writable { module.exports = (handler) => { return through.obj(function (file, enc, callback) { - file.contents.pipe(new StringWritable(handler)); + if (file.contents && file.contents.pipe) { + file.contents.pipe(new StringWritable(handler)); + } else { + const tail = new Tail(file.path); + tail.on("line", data => handler(data)); + tail.on("error", error => handler('[ERROR]: ', error)); + } this.push(file); callback(); }); diff --git a/index.js b/index.js index f2d9145..67430d1 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,6 @@ module.exports = { Sdk: require('./haxetool/sdk'), Haxe: require('./haxetool/haxe'), FlashPlayer: require('./haxetool/flashplayer'), - Neko: require('./haxetool/neko'), AdobeAir: require('./haxetool/adobe_air'), Project: require('./haxetool/project'), }; \ No newline at end of file diff --git a/package.json b/package.json index 7a5a70c..9b4a8dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gulp-haxetool", - "version": "0.0.5", + "version": "0.0.6", "description": "Haxe tool for gulp", "main": "index.js", "dependencies": { @@ -10,14 +10,17 @@ "fs-extra": "^5.0.0", "got": "^8.3.0", "gulp": "^4.0.0", - "gulp-run": "^1.7.1", + "gulp-rename": "^1.2.2", + "gulp-spawn": "^0.4.0", "gulp-webserver": "^0.9.1", + "lodash.defaults": "^4.2.0", "lodash.template": "^4.4.0", "mkdirp": "^0.5.1", "plugin-error": "^1.0.1", "progress": "^2.0.0", "promise-streams": "^2.1.1", "rmdir": "^1.2.0", + "tail": "^1.2.3", "tar": "^4.4.1", "through2": "^2.0.3", "tmp-file": "^2.0.1", diff --git a/run/command.js b/run/command.js new file mode 100644 index 0000000..30a0c99 --- /dev/null +++ b/run/command.js @@ -0,0 +1,195 @@ +var cp = require('child_process'); +var path = require('path'); +var stream = require('stream'); +var util = require('util'); +var defaults = require('lodash.defaults'); +var applyTemplate = require('lodash.template'); +var Vinyl = require('vinyl'); +var colors = require('ansi-colors'); + +/** + * Creates a new `gulp-run` command. + * + * @param {string} command + * @param {object} options + */ +function Command(command, options) { + var previousPath; + + this.command = command; + + // We're on Windows if `process.platform` starts with "win", i.e. "win32". + this.isWindows = (process.platform.lastIndexOf('win') === 0); + + // the cwd and environment of the command are the same as the main node + // process by default. + this.options = defaults(options || {}, { + cwd: process.cwd(), + env: process.env, + verbosity: (options && options.silent) ? 1 : 2, + usePowerShell: false + }); + + // include node_modules/.bin on the path when we execute the command. + previousPath = this.options.env.PATH; + this.options.env.PATH = path.join(this.options.cwd, 'node_modules', '.bin'); + this.options.env.PATH += path.delimiter; + this.options.env.PATH += previousPath; +} + +/** + * Execute the command, invoking the callback when the command exits. + * Returns a Vinyl file wrapping the command's stdout. + * + * @param {string} stdin + * @param {function} callback + * @return {Stream} + */ +Command.prototype.exec = function exec(stdin, callback) { + var self = this; + var command; + var fileName; + var directory; + var subShell; + var log; + var err; + var stdout; + + // parse the arguments, both are optional. + // after parsing, stdin is a vinyl file to use as standard input to + // the command (possibly empty), and callback is a function. + if (typeof stdin === 'function') { + callback = stdin; + stdin = undefined; + } else if (typeof callback !== 'function') { + callback = function noop() {}; + } + + if (!(stdin instanceof Vinyl)) { + fileName = this.command.split(' ')[0]; + directory = path.join(this.options.cwd, fileName); + + if (typeof stdin === 'string') { + stdin = new Vinyl({ + path: directory, + contents: new Buffer(stdin) + }); + } else if (stdin instanceof Buffer || stdin instanceof stream.Readable) { + stdin = new Vinyl({ + path: directory, + contents: stdin + }); + } else { + stdin = new Vinyl(stdin); + + if (!stdin.path) { + stdin.path = directory; + } + } + } + + // execute the command. + // we spawn the command in a subshell, so things like i/o redirection + // just work. e.g. `echo hello world >> ./hello.txt` works as expected. + command = applyTemplate(this.command)({ + file: stdin + }); + + if (this.isWindows && this.options.usePowerShell) { + // windows powershell + subShell = cp.spawn('powershell.exe', ['-NonInteractive', '-NoLogo', '-Command', command], { + env: this.options.env, + cwd: this.options.cwd + }); + } else if (this.isWindows) { + // windows cmd.exe + subShell = cp.spawn('cmd.exe', ['/c', command], { + env: this.options.env, + cwd: this.options.cwd + }); + } else { + // POSIX shell + subShell = cp.spawn('sh', ['-c', command], { + env: this.options.env, + cwd: this.options.cwd + }); + } + + // setup the output + // + // - if verbosity equals to 3, the command prints directly to the terminal. + // - if verbosity equals to 2, the command's stdout and stderr are buffered + // and printed to the user's terminal after the command exits (this + // prevents overlaping output of multiple commands) + // - if verbosity equals to 1, the command's stderr is buffered as in 2, but + // the stdout is silenced. + log = new stream.PassThrough(); + + function sendLog(context) { + var title = util.format( + '$ %s%s', + colors.blue(command), + (self.options.verbosity < 2) ? colors.grey(' # Silenced\n') : '\n' + ); + + context.write(title); + } + + switch (this.options.verbosity) { + case 3: + sendLog(process.stdout); + subShell.stdout.pipe(process.stdout); + subShell.stderr.pipe(process.stderr); + break; + case 2: + subShell.stdout.pipe(log); + // fallthrough + case 1: + subShell.stderr.pipe(log); + sendLog(log); + break; + } + + // setup the cleanup proceedure for when the command finishes. + subShell.once('close', function handleSubShellClose() { + // write the buffered output to stdout + var content = log.read(); + + if (content !== null) { + process.stdout.write(content); + } + }); + + subShell.once('exit', function handleSubShellExit(code) { + // report an error if the command exited with a non-zero exit code. + if (code !== 0) { + err = new Error(util.format('Command `%s` exited with code %s', command, code)); + err.status = code; + + return callback(err); + } + + callback(null); + }); + + // the file wrapping stdout is as the one wrapping stdin (same metadata) + // with different contents. + stdout = stdin.clone(); + stdout.contents = subShell.stdout.pipe(new stream.PassThrough()); + + // finally, write the input to the process's stdin. + //stdin.pipe(subShell.stdin); //ToDo: + + return stdout; +}; + +/** + * Returns the command template. + * + * @return {string} + */ +Command.prototype.toString = function toString() { + return this.command; +}; + +module.exports = Command; diff --git a/run/index.js b/run/index.js new file mode 100644 index 0000000..74c4083 --- /dev/null +++ b/run/index.js @@ -0,0 +1,70 @@ +/** + * Pipe shell commands in gulp. + * @module gulp-run + */ + +var inherit = require('util').inherits; +var Transform = require('stream').Transform; +var Command = require('./command'); + +/** + * Creates a GulpRunner. + * + * A GulpRunner is a Vinyl transform stream that spawns a child process to + * transform the file. A separate process is spawned to handle each file + * passing through the stream. + * + * @param {string} template + * @param {object} options + */ +function GulpRunner(template, options) { + if (!(this instanceof GulpRunner)) { + return new GulpRunner(template, options); + } + + this.command = new Command(template, options || {}); + Transform.call(this, { objectMode: true }); +} + +/** + * @extends {Stream.Transform} + */ +inherit(GulpRunner, Transform); + +/** + * @param {string} file + * @param {string} encoding + * @param {function} callback + * @return {void} + */ +GulpRunner.prototype._transform = function _transform(file, encoding, callback) { + var newfile = this.command.exec(file, callback); + this.push(newfile); +}; + +/** + * Writes `stdin` to itself and returns itself. + * + * Whenever an object is written into the GulpRunner, a new process is + * spawned taking that data as standard input, and a Vinyl file wrapping the + * process's standard output is pushed downstream. + * + * `stdin` may be a String, Buffer, Readable stream, or Vinyl file. + * + * @param {mixed} stdin + * @param {function} callback + * @return {GulpRunner} + */ +GulpRunner.prototype.exec = function exec(stdin, callback) { + this.write(stdin, callback); + this.end(); + return this; +}; + +/** + * @static + * @type {Command} + */ +GulpRunner.Command = Command; + +module.exports = GulpRunner; diff --git a/template/project.hxml b/template/project.hxml new file mode 100644 index 0000000..83bf3d7 --- /dev/null +++ b/template/project.hxml @@ -0,0 +1,9 @@ +<% sources.forEach(function(item) { %> +-cp "<%=item%>"<% }); %> +<% libs.forEach(function(item) { %> +-lib <%=item.name%>:<%=item.version.split('@').shift()%><% }); %> +<% macros.forEach(function(item) { %> +--macro "<%=item%>"<% }); %> + +-main <%=main%> +-<%=out%> "<%=buildDir%>/<%=platform%>/bin/<%=name%><%=ext%>" diff --git a/template/project.xml b/template/project.xml index 945d4db..99002e8 100644 --- a/template/project.xml +++ b/template/project.xml @@ -1,13 +1,15 @@ - - + + <% sources.forEach(function(item) { %> - <% }); %> + <% }); %> <% assets.forEach(function(item) { %> - <% }); %> + <% }); %> <% libs.forEach(function(item) { %> - <% }); %> + <% }); %> + <% macros.forEach(function(item) { %> + <% }); %>