From 25c079d73178428527ea2da7cf8a02033f921589 Mon Sep 17 00:00:00 2001 From: Hzj_jie Date: Wed, 5 Jun 2024 14:51:00 -0700 Subject: [PATCH] [Fuchsia] Run fuchsia-gn-sdk from chromium The latest build rules have the ffuchsia-api-level. Need https://crrev.com/c/5586319. Bug: fuchsia:42085580, fuchsia:327691011 Change-Id: I21383e02f9fff3db9405c0dbe42051122a325003 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/5585353 Commit-Queue: Zijie He Reviewed-by: Mark Mentovai --- .gitignore | 8 +- DEPS | 34 ++- build/BUILDCONFIG.gn | 8 + build/config/fuchsia/gn_configs.gni | 62 +++++ build/crashpad_buildconfig.gni | 3 + build/fuchsia/gen_build_defs.py | 350 ---------------------------- build/fuchsia_envs.py | 45 ++++ 7 files changed, 155 insertions(+), 355 deletions(-) create mode 100644 build/config/fuchsia/gn_configs.gni delete mode 100755 build/fuchsia/gen_build_defs.py create mode 100755 build/fuchsia_envs.py diff --git a/.gitignore b/.gitignore index bf9b495c..d8f0acd3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Keep sorted + *.Makefile *.ninja *.pyc @@ -19,24 +21,26 @@ *.xcodeproj *~ .*.sw? -.cache .DS_Store +.cache .gdb_history .gdbinit /Makefile +/build/fuchsia /out /third_party/edo/edo +/third_party/fuchsia-gn-sdk /third_party/fuchsia/.cipd /third_party/fuchsia/clang /third_party/fuchsia/qemu /third_party/fuchsia/sdk /third_party/googletest/googletest +/third_party/gyp/gyp /third_party/libfuzzer /third_party/linux/.cipd /third_party/linux/clang /third_party/linux/sysroot /third_party/lss/lss -/third_party/gyp/gyp /third_party/mini_chromium/mini_chromium /third_party/ninja/linux /third_party/ninja/mac* diff --git a/DEPS b/DEPS index fa7eede1..b4fe4fff 100644 --- a/DEPS +++ b/DEPS @@ -47,7 +47,7 @@ deps = { '9719c1e1e676814c456b55f5f070eabad6709d31', 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + - '5856e1ea610f6d1b47ee2e9c905498a05a1634e8', + 'bd56f6933f2fa021a44766ced638a18f477ef1c1', 'crashpad/third_party/libfuzzer/src': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' + 'fda403cf93ecb8792cb1d061564d89a6553ca020', @@ -86,6 +86,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'host_os == "win"', }, + 'crashpad/build/fuchsia': { + 'packages': [ + { + 'package': 'chromium/fuchsia/test-scripts', + 'version': 'latest', + } + ], + 'condition': 'checkout_fuchsia', + 'dep_type': 'cipd', + }, 'crashpad/third_party/linux/clang/linux-amd64': { 'packages': [ { @@ -117,9 +127,14 @@ deps = { 'dep_type': 'cipd' }, 'crashpad/third_party/fuchsia-gn-sdk': { - 'url': Var('chromium_git') + '/chromium/src/third_party/fuchsia-gn-sdk.git@' + - '0d6902558d92fe3d49ba9a8f638ddea829be595b', + 'packages': [ + { + 'package': 'chromium/fuchsia/gn-sdk', + 'version': 'latest' + }, + ], 'condition': 'checkout_fuchsia', + 'dep_type': 'cipd' }, 'crashpad/third_party/fuchsia/sdk/linux-amd64': { 'packages': [ @@ -244,12 +259,25 @@ hooks = [ 'crashpad/build/install_linux_sysroot.py', ], }, + { + # Avoid introducing unnecessary PRESUBMIT.py file from build/fuchsia. + # Never fail and ignore the error if the file does not exist. + 'name': 'Remove the PRESUBMIT.py from build/fuchsia', + 'pattern': '.', + 'condition': 'checkout_fuchsia', + 'action': [ + 'rm', + '-f', + 'crashpad/build/fuchsia/PRESUBMIT.py', + ], + }, { 'name': 'Generate Fuchsia Build Definitions', 'pattern': '.', 'condition': 'checkout_fuchsia', 'action': [ 'python3', + 'crashpad/build/fuchsia_envs.py', 'crashpad/build/fuchsia/gen_build_defs.py' ], }, diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn index f2ea1cb9..ef36cf63 100644 --- a/build/BUILDCONFIG.gn +++ b/build/BUILDCONFIG.gn @@ -69,6 +69,14 @@ if (crashpad_use_libfuzzer) { _default_configs += [ "//build/config:crashpad_fuzzer_flags" ] } +if (current_os == "fuchsia") { + _default_configs += [ + "//third_party/fuchsia-gn-sdk/src/config:compiler", + "//third_party/fuchsia-gn-sdk/src/config:runtime_library", + ] + import("//third_party/fuchsia-gn-sdk/src/gn_configs.gni") +} + _default_executable_configs = _default_configs + [ "$_mini_chromium_dir/build/config:executable", "$_mini_chromium_dir/build/config:win_console", diff --git a/build/config/fuchsia/gn_configs.gni b/build/config/fuchsia/gn_configs.gni new file mode 100644 index 00000000..6cbf4ef3 --- /dev/null +++ b/build/config/fuchsia/gn_configs.gni @@ -0,0 +1,62 @@ +# Copyright 2024 The Crashpad Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is copied from +# https://crsrc.org/c/build/config/fuchsia/gn_configs.gni?q=gn_configs.gni +# with some local modifications to match the crashpad setup. + +# Path to the fuchsia SDK. This is intended for use in other templates & +# rules to reference the contents of the fuchsia SDK. +fuchsia_sdk = "//third_party/fuchsia/sdk/linux-amd64" + +# ID uniquely identifying the Fuchsia IDK build. This is exposed as a +# property so it can be used to locate images and packages on GCS and +# as a marker to indicate the "version" of the IDK. +# Defaults to the id found in the manifest.json file of the SDK. +fuchsia_sdk_id = "" + +# The target API level for this repository. Embedders should override this +# value to specify the API level the packages produced from this repository +# should be targeting, e.g. in their top-level //.gn file. A value of -1 +# means that no API level will be passed to the tools that consumes it. +fuchsia_target_api_level = 18 + +# The SDK manifest file. This is useful to include as a dependency +# for some targets in order to cause a rebuild when the version of the +# SDK is changed. +fuchsia_sdk_manifest_file = "${fuchsia_sdk}/meta/manifest.json" + +# fuchsia_tool_dir is used to specify the directory in the SDK to locate +# tools for the host cpu architecture. If the host_cpu is not recognized, +# then tool dir defaults to x64. +fuchsia_tool_dir = "${fuchsia_sdk}/tools/${host_cpu}" + +if (fuchsia_sdk_id == "") { + # Note: If we need to expose more than just the id in the future, + # we should consider exposing the entire json object for the metadata vs. + # adding a bunch of variables. + _meta = read_file(fuchsia_sdk_manifest_file, "json") + fuchsia_sdk_id = _meta.id +} + +declare_args() { + # Specify a readelf_exec path to use. If not specified, the host's system + # executable will be used. Passed to populate_build_id_dir.py and + # prepare_package_inputs.py via the --readelf-exec flag. + # Must be a GN path (not an absolute path) since it is adjusted with + # rebase_path(). + if (!defined(fuchsia_sdk_readelf_exec)) { + fuchsia_sdk_readelf_exec = "" + } +} diff --git a/build/crashpad_buildconfig.gni b/build/crashpad_buildconfig.gni index 3d0150a2..96e81b3b 100644 --- a/build/crashpad_buildconfig.gni +++ b/build/crashpad_buildconfig.gni @@ -83,6 +83,9 @@ if (crashpad_is_in_chromium) { crashpad_is_posix = mini_chromium_is_posix crashpad_is_clang = mini_chromium_is_clang + + # fuchsia-gn-sdk from chromium uses "is_fuchsia" condition. + is_fuchsia = crashpad_is_fuchsia } crashpad_flock_always_supported = !(crashpad_is_android || crashpad_is_fuchsia) diff --git a/build/fuchsia/gen_build_defs.py b/build/fuchsia/gen_build_defs.py deleted file mode 100755 index 22414d1c..00000000 --- a/build/fuchsia/gen_build_defs.py +++ /dev/null @@ -1,350 +0,0 @@ -#!/usr/bin/env vpython3 -# Copyright 2023 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Generates a single BUILD.gn file with build targets generated using the -# manifest files in the SDK. - -import json -import logging -import os -import shutil -import sys - - -DIR_SRC_ROOT = os.path.abspath( - os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) - -def GetHostOS(): - """Get host operating system.""" - - host_platform = sys.platform - if host_platform.startswith('linux'): - return 'linux' - if host_platform.startswith('darwin'): - return 'mac' - raise Exception('Unsupported host platform: %s' % host_platform) - - -# Inserted at the top of the generated BUILD.gn file. -_GENERATED_PREAMBLE = """# DO NOT EDIT! This file was generated by -# //build/fuchsia/gen_build_def.py. -# Any changes made to this file will be discarded. - -import("//third_party/fuchsia/sdk/{host_os}-amd64/build/fidl_library.gni") -import("//third_party/fuchsia/sdk/{host_os}-amd64/build/fuchsia_sdk_pkg.gni") - -""".format(host_os=GetHostOS()) - -SDK_ROOT = os.path.join(DIR_SRC_ROOT, 'third_party', 'fuchsia', 'sdk', - f'{GetHostOS()}-amd64') - - -def ReformatTargetName(dep_name): - """"Substitutes characters in |dep_name| which are not valid in GN target - names (e.g. dots become hyphens).""" - return dep_name - - -def FormatGNTarget(fields): - """Returns a GN target definition as a string. - - |fields|: The GN fields to include in the target body. - 'target_name' and 'type' are mandatory.""" - - output = '%s("%s") {\n' % (fields['type'], fields['target_name']) - del fields['target_name'] - del fields['type'] - - # Ensure that fields with no ordering requirement are sorted. - for field in ['sources', 'public_deps']: - if field in fields: - fields[field].sort() - - for key, val in fields.items(): - if isinstance(val, str): - val_serialized = '\"%s\"' % val - elif isinstance(val, list): - # Serialize a list of strings in the prettiest possible manner. - if len(val) == 0: - val_serialized = '[]' - elif len(val) == 1: - val_serialized = '[ \"%s\" ]' % val[0] - else: - val_serialized = '[\n ' + ',\n '.join(['\"%s\"' % x - for x in val]) + '\n ]' - else: - raise Exception('Could not serialize %r' % val) - - output += ' %s = %s\n' % (key, val_serialized) - output += '}' - - return output - - -def MetaRootRelativePaths(sdk_relative_paths, meta_root): - return [os.path.relpath(path, meta_root) for path in sdk_relative_paths] - - -def ConvertCommonFields(json): - """Extracts fields from JSON manifest data which are used across all - target types. Note that FIDL packages do their own processing.""" - - meta_root = json['root'] - - converted = {'target_name': ReformatTargetName(json['name'])} - - if 'deps' in json: - converted['public_deps'] = MetaRootRelativePaths(json['deps'], - os.path.dirname(meta_root)) - - # FIDL bindings dependencies are relative to the "fidl" sub-directory. - if 'fidl_binding_deps' in json: - for entry in json['fidl_binding_deps']: - converted['public_deps'] += MetaRootRelativePaths([ - 'fidl/' + dep + ':' + os.path.basename(dep) + '_' + - entry['binding_type'] for dep in entry['deps'] - ], meta_root) - - return converted - - -def ConvertFidlLibrary(json): - """Converts a fidl_library manifest entry to a GN target. - - Arguments: - json: The parsed manifest JSON. - Returns: - The GN target definition, represented as a string.""" - - meta_root = json['root'] - - converted = ConvertCommonFields(json) - converted['type'] = 'fidl_library' - converted['sources'] = MetaRootRelativePaths(json['sources'], meta_root) - converted['library_name'] = json['name'] - - return converted - - -def ConvertCcPrebuiltLibrary(json): - """Converts a cc_prebuilt_library manifest entry to a GN target. - - Arguments: - json: The parsed manifest JSON. - Returns: - The GN target definition, represented as a string.""" - - meta_root = json['root'] - - converted = ConvertCommonFields(json) - converted['type'] = 'fuchsia_sdk_pkg' - - converted['sources'] = MetaRootRelativePaths(json['headers'], meta_root) - - converted['include_dirs'] = MetaRootRelativePaths([json['include_dir']], - meta_root) - - if json['format'] == 'shared': - converted['shared_libs'] = [json['name']] - else: - converted['static_libs'] = [json['name']] - - return converted - - -def ConvertCcSourceLibrary(json): - """Converts a cc_source_library manifest entry to a GN target. - - Arguments: - json: The parsed manifest JSON. - Returns: - The GN target definition, represented as a string.""" - - meta_root = json['root'] - - converted = ConvertCommonFields(json) - converted['type'] = 'fuchsia_sdk_pkg' - - # Headers and source file paths can be scattered across "sources", "headers", - # and "files". Merge them together into one source list. - converted['sources'] = MetaRootRelativePaths(json['sources'], meta_root) - if 'headers' in json: - converted['sources'] += MetaRootRelativePaths(json['headers'], meta_root) - if 'files' in json: - converted['sources'] += MetaRootRelativePaths(json['files'], meta_root) - converted['sources'] = list(set(converted['sources'])) - - converted['include_dirs'] = MetaRootRelativePaths([json['include_dir']], - meta_root) - - return converted - - -def ConvertLoadableModule(json): - """Converts a loadable module manifest entry to GN targets. - - Arguments: - json: The parsed manifest JSON. - Returns: - A list of GN target definitions.""" - - name = json['name'] - if name != 'vulkan_layers': - raise RuntimeError('Unsupported loadable_module: %s' % name) - - # Copy resources and binaries - resources = json['resources'] - - binaries = json['binaries'] - - def _filename_no_ext(name): - return os.path.splitext(os.path.basename(name))[0] - - # Pair each json resource with its corresponding binary. Each such pair - # is a "layer". We only need to check one arch because each arch has the - # same list of binaries. - arch = next(iter(binaries)) - binary_names = binaries[arch] - local_pkg = json['root'] - vulkan_targets = [] - - for res in resources: - layer_name = _filename_no_ext(res) - - # Filter binaries for a matching name. - filtered = [n for n in binary_names if _filename_no_ext(n) == layer_name] - - if not filtered: - # If the binary could not be found then do not generate a - # target for this layer. The missing targets will cause a - # mismatch with the "golden" outputs. - continue - - # Replace hardcoded arch in the found binary filename. - binary = filtered[0].replace('/' + arch + '/', "/${target_cpu}/") - - target = {} - target['name'] = layer_name - target['config'] = os.path.relpath(res, start=local_pkg) - target['binary'] = os.path.relpath(binary, start=local_pkg) - - vulkan_targets.append(target) - - converted = [] - all_target = {} - all_target['target_name'] = 'all' - all_target['type'] = 'group' - all_target['data_deps'] = [] - for target in vulkan_targets: - config_target = {} - config_target['target_name'] = target['name'] + '_config' - config_target['type'] = 'copy' - config_target['sources'] = [target['config']] - config_target['outputs'] = ['${root_gen_dir}/' + target['config']] - converted.append(config_target) - lib_target = {} - lib_target['target_name'] = target['name'] + '_lib' - lib_target['type'] = 'copy' - lib_target['sources'] = [target['binary']] - lib_target['outputs'] = ['${root_out_dir}/lib/{{source_file_part}}'] - converted.append(lib_target) - group_target = {} - group_target['target_name'] = target['name'] - group_target['type'] = 'group' - group_target['data_deps'] = [ - ':' + target['name'] + '_config', ':' + target['name'] + '_lib' - ] - converted.append(group_target) - all_target['data_deps'].append(':' + target['name']) - converted.append(all_target) - return converted - - -def ConvertNoOp(json): - """Null implementation of a conversion function. No output is generated.""" - - return None - - -"""Maps manifest types to conversion functions.""" -_CONVERSION_FUNCTION_MAP = { - 'fidl_library': ConvertFidlLibrary, - 'cc_source_library': ConvertCcSourceLibrary, - 'cc_prebuilt_library': ConvertCcPrebuiltLibrary, - 'loadable_module': ConvertLoadableModule, - - # No need to build targets for these types yet. - 'companion_host_tool': ConvertNoOp, - 'component_manifest': ConvertNoOp, - 'config': ConvertNoOp, - 'dart_library': ConvertNoOp, - 'data': ConvertNoOp, - 'device_profile': ConvertNoOp, - 'documentation': ConvertNoOp, - 'ffx_tool': ConvertNoOp, - 'host_tool': ConvertNoOp, - 'image': ConvertNoOp, - 'sysroot': ConvertNoOp, -} - - -def ConvertMeta(meta_path): - parsed = json.load(open(meta_path)) - if 'type' not in parsed: - return - - convert_function = _CONVERSION_FUNCTION_MAP.get(parsed['type']) - if convert_function is None: - logging.warning('Unexpected SDK artifact type %s in %s.' % - (parsed['type'], meta_path)) - return - - converted = convert_function(parsed) - if not converted: - return - output_path = os.path.join(os.path.dirname(meta_path), 'BUILD.gn') - if os.path.exists(output_path): - os.unlink(output_path) - with open(output_path, 'w') as buildfile: - buildfile.write(_GENERATED_PREAMBLE) - - # Loadable modules have multiple targets - if convert_function != ConvertLoadableModule: - buildfile.write(FormatGNTarget(converted) + '\n\n') - else: - for target in converted: - buildfile.write(FormatGNTarget(target) + '\n\n') - - -def ProcessSdkManifest(): - toplevel_meta = json.load( - open(os.path.join(SDK_ROOT, 'meta', 'manifest.json'))) - - for part in toplevel_meta['parts']: - meta_path = os.path.join(SDK_ROOT, part['meta']) - ConvertMeta(meta_path) - - -def main(): - - # Exit if there's no Fuchsia support for this platform. - try: - GetHostOS() - except: - logging.warning('Fuchsia SDK is not supported on this platform.') - return 0 - - # TODO(crbug/1432399): Remove this when links to these files inside the sdk - # directory have been redirected. - shutil.copytree(os.path.join(DIR_SRC_ROOT, 'third_party', 'fuchsia-gn-sdk', - 'src'), - os.path.join(SDK_ROOT, 'build'), - dirs_exist_ok=True) - - ProcessSdkManifest() - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/build/fuchsia_envs.py b/build/fuchsia_envs.py new file mode 100755 index 00000000..8d95b78b --- /dev/null +++ b/build/fuchsia_envs.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +# Copyright 2024 The Crashpad Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import platform +import subprocess +import sys + + +def main(args): + """ + Executes the test-scripts with required environment variables. It acts like + /usr/bin/env, but provides some extra functionality to dynamically set up + the environment variables. + + Args: + args: the command line arguments without the script name itself. + """ + os.environ['SRC_ROOT'] = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..')) + + assert platform.system() == 'Linux', 'Unsupported OS ' + platform.system() + os.environ['FUCHSIA_SDK_ROOT'] = os.path.join( + os.environ['SRC_ROOT'], 'third_party/fuchsia/sdk/linux-amd64/') + os.environ['FUCHSIA_GN_SDK_ROOT'] = os.path.join( + os.environ['SRC_ROOT'], 'third_party/fuchsia-gn-sdk/src') + + return subprocess.run(args).returncode + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:]))