const os = require('os'); const fs = require('fs'); const fse = require('fs-extra'); const path = require('path'); const exec = require('./exec'); const Sdk = require('./sdk'); const Env = require('./env'); const Neko = require('./neko'); const vfs = require('vinyl-fs'); const template = require('lodash.template'); const rename = require('gulp-rename'); class Haxe extends Sdk { getBin(name) { if (Sdk.System.isWindows) { return path.join(this.path, name + '.exe'); } else if (Sdk.System.isLinux) { const binPath = path.join(this.path, name); if (fs.existsSync(binPath)) { fs.chmodSync(binPath, 0o755); } return binPath; } throw `Unsupported OS: ${os.type()}`; } get haxeBin() { return this.getBin('haxe'); } get haxelibBin() { return this.getBin('haxelib'); } constructor(version) { super(Haxe.ID, version || Haxe.VERSION); this.neko = new Neko(); } get prepared() { try { return fs.existsSync(this.haxeBin); } catch (e) { return false; } } activate() { this.neko.activate(); Env.set('HAXE_VERSION', this.version); Env.set('HAXE_STD_PATH', path.join(this.path, 'std')); Env.set('HAXE_HOME', this.path); Env.addPath(this.path); Env.addPath(this.path, 'LD_LIBRARY_PATH'); } prepare() { return Promise.all([this.neko.prepare(), super.prepare()]).then(() => { fs.copyFileSync(path.resolve(__dirname, '..', 'template/haxe/activate'), path.resolve(this.path, 'activate')); }); } get link() { if (Sdk.System.isWindows) { return `https://github.com/HaxeFoundation/haxe/releases/download/${this.version}/haxe-${this.version}-win.zip`; } else if (Sdk.System.isLinux) { let arch = Sdk.System.archInt; return `https://github.com/HaxeFoundation/haxe/releases/download/${this.version}/haxe-${this.version}-linux${arch}.tar.gz`; } } haxe(args) { return exec('.', [this.haxeBin].concat(args).join(' ')); } haxelib(args) { return exec('.', [this.haxelibBin].concat(args).join(' ')); } openfl(command, platform, config, debug=false) { this.log.i('_openfl_ _build_ *%s*', platform); this.activate(); const buildDir = path.join(os.tmpdir(), 'build', config.name); fse.ensureDirSync(buildDir); const projectTemplate = template(fs.readFileSync(path.resolve(__dirname, '..', 'template/project.xml'))); const project = projectTemplate({...config, buildDir: buildDir}); fs.writeFileSync(path.resolve(buildDir, 'project.xml'), project); const args = ['-cwd', buildDir, 'run', 'openfl', command, platform]; if (config.flags.dom) { args.push('-Ddom'); } if (debug) { args.push('-debug'); } const target = path.resolve(buildDir, platform, 'bin'); fse.emptyDirSync(target); const result = { 'android': 'app/build/outputs/apk/*-debug.apk', 'flash': '*.swf', }[platform] || '**/*'; return this.haxelib(args).then(() => { let r = vfs.src(`${target}/${result}`); if (platform === 'android') { r = r.pipe(rename(`${config.meta.filename}_${config.meta.version}.apk`)); } return r; }); } build(platform, config, debug=false) { this.log.i('_build_ *%s*', platform); this.activate(); const buildDir = path.join(os.tmpdir(), 'build', config.name); fse.ensureDirSync(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'); fse.emptyDirSync(target); for (const asset of config.assets) { fse.copySync(asset, path.join(target, asset.split(path.sep).pop())); } return this.haxe(args).then(() => vfs.src(`${target}/**/*`)); } install(packages) { this.activate(); let promise = this.haxelib(['setup', path.join(this.path, 'lib')]); const next = (args) => () => { this.log.i('_haxelib_ _install_ *%s:%s*', args[1], args[2]); return this.haxelib(args); }; if (!Array.isArray(packages)) { packages = Object.entries(packages).map(([k, v]) => ({name: k, version: v})); } for (let pack of packages) { const args = []; let version = null; if (typeof pack === 'string') { args.push('install', pack); } else if (typeof pack === 'object') { version = pack.version; if (version.substr(0, 3) === 'git') { pack.git = version; version = null; } if (pack.git) { args.push('git', pack.name, pack.git); if (pack.branch) args.push(pack.branch); } else { args.push('install', pack.name); if (version) args.push(version); } args.push('--always'); } let path = `${this.path}/lib/${args[1]}`; if (version) { path += `/${version.replace(/\./g, ',')}`; } else if (pack.git) { path += '/git'; } if (!fs.existsSync(path)) { promise = promise.then(next(args)); } } return promise; } upgrade() { let promise = this.haxelib(['setup', path.join(this.path, 'lib')]); promise = promise.then(() => this.haxelib(['upgrade', '--always'])); return promise; } } Haxe.ID = 'haxe'; Haxe.VERSION_3_4_0 = '3.4.0'; Haxe.VERSION_3_4_2 = '3.4.2'; Haxe.VERSION_3_4_3 = '3.4.3'; Haxe.VERSION_3_4_7 = '3.4.7'; Haxe.VERSION_3 = Haxe.VERSION_3_4_7; Haxe.VERSION = Haxe.VERSION_3; module.exports = Haxe;