const path = require('path') const spawnSync = require('child_process').spawnSync const config = require('./config') const fs = require('fs-extra') const autoGeneratedBraveToChromiumMapping = Object.assign({}, require('./l10nUtil').autoGeneratedBraveToChromiumMapping) const runGClient = (args, options = {}) => { if (config.gClientVerbose) args.push('--verbose') options.cwd = options.cwd || config.rootDir options = mergeWithDefault(options) options.env.GCLIENT_FILE = config.gClientFile util.run('gclient', args, options) } const mergeWithDefault = (options) => { return Object.assign({}, config.defaultOptions, options) } const util = { run: (cmd, args = [], options = {}) => { console.log(cmd, args.join(' ')) const continueOnFail = options.continueOnFail delete options.continueOnFail const prog = spawnSync(cmd, args, options) if (prog.status !== 0) { if (!continueOnFail) { console.log(prog.stdout && prog.stdout.toString()) console.error(prog.stderr && prog.stderr.toString()) process.exit(1) } } return prog }, buildGClientConfig: () => { function replacer(key, value) { return value; } let solutions = config.projectNames.filter((projectName) => config.projects[projectName].ref).map((projectName) => { let project = config.projects[projectName] return { managed: "%False%", name: project.gclientName, url: project.url, custom_deps: project.custom_deps } }) const out = 'solutions = ' + JSON.stringify(solutions, replacer, 2) .replace(/"%None%"/g, "None") .replace(/"%False%"/g, "False") fs.writeFileSync(config.defaultGClientFile, out) }, updateBranding: () => { console.log('update branding...') const chromeComponentsDir = path.join(config.srcDir, 'components') const braveComponentsDir = path.join(config.projects['brave-core'].dir, 'components') const chromeAppDir = path.join(config.srcDir, 'chrome', 'app') const braveAppDir = path.join(config.projects['brave-core'].dir, 'app') const chromeResourcesDir = path.join(config.srcDir, 'chrome', 'browser', 'resources') const braveResourcesDir = path.join(config.projects['brave-core'].dir, 'browser', 'resources') const chromeBrowserDir = path.join(config.srcDir, 'chrome', 'browser') const braveBrowserDir = path.join(config.projects['brave-core'].dir, 'browser') const braveAppVectorIconsDir = path.join(config.projects['brave-core'].dir, 'vector_icons', 'chrome', 'app') // The following 3 entries we map to the same name, not the chromium equivalent name for copying back autoGeneratedBraveToChromiumMapping[path.join(braveAppDir, 'brave_strings.grd')] = path.join(chromeAppDir, 'brave_strings.grd') autoGeneratedBraveToChromiumMapping[path.join(braveAppDir, 'settings_brave_strings.grdp')] = path.join(chromeAppDir, 'settings_brave_strings.grdp') autoGeneratedBraveToChromiumMapping[path.join(braveAppDir, 'components_brave_strings.grd')] = path.join(config.srcDir, 'components', 'components_brave_strings.grd') // Copy each grd back to Chromium src dir Object.entries(autoGeneratedBraveToChromiumMapping).forEach(([bravePath, chromiumPath]) => fs.copySync(bravePath, chromiumPath)) // Copy xtb files for: // brave/app/resources/chromium_strings*.xtb // brave/app/strings/components_chromium_strings*.xtb // brave/app/resources/generated_resoruces*.xtb fs.copySync(path.join(braveAppDir, 'resources'), path.join(chromeAppDir, 'resources')) fs.copySync(path.join(braveAppDir, 'strings'), path.join(chromeComponentsDir, 'strings')) fs.copySync(path.join(braveAppDir, 'theme', 'brave'), path.join(chromeAppDir, 'theme', 'brave')) fs.copySync(path.join(braveAppDir, 'theme', 'default_100_percent', 'brave'), path.join(chromeAppDir, 'theme', 'default_100_percent', 'brave')) fs.copySync(path.join(braveAppDir, 'theme', 'default_200_percent', 'brave'), path.join(chromeAppDir, 'theme', 'default_200_percent', 'brave')) // By overwriting, we don't need to modify some grd files. fs.copySync(path.join(braveAppDir, 'theme', 'brave'), path.join(chromeAppDir, 'theme', 'chromium')) fs.copySync(path.join(braveAppDir, 'theme', 'default_100_percent', 'brave'), path.join(chromeAppDir, 'theme', 'default_100_percent', 'chromium')) fs.copySync(path.join(braveAppDir, 'theme', 'default_200_percent', 'brave'), path.join(chromeAppDir, 'theme', 'default_200_percent', 'chromium')) fs.copySync(path.join(braveComponentsDir, 'resources', 'default_100_percent', 'brave'), path.join(chromeComponentsDir, 'resources', 'default_100_percent', 'chromium')) fs.copySync(path.join(braveComponentsDir, 'resources', 'default_200_percent', 'brave'), path.join(chromeComponentsDir, 'resources', 'default_200_percent', 'chromium')) fs.copySync(path.join(braveAppVectorIconsDir, 'vector_icons', 'brave'), path.join(chromeAppDir, 'vector_icons', 'brave')) fs.copySync(path.join(braveResourcesDir, 'settings', 'brave_page_visibility.js'), path.join(chromeResourcesDir, 'settings', 'brave_page_visibility.js')) }, // Chromium compares pre-installed midl files and generated midl files from IDL during the build to check integrity. // Generated files during the build time and upstream pre-installed files are different because we use different IDL file. // So, we should copy our pre-installed files to overwrite upstream pre-installed files. // After checking, pre-installed files are copied to gen dir and they are used to compile. // So, this copying in every build doesn't affect compile performance. updateOmahaMidlFiles: () => { console.log('update omaha midl files...') const srcDir = path.join(config.projects['brave-core'].dir, 'win_build_output', 'midl', 'google_update') const dstDir = path.join(config.srcDir, 'third_party', 'win_build_output', 'midl', 'google_update') fs.copySync(srcDir, dstDir) }, buildTarget: (options = config.defaultOptions) => { console.log('building ' + config.buildTarget + '...') if (process.platform === 'win32') util.updateOmahaMidlFiles() const args = util.buildArgsToString(config.buildArgs()) util.run('gn', ['gen', config.outputDir, '--args="' + args + '"'], options) util.run('ninja', ['-C', config.outputDir, config.buildTarget], options) }, submoduleSync: (options = {}) => { if (!options.cwd) options.cwd = config.rootDir // default cwd `./src` may not exist yet options = mergeWithDefault(options) util.run('git', ['submodule', 'sync'], options) util.run('git', ['submodule', 'update', '--init', '--recursive'], options) util.run('git', ['-C', config.depotToolsDir, 'clean', '-fxd'], options) util.run('git', ['-C', config.depotToolsDir, 'reset', '--hard', 'HEAD'], options) }, gclientSync: (options = {}) => { runGClient(['sync', '--force', '--nohooks', '--with_branch_heads'], options) }, gclientRunhooks: (options = {}) => { runGClient(['runhooks'], options) }, fetch: (options = {}) => { if (!options.cwd) options.cwd = config.rootDir options = mergeWithDefault(options) util.run('git', ['-C', options.git_cwd, 'fetch', '--all', '--tags'], options) }, setVersion: (version, options = {}) => { if (!options.cwd) options.cwd = config.rootDir util.run('git', ['-C', options.git_cwd, 'clean', '-f'], options) util.run('git', ['-C', options.git_cwd, 'reset', '--hard', version], options) }, setDepVersion: (dir, version) => { const options = { git_cwd: dir } util.fetch(options) util.setVersion(version, options) }, buildArgsToString: (buildArgs) => { let args = '' for (let arg in buildArgs) { let val = buildArgs[arg] if (typeof val === 'string') { val = '"' + val + '"' } else { val = JSON.stringify(val) } args += arg + '=' + val + ' ' } return args.replace(/"/g,'\\"') } } module.exports = util