From 5d391ba9a3ae5284c83ea7d8bdc4b20932eb4a29 Mon Sep 17 00:00:00 2001 From: jhwgh1968 Date: Mon, 10 Feb 2020 22:37:23 -0600 Subject: [PATCH] Created new asbuild utility, run from npm --- bin/asbuild | 10 ++++ bin/asinit | 4 +- cli/asbuild/asbuild.js | 111 ++++++++++++++++++++++++++++++++++++++ cli/asbuild/asbuild.json | 37 +++++++++++++ cli/asbuild/profiles.json | 17 ++++++ package.json | 3 +- 6 files changed, 179 insertions(+), 3 deletions(-) create mode 100755 bin/asbuild create mode 100644 cli/asbuild/asbuild.js create mode 100644 cli/asbuild/asbuild.json create mode 100644 cli/asbuild/profiles.json diff --git a/bin/asbuild b/bin/asbuild new file mode 100755 index 0000000000..ccfba9fda6 --- /dev/null +++ b/bin/asbuild @@ -0,0 +1,10 @@ +#!/usr/bin/env node + +/* tslint:disable */ + +try { require("source-map-support").install(); } catch (e) {} + +const asbuild = module.exports = require("../cli/asbuild/asbuild.js"); +if (/\basbuild$/.test(process.argv[1])) { + process.exitCode = asbuild.main(process.argv.slice(2)); +} diff --git a/bin/asinit b/bin/asinit index 62822ea573..ce0eb1dd37 100755 --- a/bin/asinit +++ b/bin/asinit @@ -224,8 +224,8 @@ function ensureGitignore() { function ensurePackageJson() { console.log("- Making sure that 'package.json' contains the build commands...") const entryPath = path.relative(projectDir, entryFile).replace(/\\/g, "/"); - const buildUntouched = "asc " + entryPath + " -b build/untouched.wasm -t build/untouched.wat --validate --sourceMap --debug"; - const buildOptimized = "asc " + entryPath + " -b build/optimized.wasm -t build/optimized.wat --validate --sourceMap --optimize"; + const buildUntouched = "asbuild --debug --"; + const buildOptimized = "asbuild --release --"; const buildAll = "npm run asbuild:untouched && npm run asbuild:optimized"; if (!fs.existsSync(packageFile)) { fs.writeFileSync(packageFile, JSON.stringify({ diff --git a/cli/asbuild/asbuild.js b/cli/asbuild/asbuild.js new file mode 100644 index 0000000000..b3352c0561 --- /dev/null +++ b/cli/asbuild/asbuild.js @@ -0,0 +1,111 @@ +"use strict"; +/** + * A tool to run asc, suitable for use by NPM or manually. + * + * It wraps the build process by allowing flags to be grouped into profiles. + * + * Run with --help for more information. + * + * @module cli/asbuild + */ + +const util = require("util"); +const execFile = util.promisify(require("child_process").execFile); + +const fs = require("fs"); +const path = require("path"); + +const optionsUtil = require("../util/options"); +exports.options = require("./asbuild.json"); + +const profiles = require("./profiles.json"); + +// Assembles the build directory and profile information into an output wasm file path. +function outputWasmName(profile, options) { + if(profiles[profile] !== undefined) { + return path.join(options.buildDir, profiles[profile].default_name + ".wasm") + } else { + return "" // intentionally cause an asc error due to missing file name + } +} + +// Assembles the build directory and profile information into an output wat file path. +function outputWatName(profile, options) { + if(profiles[profile] !== undefined) { + return path.join(options.buildDir, profiles[profile].default_name + ".wat") + } else { + return "" // intentionally cause an asc error due to missing file name + } +} + +// Gather all the flags and options into an ASC command line, and run the compiler. +function ascRun(profile, argv) { + var execargs = [ + argv.options.entryPath, + "-b", outputWasmName(profile, argv.options), + "-t", outputWatName(profile, argv.options) + ]; + if(profiles[profile] !== undefined) { + profiles[profile].args.forEach(e => execargs.push(e)); + } + argv.trailing.forEach(e => execargs.push(e)); + + return execFile("asc", execargs); +} + +// Nail down directories for the build if the user omitted them. +function cleanUpBuildDirs(argv) { + argv.options.baseDir = path.resolve(argv.options.baseDir); + while (!fs.existsSync(path.join(argv.options.baseDir, "package.json"))) { + argv.options.baseDir = path.normalize(path.join(argv.options.baseDir, "..")); + var p = path.parse(argv.options.baseDir); + if (p.root === p.dir) { + throw new Error("cannot find package.json; please specify --baseDir option"); + } + } + + if(argv.options.buildDir === undefined) { + argv.options.buildDir = path.relative(argv.options.baseDir, + path.join(argv.options.baseDir, "build")); + } + argv.options.assemblyDir = path.join(argv.options.baseDir, "assembly"); + if (fs.existsSync(path.join(argv.options.assemblyDir, "index.ts"))) { + argv.options.entryPath = path.join(argv.options.assemblyDir, "index.ts"); + } else { + argv.options.entryPath = argv.options.assemblyDir; + } + + // NB: asc only accepts relative root paths, hence this trick + process.chdir(argv.options.baseDir); + argv.options.baseDir = path.relative(process.cwd(), argv.options.baseDir); + argv.options.buildDir = path.relative(process.cwd(), argv.options.buildDir); + argv.options.assemblyDir = path.relative(process.cwd(), argv.options.assemblyDir); + argv.options.entryPath = path.relative(process.cwd(), argv.options.entryPath); + + return argv; +} + +// Merge profile information with static options to populate the full list of options of asbuild. +function mergeConfigOptions() { + var config = {}; + Object.keys(exports.options).forEach(k => config[k] = exports.options[k]); + Object.keys(profiles).forEach(k => config[k] = { + description: [ profiles[k].description ], + type: "b", + default: false + }); + return config; +} + +exports.main = async function main(argv) { + var argv = cleanUpBuildDirs(optionsUtil.parse(argv, mergeConfigOptions())); + + if (argv.options.debug && argv.options.release) { + await ascRun("debug", argv) + .then(function() { return ascRun("release", argv) }); + } else if (argv.options.release) { + await ascRun("release", argv); + } else { + await ascRun("debug", argv); + } +} diff --git a/cli/asbuild/asbuild.json b/cli/asbuild/asbuild.json new file mode 100644 index 0000000000..c6c8ebb1f2 --- /dev/null +++ b/cli/asbuild/asbuild.json @@ -0,0 +1,37 @@ +{ + "help": { + "description": "Prints this message and exits.", + "type": "b", + "alias": "h" + }, + "baseDir": { + "description": "Specifies the base directory of input and output files.", + "type": "s", + "default": "." + }, + "outFile": { + "description": "Specifies an output file. File extension indicates format.", + "type": "s", + "alias": "o" + }, + "binaryFile": { + "description": "Specifies the WebAssembly output file (.wasm).", + "type": "s", + "alias": "b" + }, + "textFile": { + "description": "Specifies the text output file (.wat).", + "type": "s", + "alias": "t" + }, + "idlFile": { + "description": "Specifies the interface definition output file (.idl).", + "type": "s", + "alias": "t" + }, + "tsdFile": { + "description": "Specifies the TypeScript definition output file (.tsd).", + "type": "s", + "alias": "t" + } +} diff --git a/cli/asbuild/profiles.json b/cli/asbuild/profiles.json new file mode 100644 index 0000000000..51709d443f --- /dev/null +++ b/cli/asbuild/profiles.json @@ -0,0 +1,17 @@ +{ + "debug": { + "default_name": "untouched", + "args": ["--validate", "--sourceMap", "--debug"], + "description": "builds a dbug wasm file: +debuginfo +assertions -optimizations ++size" + }, + "release": { + "default_name": "optimized", + "args": ["--validate", "--sourceMap", "-O3", "--noAssert"], + "description": "builds an optimized wasm file: -debuginfo -assertions +optimizations +size" + }, + "releasemin": { + "default_name": "optimizedmin", + "args": ["--validate", "--sourceMap", "-O3z", "--noAssert"], + "description": "builds a size-optimized wasm file: -debuginfo -assertions +optimizations -size" + } +} diff --git a/package.json b/package.json index 591c8bf439..b46efefa27 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "types": "index.d.ts", "bin": { "asc": "bin/asc", - "asinit": "bin/asinit" + "asinit": "bin/asinit", + "asbuild": "bin/asbuild" }, "scripts": { "build": "npm run build:bundle && npm run build:dts && npm run build:sdk",