123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- #!/usr/bin/env python
- # Copyright 2017 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.
- from __future__ import print_function
- import hashlib
- import json
- import os
- import shutil
- import subprocess
- import sys
- import tarfile
- import tempfile
- SELF_FILE = os.path.normpath(os.path.abspath(__file__))
- REPOSITORY_ROOT = os.path.abspath(
- os.path.join(os.path.dirname(__file__), '..', '..'))
- def Run(*args):
- print('Run:', ' '.join(args))
- subprocess.check_call(args)
- def EnsureEmptyDir(path):
- if os.path.isdir(path):
- shutil.rmtree(path)
- if not os.path.exists(path):
- print('Creating directory', path)
- os.makedirs(path)
- def BuildForArch(arch):
- Run('scripts/fx', '--dir', 'out/release-{}'.format(arch), 'set',
- 'terminal.qemu-{}'.format(arch), '--args=is_debug=false',
- '--args=build_sdk_archives=true')
- Run('scripts/fx', 'build', 'sdk', 'build/images')
- def _CopyFilesIntoExistingDirectory(src, dst):
- for entry in os.listdir(src):
- src_path = os.path.join(src, entry)
- dst_path = os.path.join(dst, entry)
- if os.path.isdir(src_path):
- if not os.path.exists(dst_path):
- os.mkdir(dst_path)
- _CopyFilesIntoExistingDirectory(src_path, dst_path)
- else:
- shutil.copy(src_path, dst_path)
- def main(args):
- if len(args) == 0 or len(args) > 2 or not os.path.isdir(args[0]):
- print("""usage: %s <path_to_fuchsia_tree> [architecture]""" % SELF_FILE)
- return 1
- target_archs = []
- if len(args) > 1:
- arch = args[1]
- if arch not in ['x64', 'arm64']:
- print('Unknown architecture: ' + arch)
- print('Must be "x64" or "arm64".')
- return 1
- target_archs = [arch]
- else:
- target_archs = ['x64', 'arm64']
- # Nuke the SDK from DEPS, put our just-built one there, and set a fake .hash
- # file. This means that on next gclient runhooks, we'll restore to the
- # real DEPS-determined SDK.
- sdk_output_dir = os.path.join(REPOSITORY_ROOT, 'third_party', 'fuchsia-sdk',
- 'sdk')
- images_output_dir = os.path.join(REPOSITORY_ROOT, 'third_party',
- 'fuchsia-sdk', 'images')
- EnsureEmptyDir(sdk_output_dir)
- EnsureEmptyDir(images_output_dir)
- original_dir = os.getcwd()
- fuchsia_root = os.path.abspath(args[0])
- merged_manifest = None
- manifest_parts = set()
- # Switch to the Fuchsia tree and build the SDKs.
- os.chdir(fuchsia_root)
- for arch in target_archs:
- BuildForArch(arch)
- arch_output_dir = os.path.join(fuchsia_root, 'out', 'release-' + arch)
- sdk_tarballs = ['core.tar.gz', 'core_testing.tar.gz']
- for sdk_tar in sdk_tarballs:
- sdk_tar_path = os.path.join(arch_output_dir, 'sdk', 'archive', sdk_tar)
- sdk_gn_dir = os.path.join(arch_output_dir, 'sdk', 'gn-' + sdk_tar)
- # Process the Core SDK tarball to generate the GN SDK.
- Run('scripts/sdk/gn/generate.py', '--archive', sdk_tar_path, '--output',
- sdk_gn_dir)
- _CopyFilesIntoExistingDirectory(sdk_gn_dir, sdk_output_dir)
- # Merge the manifests.
- manifest_path = os.path.join(sdk_output_dir, 'meta', 'manifest.json')
- if os.path.isfile(manifest_path):
- manifest = json.load(open(manifest_path))
- os.remove(manifest_path)
- if not merged_manifest:
- merged_manifest = manifest
- for part in manifest['parts']:
- manifest_parts.add(part['meta'])
- else:
- for part in manifest['parts']:
- if part['meta'] not in manifest_parts:
- manifest_parts.add(part['meta'])
- merged_manifest['parts'].append(part)
- arch_image_dir = os.path.join(images_output_dir, arch, 'qemu')
- os.mkdir(os.path.join(images_output_dir, arch))
- os.mkdir(arch_image_dir)
- # Stage the image directory using entries specified in the build image
- # manifest.
- images_json = json.load(open(os.path.join(arch_output_dir, 'images.json')))
- for entry in images_json:
- if entry['type'] not in ['blk', 'zbi', 'kernel']:
- continue
- # Not all images are actually built. Only copy images with the 'archive'
- # tag.
- if not entry.get('archive'):
- continue
- shutil.copyfile(
- os.path.join(arch_output_dir, entry['path']),
- os.path.join(arch_image_dir, entry['name']) + '.' + entry['type'])
- # Write merged manifest file.
- with open(manifest_path, 'w') as manifest_file:
- json.dump(merged_manifest, manifest_file, indent=2)
- print('Hashing sysroot...')
- # Hash the sysroot to catch updates to the headers, but don't hash the whole
- # tree, as we want to avoid rebuilding all of Chromium if it's only e.g. the
- # kernel blob has changed. https://crbug.com/793956.
- sysroot_hash_obj = hashlib.sha1()
- for root, dirs, files in os.walk(os.path.join(sdk_output_dir, 'sysroot')):
- for f in files:
- path = os.path.join(root, f)
- sysroot_hash_obj.update(path)
- sysroot_hash_obj.update(open(path, 'rb').read())
- sysroot_hash = sysroot_hash_obj.hexdigest()
- hash_filename = os.path.join(sdk_output_dir, '.hash')
- with open(hash_filename, 'w') as f:
- f.write('locally-built-sdk-' + sysroot_hash)
- # Clean up.
- os.chdir(original_dir)
- return 0
- if __name__ == '__main__':
- sys.exit(main(sys.argv[1:]))
|