2020-12-23 01:14:52 +03:00
|
|
|
const child_process = require('child_process')
|
2021-11-05 14:51:43 +03:00
|
|
|
const cmd = require('./cmd')
|
|
|
|
const fs = require('fs').promises
|
|
|
|
const fse = require('fs-extra')
|
|
|
|
const fss = require('fs')
|
|
|
|
const unzipper = require('unzipper')
|
|
|
|
const glob = require('glob')
|
|
|
|
const ncp = require('ncp').ncp
|
|
|
|
const os = require('os')
|
|
|
|
const path = require('path')
|
|
|
|
const paths = require('./paths')
|
|
|
|
const prettier = require('prettier')
|
|
|
|
const release = require('./release')
|
|
|
|
const stream = require('stream')
|
|
|
|
const workflow = require('./workflow')
|
|
|
|
const yargs = require('yargs')
|
|
|
|
const zlib = require('zlib')
|
2021-02-02 08:07:43 +03:00
|
|
|
const { promisify } = require('util')
|
|
|
|
const pipe = promisify(stream.pipeline)
|
2020-03-16 05:58:00 +03:00
|
|
|
|
2021-02-02 08:07:43 +03:00
|
|
|
// ==============
|
|
|
|
// === Errors ===
|
|
|
|
// ==============
|
2020-03-16 05:58:00 +03:00
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
process.on('unhandledRejection', error => {
|
|
|
|
throw error
|
|
|
|
})
|
2021-02-02 08:07:43 +03:00
|
|
|
process.chdir(paths.root)
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2020-03-16 05:58:00 +03:00
|
|
|
// ========================
|
|
|
|
// === Global Variables ===
|
|
|
|
// ========================
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2020-04-03 14:18:22 +03:00
|
|
|
/// Arguments passed to cargo build system called from this script. This variable is set to a
|
|
|
|
/// specific value after the command line args get parsed.
|
|
|
|
let cargoArgs = undefined
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
/// Arguments passed to a target binary if any. This variable is set to a specific value after the
|
|
|
|
// command line args get parsed.
|
|
|
|
let targetArgs = undefined
|
2020-03-05 08:25:00 +03:00
|
|
|
|
|
|
|
// =============
|
|
|
|
// === Utils ===
|
|
|
|
// =============
|
|
|
|
|
2021-02-02 08:07:43 +03:00
|
|
|
async function gzip(input, output) {
|
2021-11-05 14:51:43 +03:00
|
|
|
const gzip = zlib.createGzip()
|
|
|
|
const source = fss.createReadStream(input)
|
|
|
|
const destination = fss.createWriteStream(output)
|
|
|
|
await pipe(source, gzip, destination)
|
2021-02-02 08:07:43 +03:00
|
|
|
}
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
/// Copy files and directories.
|
2021-11-05 14:51:43 +03:00
|
|
|
async function copy(src, tgt) {
|
2020-03-05 08:25:00 +03:00
|
|
|
return new Promise((resolve, reject) => {
|
2021-11-05 14:51:43 +03:00
|
|
|
ncp(src, tgt, err => {
|
|
|
|
if (err) {
|
|
|
|
reject(`${err}`)
|
|
|
|
}
|
2020-03-05 08:25:00 +03:00
|
|
|
resolve()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-04-03 14:18:22 +03:00
|
|
|
/// Run the command with the provided args and all args passed to this script after the `--` symbol.
|
2021-11-05 14:51:43 +03:00
|
|
|
async function run_cargo(command, args) {
|
|
|
|
await cmd.run(command, args.concat(cargoArgs))
|
2020-04-03 14:18:22 +03:00
|
|
|
}
|
|
|
|
|
2020-03-05 22:00:47 +03:00
|
|
|
/// Run the command with the provided args and all args passed to this script after the `--` symbol.
|
2021-11-05 14:51:43 +03:00
|
|
|
async function run(command, args) {
|
|
|
|
await cmd.run(command, args)
|
2020-03-05 22:00:47 +03:00
|
|
|
}
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
/// Defines a new command argument builder.
|
|
|
|
function command(docs) {
|
2021-11-05 14:51:43 +03:00
|
|
|
return { docs }
|
2020-03-13 07:10:08 +03:00
|
|
|
}
|
|
|
|
|
2021-01-21 16:52:57 +03:00
|
|
|
/// Build the project manager module, which downloads the project manager binary for the current
|
|
|
|
/// platform.
|
|
|
|
async function build_project_manager() {
|
|
|
|
console.log(`Getting project manager manager.`)
|
2021-11-16 12:04:56 +03:00
|
|
|
await cmd.with_cwd(paths.ide_desktop.lib.projectManager, async () => {
|
2021-11-05 14:51:43 +03:00
|
|
|
await run('npm', ['run-script build'])
|
2021-01-21 16:52:57 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Run the local project manager binary.
|
|
|
|
function run_project_manager() {
|
2021-11-05 14:51:43 +03:00
|
|
|
const bin_path = paths.get_project_manager_path(paths.dist.bin)
|
|
|
|
console.log(`Starting the project manager from "${bin_path}".`)
|
|
|
|
child_process.execFile(bin_path, [], (error, stdout, stderr) => {
|
|
|
|
console.error(stderr)
|
|
|
|
if (error) {
|
|
|
|
throw error
|
|
|
|
}
|
|
|
|
console.log(stdout)
|
|
|
|
console.log(`Project manager running.`)
|
|
|
|
})
|
2021-01-21 16:52:57 +03:00
|
|
|
}
|
2020-03-13 07:10:08 +03:00
|
|
|
|
|
|
|
// ================
|
|
|
|
// === Commands ===
|
|
|
|
// ================
|
|
|
|
|
2021-11-16 12:04:56 +03:00
|
|
|
const DEFAULT_CRATE = 'app/gui'
|
2020-03-13 07:10:08 +03:00
|
|
|
let commands = {}
|
|
|
|
|
2020-03-05 08:25:00 +03:00
|
|
|
// === Clean ===
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
commands.clean = command(`Clean all build artifacts`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.clean.js = async function () {
|
2021-11-16 12:04:56 +03:00
|
|
|
await cmd.with_cwd(paths.ide_desktop.root, async () => {
|
2021-11-05 14:51:43 +03:00
|
|
|
await run('npm', ['run', 'clean'])
|
2020-03-05 08:25:00 +03:00
|
|
|
})
|
2021-02-02 08:07:43 +03:00
|
|
|
try {
|
|
|
|
await fs.unlink(paths.dist.init)
|
|
|
|
await fs.unlink(paths.dist.buildInit)
|
|
|
|
} catch {}
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.clean.rust = async function () {
|
|
|
|
await run_cargo('cargo', ['clean'])
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// === Check ===
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
commands.check = command(`Fast check if project builds (only Rust target)`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.check.rust = async function () {
|
|
|
|
await run_cargo('cargo', ['check'])
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// === Build ===
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
commands.build = command(`Build the sources in release mode`)
|
2020-08-08 09:06:15 +03:00
|
|
|
commands.build.options = {
|
2021-11-05 14:51:43 +03:00
|
|
|
crate: {
|
|
|
|
describe: 'Target crate to build',
|
|
|
|
type: 'string',
|
|
|
|
},
|
2020-08-08 09:06:15 +03:00
|
|
|
}
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.build.js = async function () {
|
2021-02-02 08:07:43 +03:00
|
|
|
await installJsDeps()
|
2020-03-05 08:25:00 +03:00
|
|
|
console.log(`Building JS target.`)
|
2021-11-05 14:51:43 +03:00
|
|
|
await run('npm', ['run', 'build'])
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.build.rust = async function (argv) {
|
|
|
|
let crate = argv.crate || DEFAULT_CRATE
|
2020-08-14 10:23:03 +03:00
|
|
|
let crate_sfx = crate ? ` '${crate}'` : ``
|
|
|
|
console.log(`Building WASM target${crate_sfx}.`)
|
2021-11-05 14:51:43 +03:00
|
|
|
let args = [
|
|
|
|
'build',
|
|
|
|
'--target',
|
|
|
|
'web',
|
|
|
|
'--out-dir',
|
|
|
|
paths.dist.wasm.root,
|
|
|
|
'--out-name',
|
|
|
|
'ide',
|
|
|
|
crate,
|
|
|
|
]
|
|
|
|
if (argv.dev) {
|
|
|
|
args.push('--dev')
|
|
|
|
}
|
2021-12-29 15:44:13 +03:00
|
|
|
if (cargoArgs) {
|
|
|
|
args.push('--')
|
|
|
|
}
|
2021-11-05 14:51:43 +03:00
|
|
|
await run_cargo('wasm-pack', args)
|
2020-03-16 05:58:00 +03:00
|
|
|
await patch_file(paths.dist.wasm.glue, js_workaround_patcher)
|
|
|
|
await fs.rename(paths.dist.wasm.mainRaw, paths.dist.wasm.main)
|
|
|
|
if (!argv.dev) {
|
|
|
|
// TODO: Enable after updating wasm-pack
|
|
|
|
// https://github.com/rustwasm/wasm-pack/issues/696
|
|
|
|
// console.log('Optimizing the WASM binary.')
|
|
|
|
// await cmd.run('npx',['wasm-opt','-O3','-o',paths.dist.wasm.mainOpt,paths.dist.wasm.main])
|
|
|
|
console.log('Minimizing the WASM binary.')
|
2021-11-05 14:51:43 +03:00
|
|
|
await gzip(paths.dist.wasm.main, paths.dist.wasm.mainOptGz) // TODO main -> mainOpt
|
2020-03-16 05:58:00 +03:00
|
|
|
|
|
|
|
console.log('Checking the resulting WASM size.')
|
|
|
|
let stats = fss.statSync(paths.dist.wasm.mainOptGz)
|
2021-11-05 14:51:43 +03:00
|
|
|
let limit = 4.6
|
|
|
|
let size = Math.round((100 * stats.size) / 1024 / 1024) / 100
|
2020-07-03 11:56:40 +03:00
|
|
|
if (size > limit) {
|
2021-11-05 14:51:43 +03:00
|
|
|
throw `Output file size exceeds the limit (${size}MB > ${limit}MB).`
|
2020-03-16 05:58:00 +03:00
|
|
|
}
|
|
|
|
}
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Workaround fix by wdanilo, see: https://github.com/rustwasm/wasm-pack/issues/790
|
|
|
|
function js_workaround_patcher(code) {
|
2021-11-05 14:51:43 +03:00
|
|
|
code = code.replace(/if \(\(typeof URL.*}\);/gs, 'return imports')
|
|
|
|
code = code.replace(/if \(typeof module.*let result/gs, 'let result')
|
|
|
|
code = code.replace(/export default init;/gs, 'export default init')
|
|
|
|
code += '\nexport function after_load(w,m) { wasm = w; init.__wbindgen_wasm_module = m;}'
|
2020-03-05 08:25:00 +03:00
|
|
|
return code
|
|
|
|
}
|
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
async function patch_file(path, patcher) {
|
|
|
|
let code_to_patch = await fs.readFile(path, 'utf8')
|
|
|
|
let patched_code = patcher(code_to_patch)
|
|
|
|
await fs.writeFile(path, patched_code)
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
// === Start ===
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
commands.start = command(`Build and start desktop client`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.start.rust = async function (argv) {
|
|
|
|
let argv2 = Object.assign({}, argv, { dev: true })
|
|
|
|
await commands.build.rust(argv2)
|
2020-03-13 07:10:08 +03:00
|
|
|
}
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2021-01-21 16:52:57 +03:00
|
|
|
commands.start.js = async function (argv) {
|
2021-02-02 08:07:43 +03:00
|
|
|
await installJsDeps()
|
2021-01-21 16:52:57 +03:00
|
|
|
console.log(`Building JS target.` + argv)
|
2021-04-30 00:21:18 +03:00
|
|
|
// The backend path is being prepended here, as appending would be incorrect.
|
|
|
|
// That is because `targetArgs` might include `-- …` and appended args could
|
|
|
|
// end up being passed to the spawned backend process.
|
2021-11-05 14:51:43 +03:00
|
|
|
const args = ['--backend-path', paths.get_project_manager_path(paths.dist.bin)].concat(
|
|
|
|
targetArgs
|
|
|
|
)
|
|
|
|
if (argv.dev) {
|
|
|
|
args.push('--dev')
|
|
|
|
}
|
2021-11-16 12:04:56 +03:00
|
|
|
await cmd.with_cwd(paths.ide_desktop.root, async () => {
|
2021-01-21 16:52:57 +03:00
|
|
|
await run('npm', ['run', 'start', '--'].concat(args))
|
2020-03-13 07:10:08 +03:00
|
|
|
})
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
// === Test ===
|
|
|
|
|
|
|
|
commands.test = command(`Run test suites`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.test.rust = async function (argv) {
|
2020-03-16 13:16:16 +03:00
|
|
|
if (argv.native) {
|
|
|
|
console.log(`Running Rust test suite.`)
|
2021-11-05 14:51:43 +03:00
|
|
|
await run_cargo('cargo', ['test'])
|
2020-03-16 13:16:16 +03:00
|
|
|
}
|
2020-03-13 07:10:08 +03:00
|
|
|
|
2020-03-16 13:16:16 +03:00
|
|
|
if (argv.wasm) {
|
|
|
|
console.log(`Running Rust WASM test suite.`)
|
2021-11-05 14:51:43 +03:00
|
|
|
let args = [
|
|
|
|
'run',
|
2021-11-16 12:04:56 +03:00
|
|
|
'--manifest-path=build/rust-scripts/Cargo.toml',
|
2021-11-05 14:51:43 +03:00
|
|
|
'--bin',
|
|
|
|
'test_all',
|
|
|
|
'--',
|
|
|
|
'--headless',
|
|
|
|
'--chrome',
|
|
|
|
]
|
|
|
|
await run_cargo('cargo', args)
|
2020-03-16 13:16:16 +03:00
|
|
|
}
|
2020-03-13 07:10:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// === Lint ===
|
|
|
|
|
|
|
|
commands.lint = command(`Lint the codebase`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.lint.rust = async function () {
|
|
|
|
await run_cargo('cargo', ['clippy', '--', '-D', 'warnings'])
|
|
|
|
await run_cargo('cargo', ['fmt', '--', '--check'])
|
2020-03-13 07:10:08 +03:00
|
|
|
}
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2020-11-30 14:38:35 +03:00
|
|
|
// === TomlFmt ===
|
|
|
|
|
|
|
|
commands['toml-fmt'] = command(`Lint the codebase`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands['toml-fmt'].rust = async function () {
|
|
|
|
console.log('Looking for all TOML files.')
|
2021-11-16 12:04:56 +03:00
|
|
|
let files = glob.sync(paths.root + '/**/*.toml', { cwd: paths.root })
|
2020-11-30 14:38:35 +03:00
|
|
|
console.log(`Found ${files.length} entries. Running auto-formatter.`)
|
|
|
|
for (let file of files) {
|
|
|
|
console.log(` Formatting '${file}'.`)
|
2021-11-05 14:51:43 +03:00
|
|
|
let text = fss.readFileSync(file, 'utf8')
|
|
|
|
let out = prettier.format(text, { parser: 'toml' })
|
|
|
|
fss.writeFileSync(file, out)
|
2020-11-30 14:38:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-05 08:25:00 +03:00
|
|
|
// === Watch ===
|
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.watch = command(`Start a file-watch utility and run interactive mode`)
|
|
|
|
commands.watch.options = Object.assign({}, commands.build.options)
|
2021-03-31 17:31:46 +03:00
|
|
|
commands.watch.parallel = false
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.watch.common = async function (argv) {
|
2021-03-31 17:31:46 +03:00
|
|
|
argv.dev = true
|
|
|
|
|
|
|
|
// Init JS build and project manager.
|
|
|
|
|
|
|
|
await installJsDeps()
|
2021-01-21 16:52:57 +03:00
|
|
|
if (argv.backend !== 'false') {
|
2021-03-31 17:31:46 +03:00
|
|
|
await build_project_manager().then(run_project_manager)
|
2021-01-21 16:52:57 +03:00
|
|
|
}
|
2020-12-23 01:14:52 +03:00
|
|
|
|
2021-03-31 17:31:46 +03:00
|
|
|
// Run build processes.
|
|
|
|
|
2021-11-16 12:04:56 +03:00
|
|
|
await cmd.with_cwd(paths.root, async () => {
|
2021-11-05 14:51:43 +03:00
|
|
|
return commands.build.rust(argv)
|
2020-03-16 05:58:00 +03:00
|
|
|
})
|
2021-11-16 12:04:56 +03:00
|
|
|
await cmd.with_cwd(paths.ide_desktop.root, async () => {
|
2021-08-30 14:57:30 +03:00
|
|
|
// Among other things, this will call the build script of the project-manager package. But
|
|
|
|
// this is unnecessary because that script is already called by `build_project_manager`
|
2021-11-05 14:51:43 +03:00
|
|
|
// above.
|
|
|
|
return commands.build.js(argv)
|
2020-03-05 08:25:00 +03:00
|
|
|
})
|
2021-03-31 17:31:46 +03:00
|
|
|
|
|
|
|
// Run watch processes.
|
|
|
|
|
2021-11-16 12:04:56 +03:00
|
|
|
const rust_process = cmd.with_cwd(paths.root, async () => {
|
2021-03-31 17:31:46 +03:00
|
|
|
let build_args = []
|
|
|
|
if (argv.crate !== undefined) {
|
|
|
|
build_args.push(`--crate=${argv.crate}`)
|
|
|
|
}
|
|
|
|
build_args = build_args.join(' ')
|
|
|
|
const target =
|
2021-11-05 14:51:43 +03:00
|
|
|
'"' +
|
|
|
|
`node ${paths.script.main} build --skip-version-validation --no-js --dev ${build_args} -- ` +
|
|
|
|
cargoArgs.join(' ') +
|
|
|
|
'"'
|
2021-03-31 17:31:46 +03:00
|
|
|
let args = ['watch', '-s', `${target}`]
|
2021-11-05 14:51:43 +03:00
|
|
|
return cmd.run('cargo', args)
|
2021-03-31 17:31:46 +03:00
|
|
|
})
|
2021-11-16 12:04:56 +03:00
|
|
|
const js_process = cmd.with_cwd(paths.ide_desktop.root, async () => {
|
2021-11-05 14:51:43 +03:00
|
|
|
return run('npm', ['run', 'watch'])
|
2021-03-31 17:31:46 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
await rust_process
|
|
|
|
await js_process
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// === Dist ===
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
commands.dist = command(`Build the sources and create distribution packages`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.dist.rust = async function (argv) {
|
2020-03-16 05:58:00 +03:00
|
|
|
await commands.build.rust(argv)
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
commands.dist.js = async function () {
|
2021-02-02 08:07:43 +03:00
|
|
|
await installJsDeps()
|
2021-11-16 12:04:56 +03:00
|
|
|
await cmd.with_cwd(paths.ide_desktop.root, async () => {
|
2021-11-05 14:51:43 +03:00
|
|
|
await run('npm', ['run', 'dist'])
|
2020-03-05 08:25:00 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-02-02 08:07:43 +03:00
|
|
|
// === CI Gen ===
|
|
|
|
|
|
|
|
/// The command is used by CI to generate the file `CURRENT_RELEASE_CHANGELOG.json`, which contains
|
|
|
|
/// information about the newest release. It is then used by CI to generate version and description
|
|
|
|
/// of the product release.
|
|
|
|
commands['ci-gen'] = command(`Generate CI build related files`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands['ci-gen'].rust = async function (argv) {
|
|
|
|
let entry = release.changelog().newestEntry()
|
|
|
|
let body = entry.body
|
|
|
|
let version = entry.version.toString()
|
2021-02-02 08:07:43 +03:00
|
|
|
let prerelease = entry.isPrerelease()
|
2021-11-05 14:51:43 +03:00
|
|
|
let obj = { version, body, prerelease }
|
|
|
|
let json = JSON.stringify(obj)
|
|
|
|
fss.writeFileSync(path.join(paths.root, 'CURRENT_RELEASE_CHANGELOG.json'), json)
|
2021-02-02 08:07:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Asserts whether the current version of the package (newest in CHANGELOG.md) is unstable.
|
|
|
|
commands['assert-version-unstable'] = command(`Assert the current version is unstable`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands['assert-version-unstable'].rust = async function (argv) {
|
2021-02-02 08:07:43 +03:00
|
|
|
let entry = release.changelog().newestEntry().assert_is_unstable()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Asserts whether the current version of the package (newest in CHANGELOG.md) is stable.
|
|
|
|
commands['assert-version-stable'] = command(`Assert the current version is stable`)
|
2021-11-05 14:51:43 +03:00
|
|
|
commands['assert-version-stable'].rust = async function (argv) {
|
2021-02-02 08:07:43 +03:00
|
|
|
let entry = release.changelog().newestEntry().assert_is_stable()
|
|
|
|
}
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
// ===========================
|
|
|
|
// === Command Line Parser ===
|
|
|
|
// ===========================
|
|
|
|
|
|
|
|
let usage = `run command [options]
|
|
|
|
|
2020-04-03 14:18:22 +03:00
|
|
|
All arguments after '--' will be passed to cargo build system.
|
2020-03-13 07:10:08 +03:00
|
|
|
All arguments after second '--' will be passed to target executable if any.
|
2020-04-03 14:18:22 +03:00
|
|
|
For example, 'run start -- --dev -- --debug-scene shapes' will pass '--dev' to cargo \
|
|
|
|
and '--debug-scene shapes' to the output binary.`
|
2020-03-13 07:10:08 +03:00
|
|
|
|
|
|
|
let optParser = yargs
|
2021-11-05 14:51:43 +03:00
|
|
|
.scriptName('')
|
2020-03-13 07:10:08 +03:00
|
|
|
.usage(usage)
|
|
|
|
.help()
|
2021-11-05 14:51:43 +03:00
|
|
|
.parserConfiguration({ 'populate--': true })
|
2020-03-13 07:10:08 +03:00
|
|
|
.demandCommand()
|
|
|
|
|
|
|
|
optParser.options('rust', {
|
2021-11-05 14:51:43 +03:00
|
|
|
describe: 'Run the Rust target',
|
|
|
|
type: 'bool',
|
|
|
|
default: true,
|
2020-03-13 07:10:08 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
optParser.options('js', {
|
2021-11-05 14:51:43 +03:00
|
|
|
describe: 'Run the JavaScript target',
|
|
|
|
type: 'bool',
|
|
|
|
default: true,
|
2020-03-13 07:10:08 +03:00
|
|
|
})
|
|
|
|
|
2020-03-16 05:58:00 +03:00
|
|
|
optParser.options('release', {
|
2021-11-05 14:51:43 +03:00
|
|
|
describe: 'Enable all optimizations',
|
|
|
|
type: 'bool',
|
2020-03-16 05:58:00 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
optParser.options('dev', {
|
2021-11-05 14:51:43 +03:00
|
|
|
describe: 'Optimize for fast builds',
|
|
|
|
type: 'bool',
|
2020-03-16 05:58:00 +03:00
|
|
|
})
|
|
|
|
|
2020-12-23 01:14:52 +03:00
|
|
|
optParser.options('target', {
|
|
|
|
describe:
|
|
|
|
'Set the build target. Defaults to the current platform. ' +
|
|
|
|
'Valid values are: "linux" "macos" and "win"',
|
|
|
|
type: 'string',
|
|
|
|
})
|
|
|
|
|
2021-01-21 16:52:57 +03:00
|
|
|
optParser.options('backend', {
|
|
|
|
describe: 'Start the backend process automatically [true]',
|
|
|
|
type: 'bool',
|
|
|
|
default: true,
|
|
|
|
})
|
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
let commandList = Object.keys(commands)
|
|
|
|
commandList.sort()
|
|
|
|
for (let command of commandList) {
|
|
|
|
let config = commands[command]
|
2021-11-05 14:51:43 +03:00
|
|
|
optParser.command(command, config.docs, args => {
|
2020-08-08 09:06:15 +03:00
|
|
|
for (let option in config.options) {
|
2021-11-05 14:51:43 +03:00
|
|
|
args.options(option, config.options[option])
|
2020-08-08 09:06:15 +03:00
|
|
|
}
|
2020-08-14 10:23:03 +03:00
|
|
|
for (let arg in config.args) {
|
2021-11-05 14:51:43 +03:00
|
|
|
args.positional(arg, config.args[arg])
|
2020-08-14 10:23:03 +03:00
|
|
|
}
|
2020-03-16 13:16:16 +03:00
|
|
|
args.options('native', {
|
2021-11-05 14:51:43 +03:00
|
|
|
describe: 'Run native tests',
|
|
|
|
type: 'bool',
|
|
|
|
default: true,
|
2020-03-16 13:16:16 +03:00
|
|
|
})
|
|
|
|
args.options('wasm', {
|
2021-11-05 14:51:43 +03:00
|
|
|
describe: 'Run WASM tests',
|
|
|
|
type: 'bool',
|
|
|
|
default: true,
|
2020-03-16 13:16:16 +03:00
|
|
|
})
|
|
|
|
})
|
2020-03-16 05:58:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// ======================
|
|
|
|
// === Package Config ===
|
|
|
|
// ======================
|
|
|
|
|
|
|
|
function defaultConfig() {
|
|
|
|
return {
|
2021-02-02 08:07:43 +03:00
|
|
|
version: `${release.currentVersion()}`,
|
2020-03-16 05:58:00 +03:00
|
|
|
author: {
|
2021-11-05 14:51:43 +03:00
|
|
|
name: 'Enso Team',
|
|
|
|
email: 'contact@enso.org',
|
2020-03-16 05:58:00 +03:00
|
|
|
},
|
2021-11-05 14:51:43 +03:00
|
|
|
homepage: 'https://github.com/enso-org/ide',
|
2020-03-16 05:58:00 +03:00
|
|
|
repository: {
|
2021-11-05 14:51:43 +03:00
|
|
|
type: 'git',
|
|
|
|
url: 'git@github.com:enso-org/ide.git',
|
2020-03-16 05:58:00 +03:00
|
|
|
},
|
|
|
|
bugs: {
|
2021-11-05 14:51:43 +03:00
|
|
|
url: 'https://github.com/enso-org/ide/issues',
|
2020-03-16 05:58:00 +03:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function processPackageConfigs() {
|
|
|
|
let files = []
|
2021-11-16 12:04:56 +03:00
|
|
|
files = files.concat(glob.sync(paths.ide_desktop.root + '/package.js', { cwd: paths.root }))
|
|
|
|
files = files.concat(
|
|
|
|
glob.sync(paths.ide_desktop.root + '/lib/*/package.js', { cwd: paths.root })
|
|
|
|
)
|
2020-03-16 05:58:00 +03:00
|
|
|
for (file of files) {
|
|
|
|
let dirPath = path.dirname(file)
|
2021-11-05 14:51:43 +03:00
|
|
|
let outPath = path.join(dirPath, 'package.json')
|
|
|
|
let src = await fs.readFile(file, 'utf8')
|
|
|
|
let modSrc = `module = {}\n${src}\nreturn module.exports`
|
|
|
|
let fn = new Function('require', 'paths', modSrc)
|
|
|
|
let mod = fn(require, paths)
|
|
|
|
let config = mod.config
|
|
|
|
if (!config) {
|
|
|
|
throw `Package config '${file}' do not export 'module.config'.`
|
|
|
|
}
|
|
|
|
config = Object.assign(defaultConfig(), config)
|
|
|
|
fs.writeFile(outPath, JSON.stringify(config, undefined, 4))
|
2020-03-16 05:58:00 +03:00
|
|
|
}
|
2020-03-13 07:10:08 +03:00
|
|
|
}
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2020-03-13 07:10:08 +03:00
|
|
|
// ============
|
|
|
|
// === Main ===
|
|
|
|
// ============
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
async function updateBuildVersion(argv) {
|
|
|
|
const target = get_target_platform(argv)
|
|
|
|
let config = {}
|
2021-02-02 08:07:43 +03:00
|
|
|
let configPath = paths.dist.buildInfo
|
2021-11-05 14:51:43 +03:00
|
|
|
let exists = fss.existsSync(configPath)
|
|
|
|
if (exists) {
|
2020-03-13 07:10:08 +03:00
|
|
|
let configFile = await fs.readFile(configPath)
|
2021-11-05 14:51:43 +03:00
|
|
|
config = JSON.parse(configFile)
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
2020-12-23 01:14:52 +03:00
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
let commitHashCmd = await cmd.run_read('git', ['rev-parse', '--short', 'HEAD'])
|
|
|
|
let commitHash = commitHashCmd.trim()
|
2020-12-23 01:14:52 +03:00
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
if (config.buildVersion !== commitHash || config.target !== target) {
|
2020-12-23 01:14:52 +03:00
|
|
|
config.target = target
|
2020-03-13 07:10:08 +03:00
|
|
|
config.buildVersion = commitHash
|
2020-12-23 01:14:52 +03:00
|
|
|
await fs.mkdir(paths.dist.root, { recursive: true })
|
|
|
|
await fs.writeFile(configPath, JSON.stringify(config, undefined, 2))
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
2020-03-13 07:10:08 +03:00
|
|
|
}
|
2020-03-05 08:25:00 +03:00
|
|
|
|
2020-03-16 05:58:00 +03:00
|
|
|
async function installJsDeps() {
|
|
|
|
let initialized = fss.existsSync(paths.dist.init)
|
|
|
|
if (!initialized) {
|
2021-08-06 19:56:53 +03:00
|
|
|
console.log('Downloading binary assets.')
|
|
|
|
await downloadJsAssets()
|
2020-12-23 01:14:52 +03:00
|
|
|
console.log('Installing application dependencies.')
|
2021-11-16 12:04:56 +03:00
|
|
|
await cmd.with_cwd(paths.ide_desktop.root, async () => {
|
2021-11-05 14:51:43 +03:00
|
|
|
await cmd.run('npm', ['run', 'install'])
|
2020-03-16 05:58:00 +03:00
|
|
|
})
|
2021-11-05 14:51:43 +03:00
|
|
|
await fs.mkdir(paths.dist.root, { recursive: true })
|
|
|
|
let handle = await fs.open(paths.dist.init, 'w')
|
2021-02-02 08:07:43 +03:00
|
|
|
await handle.close()
|
2020-03-16 05:58:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-06 19:56:53 +03:00
|
|
|
async function downloadJsAssets() {
|
|
|
|
const workdir = path.join(paths.root, '.assets-temp')
|
2021-11-05 14:51:43 +03:00
|
|
|
await fs.mkdir(workdir, { recursive: true })
|
2021-08-06 19:56:53 +03:00
|
|
|
const ideAssetsMainZip = 'ide-assets-main.zip'
|
2021-08-09 18:35:02 +03:00
|
|
|
const ideAssetsUrl = `https://github.com/enso-org/ide-assets/archive/refs/heads/main.zip`
|
2021-08-06 19:56:53 +03:00
|
|
|
const unzippedAssets = path.join(workdir, 'ide-assets-main', 'content', 'assets')
|
2021-11-16 12:04:56 +03:00
|
|
|
const jsLibAssets = path.join(paths.ide_desktop.lib.content, 'assets')
|
2021-08-06 19:56:53 +03:00
|
|
|
await cmd.with_cwd(workdir, async () => {
|
|
|
|
await cmd.run('curl', [
|
|
|
|
'--retry',
|
|
|
|
'4',
|
|
|
|
'--retry-connrefused',
|
|
|
|
'-fsSL',
|
|
|
|
'-o',
|
|
|
|
ideAssetsMainZip,
|
2021-08-09 18:35:02 +03:00
|
|
|
ideAssetsUrl,
|
2021-08-06 19:56:53 +03:00
|
|
|
])
|
|
|
|
})
|
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
const assetsArchive = await unzipper.Open.file(path.join(workdir, ideAssetsMainZip))
|
|
|
|
await assetsArchive.extract({ path: workdir })
|
|
|
|
await fse.copy(unzippedAssets, jsLibAssets)
|
2021-08-09 18:35:02 +03:00
|
|
|
await fse.remove(workdir)
|
2021-08-06 19:56:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async function runCommand(command, argv) {
|
2020-04-03 14:18:22 +03:00
|
|
|
let config = commands[command]
|
2021-11-05 14:51:43 +03:00
|
|
|
cargoArgs = argv['--']
|
2020-11-30 14:38:35 +03:00
|
|
|
if (config === undefined) {
|
|
|
|
console.error(`Invalid command '${command}'.`)
|
|
|
|
return
|
|
|
|
}
|
2021-11-05 14:51:43 +03:00
|
|
|
if (cargoArgs === undefined) {
|
|
|
|
cargoArgs = []
|
|
|
|
}
|
2020-04-03 14:18:22 +03:00
|
|
|
let index = cargoArgs.indexOf('--')
|
2020-03-16 05:58:00 +03:00
|
|
|
if (index == -1) {
|
|
|
|
targetArgs = []
|
2021-11-05 14:51:43 +03:00
|
|
|
} else {
|
2020-04-03 14:18:22 +03:00
|
|
|
targetArgs = cargoArgs.slice(index + 1)
|
2021-11-05 14:51:43 +03:00
|
|
|
cargoArgs = cargoArgs.slice(0, index)
|
2020-03-16 05:58:00 +03:00
|
|
|
}
|
|
|
|
let runner = async function () {
|
2021-03-31 17:31:46 +03:00
|
|
|
let do_common = config.common
|
2021-11-05 14:51:43 +03:00
|
|
|
let do_rust = argv.rust && config.rust
|
|
|
|
let do_js = argv.js && config.js
|
2021-03-31 17:31:46 +03:00
|
|
|
|
|
|
|
let commonCmd = () => cmd.with_cwd(paths.root, async () => await config.common(argv))
|
2021-11-16 12:04:56 +03:00
|
|
|
let rustCmd = () => cmd.with_cwd(paths.root, async () => await config.rust(argv))
|
|
|
|
let jsCmd = () => cmd.with_cwd(paths.ide_desktop.root, async () => await config.js(argv))
|
2021-11-05 14:51:43 +03:00
|
|
|
if (config.parallel) {
|
2020-03-16 05:58:00 +03:00
|
|
|
let promises = []
|
2021-11-05 14:51:43 +03:00
|
|
|
if (do_common) {
|
|
|
|
promises.push(commonCmd())
|
|
|
|
}
|
|
|
|
if (do_rust) {
|
|
|
|
promises.push(rustCmd())
|
|
|
|
}
|
|
|
|
if (do_js) {
|
|
|
|
promises.push(jsCmd())
|
|
|
|
}
|
2020-03-16 05:58:00 +03:00
|
|
|
await Promise.all(promises)
|
|
|
|
} else {
|
2021-11-05 14:51:43 +03:00
|
|
|
if (do_common) {
|
|
|
|
await commonCmd()
|
|
|
|
}
|
|
|
|
if (do_rust) {
|
|
|
|
await rustCmd()
|
|
|
|
}
|
|
|
|
if (do_js) {
|
|
|
|
await jsCmd()
|
|
|
|
}
|
2020-03-16 05:58:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cmd.section(command)
|
|
|
|
runner()
|
|
|
|
}
|
|
|
|
|
2020-12-23 01:14:52 +03:00
|
|
|
function get_target_platform(argv) {
|
|
|
|
let target = argv.target
|
|
|
|
if (target === undefined) {
|
|
|
|
const local_platform = os.platform()
|
|
|
|
switch (local_platform) {
|
|
|
|
case 'darwin':
|
|
|
|
return 'macos'
|
|
|
|
case 'win32':
|
|
|
|
return 'win'
|
|
|
|
default:
|
|
|
|
return local_platform
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return target
|
|
|
|
}
|
|
|
|
|
2021-11-05 14:51:43 +03:00
|
|
|
async function main() {
|
2020-12-23 01:14:52 +03:00
|
|
|
let argv = optParser.parse()
|
|
|
|
await updateBuildVersion(argv)
|
2020-03-16 05:58:00 +03:00
|
|
|
await processPackageConfigs()
|
2021-02-02 08:07:43 +03:00
|
|
|
workflow.generate()
|
2020-03-16 05:58:00 +03:00
|
|
|
let command = argv._[0]
|
2021-11-05 14:51:43 +03:00
|
|
|
await runCommand(command, argv)
|
2020-03-05 08:25:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
main()
|