373 строки
14 KiB
Python
Executable File
373 строки
14 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import argparse
|
|
import contextlib
|
|
import json
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import urllib2
|
|
import platform
|
|
import tarfile
|
|
|
|
import lib.filesystem as filesystem
|
|
import lib.sccache as sccache
|
|
import lib.util as util
|
|
|
|
from lib.config import MIPS64EL_GCC, MIPS64EL_GCC_URL, MIPS64EL_SYSROOT, \
|
|
set_mips64el_env, IS_ARM64_HOST, IS_ARMV7_HOST, \
|
|
SOURCE_ROOT, VENDOR_DIR, DEPOT_TOOLS_DIR, SRC_DIR, \
|
|
PLATFORM_KEY
|
|
|
|
CHROMIUMCONTENT_SOURCE_DIR = os.path.join(SOURCE_ROOT, 'chromiumcontent')
|
|
CHROMIUMCONTENT_DESTINATION_DIR = os.path.join(
|
|
SRC_DIR, 'libchromiumcontent', 'chromiumcontent')
|
|
CHROMIUMCONTENT_SRC_URL = 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent'
|
|
|
|
DEBIAN_MIRROR = 'http://ftp.jp.debian.org/debian/pool/main/'
|
|
BINTOOLS_NAME = 'c/cross-binutils/binutils-aarch64-linux-gnu_2.25-5_amd64.deb'
|
|
GCLIENT_CONFIG_PATH = os.path.join(SOURCE_ROOT, '.gclient')
|
|
GCLIENT_CONFIG_TEMPLATE = '''
|
|
solutions = [
|
|
{{
|
|
"url": "https://chromium.googlesource.com/chromium/src.git",
|
|
"managed": False,
|
|
"name": "src",
|
|
"deps_file": ".DEPS.git",
|
|
"custom_vars": {{
|
|
"checkout_nacl": False
|
|
}},
|
|
"custom_deps": {{}},
|
|
}},
|
|
]
|
|
{cache_dir_line}
|
|
'''
|
|
SRC_FILES_TO_IGNORE = [
|
|
os.path.join('src', 'native_client'),
|
|
os.path.join('src', 'third_party', 'WebKit', 'LayoutTests'),
|
|
os.path.join('src', 'third_party', 'catapult', 'tracing', 'test_data'),
|
|
os.path.join('src', 'third_party', 'deqp'),
|
|
os.path.join('src', 'third_party', 'sqlite', 'sqlite-src-3200100', 'test'),
|
|
os.path.join('src', 'third_party', 'sqlite', 'src', 'test'),
|
|
os.path.join('src', 'tools', 'swarming_client', 'example')
|
|
]
|
|
|
|
def main():
|
|
args = parse_args()
|
|
|
|
if sys.platform == 'win32' and args.update_depot_tools:
|
|
update_depot_tools()
|
|
|
|
if args.clean and os.path.isdir(SRC_DIR):
|
|
git_clean_recursive(SRC_DIR)
|
|
|
|
# Warning about using a network share as git cache from Windows 7+: The
|
|
# gclient script may experience errors unless you disable SMBv2 cache by
|
|
# setting the registry key
|
|
# HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime
|
|
# to 0.
|
|
# More information: https://stackoverflow.com/a/9935126
|
|
git_cache = args.git_cache or os.getenv('LIBCHROMIUMCONTENT_GIT_CACHE', '')
|
|
|
|
target_arch = args.target_arch
|
|
nohooks = target_arch == 'arm64' and IS_ARM64_HOST or target_arch == 'arm' and IS_ARMV7_HOST
|
|
|
|
|
|
if args.run_gclient:
|
|
if args.use_packaged_src:
|
|
get_packaged_src(args.clean, git_cache, nohooks, args.upload_packaged_src, args.verbose)
|
|
else:
|
|
gclient_sync(chromium_version(), args.clean, git_cache, nohooks)
|
|
if args.source_only:
|
|
return
|
|
|
|
if sys.platform in ['win32', 'cygwin']:
|
|
update_toolchain_json()
|
|
|
|
if target_arch == 'arm64':
|
|
install_aarch64_bintools()
|
|
|
|
return ((apply_patches(target_arch) if args.apply_patches else 0) or
|
|
install_sysroot_if_needed(target_arch) or
|
|
copy_chromiumcontent_files() or
|
|
update_clang() or
|
|
setup_mips64el_toolchain(target_arch) or
|
|
run_gn(target_arch, args.cc_wrapper, args.verbose))
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(description='Update build configuration')
|
|
parser.add_argument('-t', '--target_arch', default='x64', help='x64 or ia32')
|
|
parser.add_argument('--git-cache', default='',
|
|
help='Global git object cache for Chromium+ deps')
|
|
parser.add_argument('--clean', action='store_true',
|
|
help='Cleans the working directory for full rebuild')
|
|
parser.add_argument('--skip_patches', dest='apply_patches', action='store_false',
|
|
help='Skips applying patches, easier to build locally')
|
|
parser.add_argument('--skip_gclient', dest='run_gclient', action='store_false',
|
|
help='Skips syncing repo, easier to build locally')
|
|
parser.add_argument('--skip_depot_tools_update', dest='update_depot_tools', action='store_false',
|
|
help='Skips update depot tools on Windows, easier to build locally')
|
|
parser.add_argument('--source_only', action='store_true',
|
|
help='Only sync the Chromium source code')
|
|
parser.add_argument('--use_packaged_src', action='store_true',
|
|
help='Get chromium source as packaged file')
|
|
parser.add_argument('--upload_packaged_src', action='store_true',
|
|
help='Upload packaged chromium source if it does not exist')
|
|
parser.add_argument('-v', '--verbose',
|
|
action='store_true',
|
|
help='Prints verbose output')
|
|
|
|
cc_wrapper_group = parser.add_mutually_exclusive_group()
|
|
cc_wrapper_group.add_argument('--cc_wrapper',
|
|
help="Compiler cache to use. E.g. ccache, sccache, etc.")
|
|
cc_wrapper_group.add_argument('--ccache',
|
|
action='store_const', const='ccache', dest='cc_wrapper',
|
|
help="Use ccache as a compiler cache.")
|
|
cc_wrapper_group.add_argument('--sccache',
|
|
action='store_const', const='sccache', dest='cc_wrapper',
|
|
help="Use sccache as a compiler cache.")
|
|
cc_wrapper_group.add_argument('--use-bundled-sccache',
|
|
action='store_const', const=sccache.get_binary_path(), dest='cc_wrapper',
|
|
help='Use sccache binary stored in with the libcc repo.')
|
|
|
|
parser.set_defaults(apply_patches=True, run_gclient=True, update_depot_tools=True)
|
|
return parser.parse_args()
|
|
|
|
|
|
def chromium_version():
|
|
with open(os.path.join(SOURCE_ROOT, 'VERSION')) as f:
|
|
return f.readline().strip()
|
|
|
|
|
|
def install_sysroot_if_needed(target_arch):
|
|
if sys.platform != 'linux2':
|
|
return 0
|
|
|
|
if target_arch == 'ia32':
|
|
target_cpu = 'i386'
|
|
elif target_arch == 'x64':
|
|
target_cpu = 'amd64'
|
|
else:
|
|
target_cpu = target_arch
|
|
|
|
for arch in ('arm', 'arm64', 'amd64', 'i386'):
|
|
# Download from chromium's sysroot storage.
|
|
install = os.path.join(SRC_DIR, 'build', 'linux', 'sysroot_scripts',
|
|
'install-sysroot.py')
|
|
subprocess.check_call([sys.executable, install, '--arch', arch])
|
|
|
|
if target_cpu == 'mips64el':
|
|
# Download from our own sysroot storage.
|
|
destination = os.path.join(SRC_DIR, 'build', 'linux')
|
|
if os.path.exists(os.path.join(destination, 'debian_jessie_mips64-sysroot')):
|
|
return
|
|
|
|
tar_name = 'debian_jessie_mips64-sysroot.tar.bz2'
|
|
download(MIPS64EL_SYSROOT, tar_name)
|
|
subprocess.call(['tar', '-jxf', tar_name, '-C', destination])
|
|
filesystem.rm_f(tar_name)
|
|
|
|
return 0
|
|
|
|
|
|
def install_aarch64_bintools():
|
|
destination = os.path.join(VENDOR_DIR, 'binutils-aarch64')
|
|
if os.path.exists(destination):
|
|
return
|
|
|
|
deb_name = 'binutils-aarch64.deb'
|
|
download(DEBIAN_MIRROR + BINTOOLS_NAME, deb_name)
|
|
|
|
env = os.environ.copy()
|
|
env['DEPOT_TOOLS_WIN_TOOLCHAIN'] = '0'
|
|
subprocess.call(['dpkg', '-x', deb_name, destination])
|
|
filesystem.rm_f(deb_name)
|
|
|
|
|
|
def update_toolchain_json():
|
|
env = os.environ.copy()
|
|
env['DEPOT_TOOLS_WIN_TOOLCHAIN'] = '0'
|
|
vs_toolchain = os.path.join(SRC_DIR, 'build', 'vs_toolchain.py')
|
|
subprocess.check_call([sys.executable, vs_toolchain, 'update'], env=env)
|
|
|
|
|
|
def copy_chromiumcontent_files():
|
|
filesystem.mkdir_p(CHROMIUMCONTENT_DESTINATION_DIR)
|
|
for dirpath, dirnames, filenames in os.walk(CHROMIUMCONTENT_SOURCE_DIR):
|
|
for dirname in dirnames:
|
|
source = os.path.join(dirpath, dirname)
|
|
relative = os.path.relpath(source, start=CHROMIUMCONTENT_SOURCE_DIR)
|
|
filesystem.mkdir_p(os.path.join(CHROMIUMCONTENT_DESTINATION_DIR, relative))
|
|
for filename in filenames:
|
|
source = os.path.join(dirpath, filename)
|
|
relative = os.path.relpath(source, start=CHROMIUMCONTENT_SOURCE_DIR)
|
|
destination = os.path.join(CHROMIUMCONTENT_DESTINATION_DIR, relative)
|
|
if is_newer(destination, source):
|
|
continue
|
|
shutil.copy2(source, destination)
|
|
|
|
|
|
def update_depot_tools():
|
|
env = os.environ.copy()
|
|
# Don't actually update the depot tools, just install the required
|
|
# tools like python
|
|
env['DEPOT_TOOLS_UPDATE'] = '0'
|
|
# Remove trailing slash from TEMP
|
|
# https://bugs.chromium.org/p/chromium/issues/detail?id=340243
|
|
env['TEMP'] = env['TEMP'].rstrip('\\')
|
|
env['PATH'] = os.pathsep.join([DEPOT_TOOLS_DIR, env['PATH']])
|
|
update_path = os.path.join(DEPOT_TOOLS_DIR, 'update_depot_tools.bat')
|
|
subprocess.check_call([update_path], env=env)
|
|
|
|
|
|
def ensure_gclient_config(git_cache):
|
|
# escape backslashes to avoid escaping the cache_dir assignment quote
|
|
git_cache = git_cache.replace('\\', '\\\\')
|
|
with open(GCLIENT_CONFIG_PATH, 'wb') as f:
|
|
f.write(GCLIENT_CONFIG_TEMPLATE.format(
|
|
cache_dir_line="cache_dir = '{0}'".format(git_cache) if git_cache else ''
|
|
))
|
|
|
|
|
|
def gclient_sync(version, force, git_cache, nohooks):
|
|
# Remove untracked files in src.
|
|
if os.path.exists(os.path.join(SRC_DIR, '.git')):
|
|
with util.scoped_cwd(SRC_DIR):
|
|
subprocess.check_call(['git', 'clean', '-df'])
|
|
|
|
ensure_gclient_config(git_cache)
|
|
env = os.environ.copy()
|
|
if sys.platform in ['win32', 'cygwin']:
|
|
env['DEPOT_TOOLS_WIN_TOOLCHAIN'] = '0'
|
|
env['PATH'] = os.pathsep.join([DEPOT_TOOLS_DIR, env['PATH']])
|
|
gclient = os.path.join(DEPOT_TOOLS_DIR, 'gclient.py')
|
|
args = [sys.executable, gclient, 'sync', '--jobs', '16',
|
|
'--revision', 'src@{0}'.format(version), '--with_tags',
|
|
'--with_branch_heads', '--reset', '--delete_unversioned_trees']
|
|
if git_cache:
|
|
args += ['--lock_timeout=15']
|
|
if force:
|
|
args += ['--force']
|
|
if nohooks:
|
|
args += ['--nohooks']
|
|
subprocess.check_call(args, env=env)
|
|
|
|
|
|
def apply_patches(target_arch):
|
|
script_path = os.path.join(SOURCE_ROOT, 'script', 'apply-patches')
|
|
script_arguments = ['--target_arch', target_arch]
|
|
return subprocess.call([sys.executable, script_path] + script_arguments)
|
|
|
|
|
|
def update_clang():
|
|
env = os.environ.copy()
|
|
env['PATH'] = os.pathsep.join([DEPOT_TOOLS_DIR, env['PATH']])
|
|
env['DEPOT_TOOLS_WIN_TOOLCHAIN'] = '0'
|
|
update = os.path.join(SRC_DIR, 'tools', 'clang', 'scripts', 'update.py')
|
|
return subprocess.call([sys.executable, update, '--if-needed'], env=env)
|
|
|
|
|
|
def setup_mips64el_toolchain(target_arch):
|
|
if target_arch != 'mips64el':
|
|
return
|
|
|
|
# Download mips64el toolchains.
|
|
if not os.path.exists(os.path.join(VENDOR_DIR, MIPS64EL_GCC)):
|
|
tar_name = MIPS64EL_GCC + '.tar.gz'
|
|
download(MIPS64EL_GCC_URL, tar_name)
|
|
subprocess.check_call(['tar', '-xf', tar_name, '-C', VENDOR_DIR])
|
|
filesystem.rm_f(tar_name)
|
|
|
|
# Gernerate ffmpeg build config files for mips64el.
|
|
env = os.environ.copy()
|
|
set_mips64el_env(env)
|
|
ffmpeg_dir = os.path.join(SRC_DIR, 'third_party', 'ffmpeg')
|
|
subprocess.check_call(['chromium/scripts/build_ffmpeg.py', 'linux', 'mips64el'], cwd=ffmpeg_dir, env=env)
|
|
subprocess.check_call(['chromium/scripts/copy_config.sh'], cwd=ffmpeg_dir)
|
|
subprocess.check_call(['chromium/scripts/generate_gn.py'], cwd=ffmpeg_dir)
|
|
|
|
|
|
def run_gn(target_arch, cc_wrapper=None, verbose=False):
|
|
gn_args = {}
|
|
|
|
if cc_wrapper is not None:
|
|
gn_args['cc_wrapper'] = cc_wrapper
|
|
|
|
script_path = os.path.join(SOURCE_ROOT, 'script', 'run-gn')
|
|
script_arguments = [
|
|
'--args', json.dumps(gn_args),
|
|
'--target_arch', target_arch
|
|
]
|
|
if verbose:
|
|
script_arguments.append('-v')
|
|
return subprocess.call([sys.executable, script_path] + script_arguments)
|
|
|
|
|
|
def is_newer(destination, source):
|
|
return os.path.exists(destination) and \
|
|
os.path.getmtime(destination) > os.path.getmtime(source)
|
|
|
|
|
|
def git_clean_recursive(path):
|
|
for root, dirs, files in os.walk(path):
|
|
if '.git' in dirs:
|
|
subprocess.call(['git', 'clean', '-xdf'], cwd=root)
|
|
dirs.remove('.git')
|
|
|
|
|
|
def download(url, filename):
|
|
with open(filename, 'wb+') as f:
|
|
with contextlib.closing(urllib2.urlopen(url)) as u:
|
|
while True:
|
|
chunk = u.read(1024*1024)
|
|
if not len(chunk):
|
|
break
|
|
f.write(chunk)
|
|
|
|
def get_packaged_src(clean, git_cache, nohooks, upload_src, verbose):
|
|
src_version = chromium_version()
|
|
tar_name = 'src.tar.bz2'
|
|
package_url = '{0}/{1}/src/{2}/{3}'.format(CHROMIUMCONTENT_SRC_URL,
|
|
PLATFORM_KEY, src_version, tar_name)
|
|
try:
|
|
print('Trying to download ' + package_url)
|
|
filesystem.download_and_extract(SOURCE_ROOT, package_url, verbose)
|
|
os.environ['CHROMIUM_BUILDTOOLS_PATH'] = os.path.join(SRC_DIR, 'buildtools')
|
|
except urllib2.URLError as err:
|
|
print('Could not download {0}, syncing from git'.format(package_url))
|
|
gclient_sync(src_version, clean, git_cache, nohooks)
|
|
if upload_src:
|
|
try:
|
|
print('Packaging source to ' + tar_name + '.')
|
|
tar_path = os.path.join(SOURCE_ROOT, tar_name)
|
|
filesystem.safe_unlink(tar_path)
|
|
with util.scoped_cwd(SOURCE_ROOT):
|
|
tar_file = tarfile.open(tar_path, 'w:bz2')
|
|
tar_file.add('src', exclude=exclude_packaged_files)
|
|
tar_file.close()
|
|
if ('LIBCHROMIUMCONTENT_S3_ACCESS_KEY' in os.environ and
|
|
'LIBCHROMIUMCONTENT_S3_BUCKET' in os.environ and
|
|
'LIBCHROMIUMCONTENT_S3_SECRET_KEY' in os.environ):
|
|
script_path = os.path.join(SOURCE_ROOT, 'script', 'upload')
|
|
script_arguments = ['--upload_packaged_src', '--chromium_version', src_version]
|
|
print('Uploading source to ' + package_url + '.')
|
|
subprocess.check_call([sys.executable, script_path] + script_arguments)
|
|
except OSError as e:
|
|
print('Unexpected error packaging {0} in chromium source: {1}'.format(e.strerror, e.filename))
|
|
except:
|
|
print('Unexpected error downloading and extracting chromium source:', sys.exc_info()[0])
|
|
raise
|
|
|
|
|
|
def exclude_packaged_files(filename):
|
|
if ".git" in filename:
|
|
return True
|
|
else:
|
|
return filename in SRC_FILES_TO_IGNORE
|
|
|
|
if __name__ == '__main__':
|
|
import sys
|
|
sys.exit(main())
|