mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-25 22:30:49 +08:00
[Fuchsia] Replace checking out gn SDK with core
The gen_build_defs.py file is lightly modified from the original one in https://source.chromium.org/chromium/chromium/src/+/main:build/fuchsia/gen_build_defs.py to accommodate for the fact that the SDK gets downloaded into a different folder in crashpad Bug: chromium:1432399 Change-Id: I2c5a5337220b6aca138ca6eb1c37895ca32e72cd Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/4600615 Commit-Queue: Chong Gu <chonggu@google.com> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
a5e179663a
commit
87e1883047
18
DEPS
18
DEPS
@ -116,10 +116,15 @@ deps = {
|
||||
'condition': 'checkout_fuchsia and host_os == "linux"',
|
||||
'dep_type': 'cipd'
|
||||
},
|
||||
'crashpad/third_party/fuchsia-gn-sdk': {
|
||||
'url': Var('chromium_git') + '/chromium/src/third_party/fuchsia-gn-sdk.git@' +
|
||||
'0d6902558d92fe3d49ba9a8f638ddea829be595b',
|
||||
'condition': 'checkout_fuchsia',
|
||||
},
|
||||
'crashpad/third_party/fuchsia/sdk/mac-amd64': {
|
||||
'packages': [
|
||||
{
|
||||
'package': 'fuchsia/sdk/gn/mac-amd64',
|
||||
'package': 'fuchsia/sdk/core/mac-amd64',
|
||||
'version': 'latest'
|
||||
},
|
||||
],
|
||||
@ -129,7 +134,7 @@ deps = {
|
||||
'crashpad/third_party/fuchsia/sdk/linux-amd64': {
|
||||
'packages': [
|
||||
{
|
||||
'package': 'fuchsia/sdk/gn/linux-amd64',
|
||||
'package': 'fuchsia/sdk/core/linux-amd64',
|
||||
'version': 'latest'
|
||||
},
|
||||
],
|
||||
@ -249,6 +254,15 @@ hooks = [
|
||||
'crashpad/build/install_linux_sysroot.py',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'Generate Fuchsia Build Definitions',
|
||||
'pattern': '.',
|
||||
'condition': 'checkout_fuchsia',
|
||||
'action': [
|
||||
'python3',
|
||||
'crashpad/build/fuchsia/gen_build_defs.py'
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'setup_gn_ios',
|
||||
'pattern': '.',
|
||||
|
350
build/fuchsia/gen_build_defs.py
Executable file
350
build/fuchsia/gen_build_defs.py
Executable file
@ -0,0 +1,350 @@
|
||||
#!/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())
|
Loading…
x
Reference in New Issue
Block a user