252 lines
9.0 KiB
Python
Executable File
252 lines
9.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Copyright (c) 2018 The Brave Authors. All rights reserved.
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
# You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import sys
|
|
import shutil
|
|
|
|
from pathlib import Path
|
|
|
|
from lib.util import execute_stdout, scoped_cwd
|
|
|
|
|
|
NPM = 'npm'
|
|
if sys.platform in ['win32', 'cygwin']:
|
|
NPM += '.cmd'
|
|
|
|
|
|
def main():
|
|
# Accept all paths as either absolute or relative to working dir,
|
|
# except grd_path, which we must know the relative location of
|
|
# in order to create a valid depfile.
|
|
args = parse_args()
|
|
|
|
output_path_absolute = os.path.abspath(args.output_path[0])
|
|
root_gen_dir = args.root_gen_dir[0]
|
|
grd_path = os.path.join(args.output_path[0], args.grd_name[0])
|
|
resource_path_prefix = args.resource_path_prefix
|
|
|
|
clean_target_dir(output_path_absolute)
|
|
|
|
webpack_gen_dir = output_path_absolute
|
|
|
|
depfile_path = os.path.abspath(args.depfile_path[0])
|
|
import_paths_file = os.path.abspath(args.import_paths_file[0])
|
|
transpile_options = dict(production=args.production,
|
|
target_gen_dir=webpack_gen_dir,
|
|
root_gen_dir=root_gen_dir,
|
|
entry_points=args.entry,
|
|
depfile_path=depfile_path,
|
|
depfile_sourcename=grd_path,
|
|
webpack_aliases=args.webpack_alias,
|
|
output_module=args.output_module,
|
|
no_externals=args.no_externals,
|
|
extra_modules=args.extra_modules,
|
|
public_asset_path=args.public_asset_path,
|
|
sync_wasm=args.sync_wasm,
|
|
no_iife=args.no_iife)
|
|
transpile_web_uis(transpile_options)
|
|
generate_grd(output_path_absolute, args.grd_name[0], args.resource_name[0],
|
|
resource_path_prefix)
|
|
|
|
verify_webpack_srcs(root_gen_dir, import_paths_file, depfile_path,
|
|
args.extra_modules)
|
|
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(description='Transpile web-uis')
|
|
parser.add_argument('-p', '--production',
|
|
action='store_true',
|
|
help='Uses production config')
|
|
parser.add_argument('--entry',
|
|
action='append',
|
|
help='Entry points',
|
|
required=True)
|
|
parser.add_argument('--no_externals', action='store_true')
|
|
parser.add_argument('--output_path', nargs=1)
|
|
parser.add_argument('--root_gen_dir', nargs=1)
|
|
parser.add_argument('--depfile_path', nargs=1)
|
|
parser.add_argument('--import_paths_file', nargs=1)
|
|
parser.add_argument('--grd_name', nargs=1)
|
|
parser.add_argument('--resource_name', nargs=1)
|
|
parser.add_argument('--public_asset_path', nargs='?')
|
|
parser.add_argument('--webpack_alias',
|
|
action='append',
|
|
help='Webpack alias',
|
|
required=False,
|
|
default=[])
|
|
parser.add_argument('--output_module', action='store_true')
|
|
parser.add_argument(
|
|
"--resource_path_prefix",
|
|
nargs='?',
|
|
help="The resource path prefix. Used in grit part files.")
|
|
parser.add_argument('--extra_modules',
|
|
action='append',
|
|
help='Extra paths to find modules',
|
|
required=False,
|
|
default=[])
|
|
parser.add_argument('--sync_wasm', action='store_true')
|
|
parser.add_argument('--no_iife', action='store_true')
|
|
|
|
args = parser.parse_args()
|
|
# validate args
|
|
if (args.output_path is None or len(args.output_path) != 1 or
|
|
len(args.output_path[0]) == 0):
|
|
raise Exception(" output_path argument was not specified correctly")
|
|
# args are valid
|
|
return args
|
|
|
|
|
|
def clean_target_dir(target_dir):
|
|
try:
|
|
if os.path.exists(target_dir):
|
|
shutil.rmtree(target_dir)
|
|
except Exception as e:
|
|
raise Exception("Error removing previous webpack target dir") from e
|
|
|
|
|
|
def transpile_web_uis(options):
|
|
env = os.environ.copy()
|
|
|
|
args = [NPM, 'run', 'web-ui', '--']
|
|
|
|
if options['production']:
|
|
args.append("--mode=production")
|
|
else:
|
|
args.append("--mode=development")
|
|
|
|
if options['public_asset_path'] is not None:
|
|
args.append("--env=output_public_path=" + options['public_asset_path'])
|
|
|
|
if options['no_externals']:
|
|
args.append("--env=no_externals")
|
|
|
|
# web pack aliases
|
|
if options['webpack_aliases']:
|
|
args.append("--env=webpack_aliases=" +
|
|
",".join(options['webpack_aliases']))
|
|
|
|
if options['output_module']:
|
|
args.append("--env=output_module")
|
|
|
|
# extra module locations
|
|
if options['extra_modules']:
|
|
args.append("--env=extra_modules=" + ",".join(options['extra_modules']))
|
|
|
|
# In webpack.config.js there is a custom parser to support named entry
|
|
# points. As webpack-cli no longer supports named entries, we provide them
|
|
# via in a custom variable, comma-separated and with
|
|
# "[name]=[path]" syntax.
|
|
args.append("--env=brave_entries=" + ",".join(options['entry_points']))
|
|
|
|
if options['sync_wasm']:
|
|
args.append("--env=sync_wasm")
|
|
|
|
# Webpack will by default wrap the output in an IIFE, which is not
|
|
# desirable for some bundles.
|
|
if options['no_iife']:
|
|
args.append("--env=no_iife")
|
|
|
|
# We should use webpack-cli env param to not pollute environment
|
|
env["ROOT_GEN_DIR"] = options['root_gen_dir']
|
|
env["TARGET_GEN_DIR"] = options['target_gen_dir']
|
|
env["DEPFILE_PATH"] = options['depfile_path']
|
|
env["DEPFILE_SOURCE_NAME"] = options['depfile_sourcename']
|
|
|
|
dirname = os.path.abspath(os.path.join(__file__, '..', '..'))
|
|
with scoped_cwd(dirname):
|
|
execute_stdout(args, env)
|
|
|
|
def generate_grd(target_include_dir, grd_name, resource_name,
|
|
resource_path_prefix):
|
|
env = os.environ.copy()
|
|
|
|
args = [NPM, 'run', 'web-ui-gen-grd']
|
|
|
|
env["RESOURCE_NAME"] = resource_name
|
|
env["GRD_NAME"] = grd_name
|
|
env["ID_PREFIX"] = "IDR_" + resource_name.upper() + '_'
|
|
env["TARGET_DIR"] = target_include_dir
|
|
|
|
if resource_path_prefix is not None:
|
|
env["RESOURCE_PATH_PREFIX"] = resource_path_prefix
|
|
|
|
dirname = os.path.abspath(os.path.join(__file__, '..', '..'))
|
|
with scoped_cwd(dirname):
|
|
execute_stdout(args, env)
|
|
|
|
|
|
# verifies that all files webpack imports or their containing folders are listed in the imports_from
|
|
# section defined in transpile_web_ui targets. Doing it here allows us to not only verify
|
|
# the completeness but also to generate an actionable error message.
|
|
# The list is important as it allows us to ensure gn analyze always works correctly.
|
|
# imports_from is passed as data to the underlying gn action and is recognised by gn analyze.
|
|
# This is a compromise solution to explicitly listing out or generating a list of files via an exec_script
|
|
# https://gn.googlesource.com/gn/+/main/docs/reference.md#cmd_analyze
|
|
def verify_webpack_srcs(root_gen_dir, import_paths_file, depfile_path,
|
|
extra_modules):
|
|
|
|
src_folder = Path(os.path.abspath(os.path.join(
|
|
__file__, '..', '..', '..'))).resolve().as_posix()
|
|
|
|
make_source_absolute = lambda path: Path(path).resolve().as_posix(
|
|
).replace(src_folder, '/')
|
|
|
|
out_dir = make_source_absolute(Path(root_gen_dir).resolve().parents[1])
|
|
|
|
with open(import_paths_file) as f:
|
|
src_roots = json.loads(f.read())
|
|
assert isinstance(src_roots, list)
|
|
|
|
with open(depfile_path) as f:
|
|
files = [make_source_absolute(file) for file in f.read().split()[1:]]
|
|
|
|
all_roots = src_roots + [
|
|
'//brave/node_modules', # handled via package.json
|
|
out_dir # generated assets are deps and handled by gn already
|
|
] + [make_source_absolute(module) for module in extra_modules]
|
|
|
|
not_contained = get_not_contained(all_roots, files)
|
|
|
|
if len(not_contained) > 0:
|
|
print("error occured cross-referencing import_paths folders.")
|
|
print("transpile_web_ui accessed the following files:")
|
|
print(" " + "\n ".join(not_contained))
|
|
|
|
if len(src_roots) > 0:
|
|
print(
|
|
"However they are not listed as imports_from in target. imports_from conatains:"
|
|
)
|
|
print(" " + "\n ".join(src_roots))
|
|
else:
|
|
print("However imports_from is empty")
|
|
|
|
print(
|
|
"fix this issue by adding the containing source folders into the transpile_web_ui target imports_from section"
|
|
)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
def get_not_contained(roots, test_paths):
|
|
"""
|
|
Check whether all given paths are contained within the source roots.
|
|
Returns list of paths that were not contained
|
|
"""
|
|
|
|
not_contained = [
|
|
str(path) for path in test_paths
|
|
if not any(path.startswith(root) for root in roots)
|
|
]
|
|
|
|
return not_contained
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|