2016-11-09 21:02:49 -07:00
|
|
|
const path = require('path')
|
2019-01-24 12:37:34 -08:00
|
|
|
const { spawn, spawnSync } = require('child_process')
|
2016-11-09 21:02:49 -07:00
|
|
|
const config = require('./config')
|
2017-01-18 19:03:26 -07:00
|
|
|
const fs = require('fs-extra')
|
2018-09-07 11:42:47 -07:00
|
|
|
const crypto = require('crypto')
|
2018-07-22 19:40:55 -04:00
|
|
|
const autoGeneratedBraveToChromiumMapping = Object.assign({}, require('./l10nUtil').autoGeneratedBraveToChromiumMapping)
|
2016-11-09 21:02:49 -07:00
|
|
|
|
|
|
|
const runGClient = (args, options = {}) => {
|
2018-06-06 17:54:19 -05:00
|
|
|
if (config.gClientVerbose) args.push('--verbose')
|
2016-11-09 21:02:49 -07:00
|
|
|
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(' '))
|
2017-07-05 10:05:32 -07:00
|
|
|
const continueOnFail = options.continueOnFail
|
|
|
|
delete options.continueOnFail
|
|
|
|
|
2016-11-09 21:02:49 -07:00
|
|
|
const prog = spawnSync(cmd, args, options)
|
|
|
|
if (prog.status !== 0) {
|
2017-07-05 10:05:32 -07:00
|
|
|
if (!continueOnFail) {
|
|
|
|
console.log(prog.stdout && prog.stdout.toString())
|
|
|
|
console.error(prog.stderr && prog.stderr.toString())
|
|
|
|
process.exit(1)
|
|
|
|
}
|
2016-11-09 21:02:49 -07:00
|
|
|
}
|
2016-11-16 13:01:25 -07:00
|
|
|
return prog
|
2016-11-09 21:02:49 -07:00
|
|
|
},
|
|
|
|
|
2019-01-24 12:37:34 -08:00
|
|
|
runAsync: (cmd, args = [], options = {}) => {
|
|
|
|
console.log(cmd, args.join(' '))
|
|
|
|
const continueOnFail = options.continueOnFail
|
|
|
|
delete options.continueOnFail
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const prog = spawn(cmd, args, options)
|
|
|
|
let stderr = ''
|
|
|
|
let stdout = ''
|
|
|
|
prog.stderr.on('data', data => {
|
|
|
|
stderr += data
|
|
|
|
})
|
|
|
|
prog.stdout.on('data', data => {
|
|
|
|
stdout += data
|
|
|
|
})
|
|
|
|
prog.on('close', statusCode => {
|
|
|
|
const hasFailed = statusCode !== 0
|
|
|
|
if (hasFailed && !continueOnFail) {
|
|
|
|
console.log(stdout)
|
|
|
|
console.error(stderr)
|
|
|
|
process.exit(1)
|
|
|
|
}
|
|
|
|
resolve(stdout)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2016-11-10 01:14:33 -07:00
|
|
|
buildGClientConfig: () => {
|
|
|
|
function replacer(key, value) {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2016-12-14 17:04:43 -07:00
|
|
|
let solutions = config.projectNames.filter((projectName) => config.projects[projectName].ref).map((projectName) => {
|
2016-11-10 01:14:33 -07:00
|
|
|
let project = config.projects[projectName]
|
|
|
|
return {
|
|
|
|
managed: "%False%",
|
|
|
|
name: project.gclientName,
|
|
|
|
url: project.url,
|
|
|
|
custom_deps: project.custom_deps
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2018-06-29 13:28:59 -07:00
|
|
|
const out = 'solutions = ' + JSON.stringify(solutions, replacer, 2)
|
2016-11-10 01:14:33 -07:00
|
|
|
.replace(/"%None%"/g, "None")
|
|
|
|
.replace(/"%False%"/g, "False")
|
|
|
|
fs.writeFileSync(config.defaultGClientFile, out)
|
|
|
|
},
|
|
|
|
|
2018-09-07 11:42:47 -07:00
|
|
|
calculateFileChecksum: (filename) => {
|
|
|
|
// adapted from https://github.com/roryrjb/md5-file
|
|
|
|
const BUFFER_SIZE = 8192
|
|
|
|
const fd = fs.openSync(filename, 'r')
|
|
|
|
const buffer = Buffer.alloc(BUFFER_SIZE)
|
|
|
|
const md5 = crypto.createHash('md5')
|
|
|
|
|
|
|
|
try {
|
|
|
|
let bytesRead
|
|
|
|
do {
|
|
|
|
bytesRead = fs.readSync(fd, buffer, 0, BUFFER_SIZE)
|
|
|
|
md5.update(buffer.slice(0, bytesRead))
|
|
|
|
} while (bytesRead === BUFFER_SIZE)
|
|
|
|
} finally {
|
|
|
|
fs.closeSync(fd)
|
|
|
|
}
|
|
|
|
|
|
|
|
return md5.digest('hex')
|
|
|
|
},
|
|
|
|
|
2017-01-16 08:14:51 -07:00
|
|
|
updateBranding: () => {
|
|
|
|
console.log('update branding...')
|
2018-02-18 19:24:57 -05:00
|
|
|
const chromeComponentsDir = path.join(config.srcDir, 'components')
|
2018-07-10 17:32:39 -07:00
|
|
|
const braveComponentsDir = path.join(config.projects['brave-core'].dir, 'components')
|
2017-11-16 12:27:28 -07:00
|
|
|
const chromeAppDir = path.join(config.srcDir, 'chrome', 'app')
|
2018-03-24 21:57:33 -04:00
|
|
|
const braveAppDir = path.join(config.projects['brave-core'].dir, 'app')
|
2018-10-26 13:35:48 +09:00
|
|
|
const chromeBrowserResourcesDir = path.join(config.srcDir, 'chrome', 'browser', 'resources')
|
|
|
|
const braveBrowserResourcesDir = path.join(config.projects['brave-core'].dir, 'browser', 'resources')
|
2018-07-10 17:31:59 -07:00
|
|
|
const braveAppVectorIconsDir = path.join(config.projects['brave-core'].dir, 'vector_icons', 'chrome', 'app')
|
2018-06-20 15:27:42 -07:00
|
|
|
|
2018-09-08 21:02:14 +09:00
|
|
|
let fileMap = new Set();
|
|
|
|
// 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')
|
|
|
|
Object.entries(autoGeneratedBraveToChromiumMapping).forEach(mapping => fileMap.add(mapping))
|
2018-07-22 19:40:55 -04:00
|
|
|
|
|
|
|
// Copy xtb files for:
|
|
|
|
// brave/app/resources/chromium_strings*.xtb
|
|
|
|
// brave/app/strings/components_chromium_strings*.xtb
|
|
|
|
// brave/app/resources/generated_resoruces*.xtb
|
2018-09-08 21:02:14 +09:00
|
|
|
fileMap.add([path.join(braveAppDir, 'resources'), path.join(chromeAppDir, 'resources')])
|
|
|
|
fileMap.add([path.join(braveAppDir, 'strings'), path.join(chromeComponentsDir, 'strings')])
|
|
|
|
fileMap.add([path.join(braveAppDir, 'theme', 'default_100_percent', 'brave'), path.join(chromeAppDir, 'theme', 'default_100_percent', 'brave')])
|
|
|
|
fileMap.add([path.join(braveAppDir, 'theme', 'default_200_percent', 'brave'), path.join(chromeAppDir, 'theme', 'default_200_percent', 'brave')])
|
2018-06-22 13:44:48 +09:00
|
|
|
// By overwriting, we don't need to modify some grd files.
|
2018-09-08 21:02:14 +09:00
|
|
|
fileMap.add([path.join(braveAppDir, 'theme', 'brave'), path.join(chromeAppDir, 'theme', 'brave')])
|
|
|
|
fileMap.add([path.join(braveAppDir, 'theme', 'brave'), path.join(chromeAppDir, 'theme', 'chromium')])
|
|
|
|
fileMap.add([path.join(braveAppDir, 'theme', 'default_100_percent', 'brave'), path.join(chromeAppDir, 'theme', 'default_100_percent', 'chromium')])
|
|
|
|
fileMap.add([path.join(braveAppDir, 'theme', 'default_200_percent', 'brave'), path.join(chromeAppDir, 'theme', 'default_200_percent', 'chromium')])
|
|
|
|
fileMap.add([path.join(braveComponentsDir, 'resources', 'default_100_percent', 'brave'), path.join(chromeComponentsDir, 'resources', 'default_100_percent', 'chromium')])
|
|
|
|
fileMap.add([path.join(braveComponentsDir, 'resources', 'default_200_percent', 'brave'), path.join(chromeComponentsDir, 'resources', 'default_200_percent', 'chromium')])
|
|
|
|
fileMap.add([path.join(braveAppVectorIconsDir, 'vector_icons', 'brave'), path.join(chromeAppDir, 'vector_icons', 'brave')])
|
2018-10-26 13:35:48 +09:00
|
|
|
// Copy chrome-logo-faded.png for replacing chrome logo of welcome page with brave's on Win8.
|
|
|
|
fileMap.add([path.join(braveBrowserResourcesDir, 'chrome-logo-faded.png'), path.join(chromeBrowserResourcesDir, 'chrome-logo-faded.png')])
|
2018-11-02 16:27:13 +09:00
|
|
|
// Copy to make our ${branding_path_component}_behaviors.cc
|
|
|
|
fileMap.add([path.join(config.projects['brave-core'].dir, 'chromium_src', 'chrome', 'installer', 'setup', 'brave_behaviors.cc'),
|
|
|
|
path.join(config.srcDir, 'chrome', 'installer', 'setup', 'brave_behaviors.cc')])
|
2018-09-08 21:02:14 +09:00
|
|
|
|
|
|
|
for (const [source, output] of fileMap) {
|
2018-09-06 12:48:27 -07:00
|
|
|
let sourceFiles = []
|
|
|
|
|
|
|
|
// get all the files if source if a directory
|
|
|
|
if (fs.statSync(source).isDirectory()) {
|
|
|
|
sourceFiles = util.walkSync(source)
|
|
|
|
} else {
|
|
|
|
sourceFiles = [source]
|
|
|
|
}
|
|
|
|
|
2018-09-08 21:02:14 +09:00
|
|
|
for (const sourceFile of sourceFiles) {
|
|
|
|
let destinationFile = path.join(output, path.relative(source, sourceFile))
|
2018-09-06 12:48:27 -07:00
|
|
|
|
|
|
|
// The destination file might be newer when updating chromium so
|
|
|
|
// we check for an exact match on the timestamp. We use seconds instead
|
|
|
|
// of ms because utimesSync doesn't set the times with ms precision
|
|
|
|
if (!fs.existsSync(destinationFile) ||
|
|
|
|
Math.floor(new Date(fs.statSync(sourceFile).mtimeMs).getTime() / 1000) !=
|
|
|
|
Math.floor(new Date(fs.statSync(destinationFile).mtimeMs).getTime() / 1000)) {
|
|
|
|
fs.copySync(sourceFile, destinationFile)
|
|
|
|
// can't set the date in the past so update the source file
|
|
|
|
// to match the newly copied destionation file
|
|
|
|
const date = fs.statSync(destinationFile).mtime
|
|
|
|
fs.utimesSync(sourceFile, date, date)
|
|
|
|
console.log(sourceFile + ' copied to ' + destinationFile)
|
|
|
|
}
|
|
|
|
}
|
2018-07-27 10:32:32 +09:00
|
|
|
}
|
2018-09-08 21:02:14 +09:00
|
|
|
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
// Copy proper mac app icon for channel to chrome/app/theme/mac/app.icns.
|
|
|
|
// Each channel's app icons are stored in brave/app/theme/$channel/app.icns.
|
|
|
|
// With this copying, we don't need to modify chrome/BUILD.gn for this.
|
|
|
|
const iconSource = path.join(braveAppDir, 'theme', 'brave', 'mac', config.channel, 'app.icns')
|
|
|
|
const iconDest = path.join(chromeAppDir, 'theme', 'brave', 'mac', 'app.icns')
|
|
|
|
if (!fs.existsSync(iconDest) ||
|
|
|
|
util.calculateFileChecksum(iconSource) != util.calculateFileChecksum(iconDest)) {
|
|
|
|
console.log('copy app icon')
|
|
|
|
fs.copySync(iconSource, iconDest)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy branding file
|
|
|
|
let branding_file_name = 'BRANDING'
|
|
|
|
if (config.channel)
|
|
|
|
branding_file_name = branding_file_name + '.' + config.channel
|
|
|
|
|
|
|
|
const brandingSource = path.join(braveAppDir, 'theme', 'brave', branding_file_name)
|
|
|
|
const brandingDest = path.join(chromeAppDir, 'theme', 'brave', 'BRANDING')
|
|
|
|
if (!fs.existsSync(brandingDest) ||
|
|
|
|
util.calculateFileChecksum(brandingSource) != util.calculateFileChecksum(brandingDest)) {
|
|
|
|
console.log('copy branding file')
|
|
|
|
fs.copySync(brandingSource, brandingDest)
|
|
|
|
}
|
|
|
|
}
|
2017-01-16 08:14:51 -07:00
|
|
|
},
|
|
|
|
|
2018-06-26 09:20:30 +09:00
|
|
|
// 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)
|
|
|
|
},
|
|
|
|
|
2019-01-02 16:05:30 -07:00
|
|
|
signApp: (options = config.defaultOptions) => {
|
|
|
|
console.log('signing ...')
|
|
|
|
|
|
|
|
util.run('ninja', ['-C', config.outputDir, config.signTarget], options)
|
|
|
|
},
|
|
|
|
|
2018-06-06 17:54:19 -05:00
|
|
|
buildTarget: (options = config.defaultOptions) => {
|
|
|
|
console.log('building ' + config.buildTarget + '...')
|
2017-01-16 08:14:51 -07:00
|
|
|
|
2018-06-28 09:37:37 +09:00
|
|
|
if (process.platform === 'win32') util.updateOmahaMidlFiles()
|
2018-06-26 09:20:30 +09:00
|
|
|
|
2018-09-20 16:51:46 +09:00
|
|
|
let num_compile_failure = 1
|
|
|
|
if (config.ignore_compile_failure)
|
2018-10-08 13:37:11 +02:00
|
|
|
num_compile_failure = 0
|
2018-09-20 16:51:46 +09:00
|
|
|
|
2017-01-16 08:14:51 -07:00
|
|
|
const args = util.buildArgsToString(config.buildArgs())
|
|
|
|
util.run('gn', ['gen', config.outputDir, '--args="' + args + '"'], options)
|
2018-09-20 16:51:46 +09:00
|
|
|
util.run('ninja', ['-C', config.outputDir, config.buildTarget, '-k', num_compile_failure], options)
|
2017-01-16 08:14:51 -07:00
|
|
|
},
|
|
|
|
|
2018-12-26 16:43:02 -07:00
|
|
|
lint: (options = {}) => {
|
|
|
|
let cmd_options = config.defaultOptions
|
|
|
|
cmd_options.cwd = config.projects['brave-core'].dir
|
2019-01-22 12:06:38 -07:00
|
|
|
util.run('python', [path.join(config.rootDir, 'scripts', 'lint.py'),
|
|
|
|
'--project_root=' + config.srcDir], cmd_options)
|
2018-12-26 16:43:02 -07:00
|
|
|
},
|
|
|
|
|
2018-05-26 19:59:44 -05:00
|
|
|
submoduleSync: (options = {}) => {
|
|
|
|
if (!options.cwd) options.cwd = config.rootDir // default cwd `./src` may not exist yet
|
2016-11-09 21:02:49 -07:00
|
|
|
options = mergeWithDefault(options)
|
|
|
|
util.run('git', ['submodule', 'sync'], options)
|
|
|
|
util.run('git', ['submodule', 'update', '--init', '--recursive'], options)
|
2018-05-26 19:59:44 -05:00
|
|
|
util.run('git', ['-C', config.depotToolsDir, 'clean', '-fxd'], options)
|
|
|
|
util.run('git', ['-C', config.depotToolsDir, 'reset', '--hard', 'HEAD'], options)
|
2016-11-09 21:02:49 -07:00
|
|
|
},
|
|
|
|
|
2018-10-17 19:45:00 -07:00
|
|
|
gclientSync: (reset = false, options = {}) => {
|
|
|
|
let args = ['sync', '--force', '--nohooks', '--with_branch_heads', '--with_tags']
|
|
|
|
if (reset)
|
|
|
|
args.push('--upstream')
|
|
|
|
runGClient(args, options)
|
2016-11-09 21:02:49 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
gclientRunhooks: (options = {}) => {
|
|
|
|
runGClient(['runhooks'], options)
|
|
|
|
},
|
|
|
|
|
|
|
|
fetch: (options = {}) => {
|
2018-05-26 19:59:44 -05:00
|
|
|
if (!options.cwd) options.cwd = config.rootDir
|
2016-11-09 21:02:49 -07:00
|
|
|
options = mergeWithDefault(options)
|
2018-05-26 19:59:44 -05:00
|
|
|
util.run('git', ['-C', options.git_cwd, 'fetch', '--all', '--tags'], options)
|
2016-11-09 21:02:49 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
setVersion: (version, options = {}) => {
|
2018-05-26 19:59:44 -05:00
|
|
|
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)
|
2016-11-09 21:02:49 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
setDepVersion: (dir, version) => {
|
2018-05-26 19:59:44 -05:00
|
|
|
const options = { git_cwd: dir }
|
2016-11-09 21:02:49 -07:00
|
|
|
util.fetch(options)
|
|
|
|
util.setVersion(version, options)
|
|
|
|
},
|
2016-11-27 19:29:59 -07:00
|
|
|
|
|
|
|
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,'\\"')
|
2018-09-06 12:48:27 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
walkSync: (dir, filter = null, filelist = []) => {
|
|
|
|
fs.readdirSync(dir).forEach(file => {
|
|
|
|
if (fs.statSync(path.join(dir, file)).isDirectory()) {
|
|
|
|
filelist = util.walkSync(path.join(dir, file), filter, filelist)
|
|
|
|
} else if (!filter || filter.call(null, file)) {
|
|
|
|
filelist = filelist.concat(path.join(dir, file))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return filelist
|
2016-11-27 19:29:59 -07:00
|
|
|
}
|
2016-11-09 21:02:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = util
|