// Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The SFC licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. 'use strict' const fs = require('node:fs') const path = require('node:path') const { spawn } = require('node:child_process') const PROJECT_ROOT = path.normalize(path.join(__dirname, '../../../..')) const WORKSPACE_FILE = path.join(PROJECT_ROOT, 'WORKSPACE') function isDevMode() { return fs.existsSync(WORKSPACE_FILE) } function checkIsDevMode() { if (!isDevMode()) { throw Error('Cannot execute build; not running in dev mode') } } /** * Targets that have been previously built. * @type {!Object} */ let builtTargets = {} /** * @param {!Array.} targets The targets to build. * @throws {Error} If not running in dev mode. * @constructor */ const Build = function (targets) { checkIsDevMode() this.targets_ = targets } /** @private {boolean} */ Build.prototype.cacheResults_ = false /** * Configures this build to only execute if it has not previously been * run during the life of the current process. * @return {!Build} A self reference. */ Build.prototype.onlyOnce = function () { this.cacheResults_ = true return this } /** * Executes the build. * @return {!Promise} A promise that will be resolved when * the build has completed. * @throws {Error} If no targets were specified. */ Build.prototype.go = function () { let targets = this.targets_ if (!targets.length) { throw Error('No targets specified') } // Filter out cached results. if (this.cacheResults_) { targets = targets.filter(function (target) { return !Object.prototype.hasOwnProperty.call(builtTargets, target) }) if (!targets.length) { return Promise.resolve() } } console.log('\nBuilding', targets.join(' '), '...') let cmd, args = targets if (process.platform === 'win32') { cmd = 'cmd.exe' args.unshift('/c', path.join(PROJECT_ROOT, 'go.bat')) } else { cmd = path.join(PROJECT_ROOT, 'go') } return new Promise((resolve, reject) => { spawn(cmd, args, { cwd: PROJECT_ROOT, env: process.env, stdio: ['ignore', process.stdout, process.stderr], }).on('exit', function (code, signal) { if (code === 0) { targets.forEach(function (target) { builtTargets[target] = 1 }) return resolve() } let msg = 'Unable to build artifacts' if (code) { // May be null. msg += '; code=' + code } if (signal) { msg += '; signal=' + signal } reject(Error(msg)) }) }) } // PUBLIC API exports.isDevMode = isDevMode /** * Creates a build of the listed targets. * @param {...string} var_args The targets to build. * @return {!Build} The new build. * @throws {Error} If not running in dev mode. */ exports.of = function (_) { let targets = Array.prototype.slice.call(arguments, 0) return new Build(targets) } /** * @return {string} Absolute path of the project's root directory. * @throws {Error} If not running in dev mode. */ exports.projectRoot = function () { return PROJECT_ROOT }