C:\chromium\src\chrome\browser\resources\tools\
gn gen out\Default --args=“target_cpu=“x86” target_os = “win” is_official_build = true chrome_pgo_phase = 0 is_debug = false proprietary_codecs = true ffmpeg_branding = “Chrome””
ninja -C out/Default mini_installer
#!/usr/bin/env python
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import itertools
import json
import os
import glob
import platform
import re
import shutil
import sys
import tempfile
_HERE_PATH = os.path.dirname(__file__)
_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..', '..'))
_CWD = os.getcwd() # NOTE(dbeam): this is typically out/<gn_name>/.
sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node'))
import node
import node_modules
# These files are already combined and minified.
_BASE_EXCLUDES = []
for excluded_file in [
'resources/polymer/v1_0/web-animations-js/web-animations-next-lite.min.js',
'resources/css/roboto.css',
'resources/css/text_defaults.css',
'resources/css/text_defaults_md.css',
'resources/mojo/mojo/public/js/mojo_bindings_lite.html',
'resources/mojo/mojo/public/mojom/base/time.mojom.html',
'resources/mojo/mojo/public/mojom/base/time.mojom-lite.js',
'resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom.html',
'resources/mojo/services/network/public/mojom/ip_address.mojom.html',
'resources/polymer/v3_0/polymer/polymer_bundled.min.js',
'resources/js/load_time_data.m.js',
]:
# Exclude both the chrome://resources form and the scheme-relative form for
# files used in Polymer 3.
_BASE_EXCLUDES.append("chrome://" + excluded_file)
_BASE_EXCLUDES.append("//" + excluded_file)
def _request_list_path(out_path, target_name):
# Using |target_name| as a prefix which is guaranteed to be unique within the
# same folder, to avoid problems when multiple optimize_webui() targets in the
# same BUILD.gn file exist.
return os.path.join(out_path, target_name + '_requestlist.txt')
def _get_dep_path(dep, host_url, in_path):
if dep.startswith(host_url):
return dep.replace(host_url, os.path.relpath(in_path, _CWD))
elif not (dep.startswith('chrome://') or dep.startswith('//')):
return os.path.relpath(in_path, _CWD) + '/' + dep
return dep
# Get a list of all files that were bundled with rollup and update the
# depfile accordingly such that Ninja knows when to re-trigger.
def _update_dep_file(in_folder, args, manifest):
in_path = os.path.join(_CWD, in_folder)
# Gather the dependencies of all bundled root files.
request_list = []
for out_file in manifest:
request_list += manifest[out_file]
# Add a slash in front of every dependency that is not a chrome:// URL, so
# that we can map it to the correct source file path below.
request_list = map(lambda dep: _get_dep_path(dep, args.host_url, in_path),
request_list)
deps = map(os.path.normpath, request_list)
out_file_name = args.js_out_files[0]
with open(os.path.join(_CWD, args.depfile), 'w') as f:
deps_file_header = os.path.join(args.out_folder, out_file_name)
f.write(deps_file_header + ': ' + ' '.join(deps))
# Autogenerate a rollup config file so that we can import the plugin and
# pass it information about the location of the directories and files to exclude
# from the bundle.
def _generate_rollup_config(tmp_out_dir, path_to_plugin, in_path, host_url,
excludes, external_paths):
rollup_config_file = os.path.join(tmp_out_dir, 'rollup.config.js')
config_content = r'''
import plugin from '{plugin_path}';
export default ({{
plugins: [
plugin('{in_path}', '{host_url}', {exclude_list},
{external_path_list}, /* allowEmptyExtension= */ false) ]
}});
'''.format(plugin_path=path_to_plugin.replace('\\', '/'),
in_path=in_path.replace('\\', '/'),
host_url=host_url,
exclude_list=json.dumps(excludes),
external_path_list=json.dumps(external_paths))
with open(rollup_config_file, 'w') as f:
f.write(config_content);
return rollup_config_file;
# Create the manifest file from the sourcemap generated by rollup and return the
# list of bundles.
def _generate_manifest_file(tmp_out_dir, in_path, manifest_out_path):
generated_sourcemaps = glob.glob('%s/*.map' % tmp_out_dir)
manifest = {}
output_filenames = []
for sourcemap_file in generated_sourcemaps:
with open(sourcemap_file, 'r') as f:
sourcemap = json.loads(f.read())
if not 'sources' in sourcemap:
raise Exception('rollup could not construct source map')
sources = sourcemap['sources']
replaced_sources = []
for source in sources:
replaced_sources.append(
source.replace('../' + os.path.basename(in_path) + "/", ""))
filename = sourcemap_file[:-len('.map')]
manifest[os.path.basename(filename)] = replaced_sources
output_filenames.append(filename)
with open(manifest_out_path, 'w') as f:
f.write(json.dumps(manifest))
return output_filenames
def _bundle_v3(tmp_out_dir, in_path, out_path, manifest_out_path, args,
excludes, external_paths):
if not os.path.exists(tmp_out_dir):
os.makedirs(tmp_out_dir)
path_to_plugin = os.path.join(
os.path.abspath(_HERE_PATH), 'rollup_plugin.js')
rollup_config_file = _generate_rollup_config(tmp_out_dir, path_to_plugin,
in_path, args.host_url, excludes,
external_paths)
rollup_args = [os.path.join(in_path, f) for f in args.js_module_in_files]
# Confirm names are as expected. This is necessary to avoid having to replace
# import statements in the generated output files.
# TODO(rbpotter): Is it worth adding import statement replacement to support
# arbitrary names?
bundled_paths = []
for index, js_file in enumerate(args.js_module_in_files):
base_file_name = os.path.basename(js_file)
expected_name = '%s.rollup.js' % base_file_name[:-len('.js')]
assert args.js_out_files[index] == expected_name, \
'Output file corresponding to %s should be named %s' % \
(js_file, expected_name)
bundled_paths.append(os.path.join(tmp_out_dir, expected_name))
# This indicates that rollup is expected to generate a shared chunk file as
# well as one file per module. Set its name using --chunkFileNames. Note:
# Currently, this only supports 2 entry points, which generate 2 corresponding
# outputs and 1 shared output.
if (len(args.js_out_files) == 3):
assert len(args.js_module_in_files) == 2, \
'Expect 2 module entry points for generating 3 outputs'
shared_file_name = args.js_out_files[2]
rollup_args += [ '--chunkFileNames', shared_file_name ]
bundled_paths.append(os.path.join(tmp_out_dir, shared_file_name))
node.RunNode(
[node_modules.PathToRollup()] + rollup_args + [
'--format', 'esm',
'--dir', tmp_out_dir,
'--entryFileNames', '[name].rollup.js',
'--sourcemap', '--sourcemapExcludeSources',
'--config', rollup_config_file,
'--silent',
])
# Create the manifest file from the sourcemaps generated by rollup.
generated_paths = _generate_manifest_file(tmp_out_dir, in_path,
manifest_out_path)
assert len(generated_paths) == len(bundled_paths), \
'unexpected number of bundles - %s - generated by rollup' % \
(len(generated_paths))
for bundled_file in bundled_paths:
with open(bundled_file, 'r', encoding='gb18030', errors='ignore') as f:
output = f.read()
assert "<if expr" not in output, \
'Unexpected <if expr> found in bundled output. Check that all ' + \
'input files using such expressions are preprocessed.'
return bundled_paths
def _optimize(in_folder, args):
in_path = os.path.normpath(os.path.join(_CWD, in_folder)).replace('\\', '/')
out_path = os.path.join(_CWD, args.out_folder).replace('\\', '/')
manifest_out_path = _request_list_path(out_path, args.target_name)
tmp_out_dir = tempfile.mkdtemp(dir=out_path).replace('\\', '/')
excludes = _BASE_EXCLUDES + [
# This file is dynamically created by C++. Should always be imported with a
# relative path.
'strings.m.js',
]
excludes.extend(args.exclude or [])
external_paths = args.external_paths or []
try:
pcb_out_paths = [os.path.join(tmp_out_dir, f) for f in args.js_out_files]
bundled_paths = _bundle_v3(tmp_out_dir, in_path, out_path,
manifest_out_path, args, excludes,
external_paths)
# Run polymer-css-build.
node.RunNode([node_modules.PathToPolymerCssBuild()] +
['--polymer-version', '2'] +
['--no-inline-includes', '-f'] +
bundled_paths + ['-o'] + pcb_out_paths)
# Pass the JS files through Terser and write the output to its final
# destination.
for index, js_out_file in enumerate(args.js_out_files):
node.RunNode([node_modules.PathToTerser(),
os.path.join(tmp_out_dir, js_out_file),
'--comments', '/Copyright|license|LICENSE|\<\/?if/',
'--output', os.path.join(out_path, js_out_file)])
finally:
shutil.rmtree(tmp_out_dir)
return manifest_out_path
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--depfile', required=True)
parser.add_argument('--target_name', required=True)
parser.add_argument('--exclude', nargs='*')
parser.add_argument('--external_paths', nargs='*')
parser.add_argument('--host', required=True)
parser.add_argument('--input', required=True)
parser.add_argument('--js_out_files', nargs='*', required=True)
parser.add_argument('--out_folder', required=True)
parser.add_argument('--js_module_in_files', nargs='*', required=True)
parser.add_argument('--out-manifest')
args = parser.parse_args(argv)
# NOTE(dbeam): on Windows, GN can send dirs/like/this. When joined, you might
# get dirs/like/this\file.txt. This looks odd to windows. Normalize to right
# the slashes.
args.depfile = os.path.normpath(args.depfile)
args.input = os.path.normpath(args.input)
args.out_folder = os.path.normpath(args.out_folder)
scheme_end_index = args.host.find('://')
if (scheme_end_index == -1):
args.host_url = 'chrome://%s/' % args.host
else:
args.host_url = args.host
manifest_out_path = _optimize(args.input, args)
# Prior call to _optimize() generated an output manifest file, containing
# information about all files that were bundled. Grab it from there.
manifest = json.loads(open(manifest_out_path, 'r').read())
# Output a manifest file that will be used to auto-generate a grd file later.
if args.out_manifest:
manifest_data = {
'base_dir': args.out_folder,
'files': list(manifest.keys()),
}
with open(os.path.normpath(os.path.join(_CWD, args.out_manifest)), 'w') \
as manifest_file:
json.dump(manifest_data, manifest_file)
_update_dep_file(args.input, args, manifest)
if __name__ == '__main__':
main(sys.argv[1:])
文件位置
C:\chromium\src\chrome\browser\resources\tools\
编译命令
gn gen out\Default --args=“target_cpu=“x86” target_os = “win” is_official_build = true chrome_pgo_phase = 0 is_debug = false proprietary_codecs = true ffmpeg_branding = “Chrome””
ninja -C out/Default mini_installer