blob: eea7f0905a4d81a9eb915980a3725bdab8090712 [file] [log] [blame]
Primiano Tucci34bc5592021-02-19 17:53:36 +01001#!/usr/bin/env python3
Sami Kyostila865d1d32017-12-12 18:37:04 +00002# Copyright (C) 2017 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16# This tool translates a collection of BUILD.gn files into a mostly equivalent
17# Android.bp file for the Android Soong build system. The input to the tool is a
18# JSON description of the GN build definition generated with the following
19# command:
20#
21# gn desc out --format=json --all-toolchains "//*" > desc.json
22#
23# The tool is then given a list of GN labels for which to generate Android.bp
24# build rules. The dependencies for the GN labels are squashed to the generated
25# Android.bp target, except for actions which get their own genrule. Some
26# libraries are also mapped to their Android equivalents -- see |builtin_deps|.
27
28import argparse
29import json
30import os
31import re
32import sys
Lalit Maganti27b00af2022-12-17 01:20:38 +000033from typing import Dict
Lalit Maganti921a3d62022-12-17 14:28:50 +000034from typing import List
35from typing import Optional
Sami Kyostila865d1d32017-12-12 18:37:04 +000036
Sami Kyostila3c88a1d2019-05-22 18:29:42 +010037import gn_utils
Lalit Maganti921a3d62022-12-17 14:28:50 +000038from gn_utils import GnParser
Sami Kyostila3c88a1d2019-05-22 18:29:42 +010039
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +010040from compat import itervalues
41
Florian Mayer246c1422019-09-18 15:40:38 +010042ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
43
Sami Kyostilab27619f2017-12-13 19:22:16 +000044# Arguments for the GN output directory.
Primiano Tucci9c411652019-08-27 07:13:59 +020045gn_args = ' '.join([
46 'is_debug=false',
Primiano Tucci7e05fc12019-08-27 17:29:47 +020047 'is_perfetto_build_generator=true',
Primiano Tucci9c411652019-08-27 07:13:59 +020048 'perfetto_build_with_android=true',
49 'target_cpu="arm"',
50 'target_os="android"',
51])
Sami Kyostilab27619f2017-12-13 19:22:16 +000052
Primiano Tucci02c11762019-08-30 00:57:59 +020053# Default targets to translate to the blueprint file.
54default_targets = [
55 '//:libperfetto_client_experimental',
56 '//:libperfetto',
57 '//:perfetto_integrationtests',
58 '//:perfetto_unittests',
59 '//protos/perfetto/trace:perfetto_trace_protos',
60 '//src/android_internal:libperfetto_android_internal',
Lalit Maganti52f13362023-01-23 16:38:01 +000061 '//src/base:perfetto_base_default_platform',
Daniele Di Proiettoec4864e2022-12-14 17:32:38 +000062 '//src/shared_lib:libperfetto_c',
Primiano Tucci02c11762019-08-30 00:57:59 +020063 '//src/perfetto_cmd:perfetto',
64 '//src/perfetto_cmd:trigger_perfetto',
65 '//src/profiling/memory:heapprofd_client',
Florian Mayer23f79372020-06-16 14:37:06 +020066 '//src/profiling/memory:heapprofd_client_api',
Florian Mayer72e87362020-12-11 19:37:25 +000067 '//src/profiling/memory:heapprofd_api_noop',
Primiano Tucci02c11762019-08-30 00:57:59 +020068 '//src/profiling/memory:heapprofd',
Florian Mayer50f07a62020-07-15 17:15:58 +010069 '//src/profiling/memory:heapprofd_standalone_client',
Ryan Savitski462b5db2019-11-20 19:06:46 +000070 '//src/profiling/perf:traced_perf',
Primiano Tucci02c11762019-08-30 00:57:59 +020071 '//src/traced/probes:traced_probes',
72 '//src/traced/service:traced',
Lalit Magantie0986f32020-09-17 15:35:47 +010073 '//src/trace_processor:trace_processor_shell',
Primiano Tuccifbf4a732019-12-11 00:32:15 +000074 '//test/cts:perfetto_cts_deps',
Lalit Maganti9782f492020-01-10 18:13:13 +000075 '//test/cts:perfetto_cts_jni_deps',
Primiano Tuccicbbe4802020-02-20 13:19:11 +000076 '//test:perfetto_gtest_logcat_printer',
Daniele Di Proietto55674432023-06-02 10:46:53 +000077 '//test:perfetto_end_to_end_integrationtests',
Daniele Di Proietto2e6c1062022-09-14 13:52:19 +000078 '//test/vts:perfetto_vts_deps',
Primiano Tuccif0d7ef82019-10-04 15:35:24 +010079]
80
81# Host targets
82ipc_plugin = '//src/ipc/protoc_plugin:ipc_plugin(%s)' % gn_utils.HOST_TOOLCHAIN
83protozero_plugin = '//src/protozero/protoc_plugin:protozero_plugin(%s)' % (
84 gn_utils.HOST_TOOLCHAIN)
Primiano Tucci57dd66b2019-10-15 23:09:04 +010085cppgen_plugin = '//src/protozero/protoc_plugin:cppgen_plugin(%s)' % (
86 gn_utils.HOST_TOOLCHAIN)
87
Primiano Tuccif0d7ef82019-10-04 15:35:24 +010088default_targets += [
Hector Dearmana9545e52022-05-17 12:23:25 +010089 '//src/traceconv:traceconv(%s)' % gn_utils.HOST_TOOLCHAIN,
Primiano Tuccif0d7ef82019-10-04 15:35:24 +010090 protozero_plugin,
91 ipc_plugin,
Primiano Tucci02c11762019-08-30 00:57:59 +020092]
93
Primiano Tucci02c11762019-08-30 00:57:59 +020094# Defines a custom init_rc argument to be applied to the corresponding output
95# blueprint target.
96target_initrc = {
Primiano Tuccif0d7ef82019-10-04 15:35:24 +010097 '//src/traced/service:traced': {'perfetto.rc'},
98 '//src/profiling/memory:heapprofd': {'heapprofd.rc'},
Ryan Savitski29082bf2020-02-12 15:13:51 +000099 '//src/profiling/perf:traced_perf': {'traced_perf.rc'},
Primiano Tucci02c11762019-08-30 00:57:59 +0200100}
101
102target_host_supported = [
Hector Dearman04cfac72019-09-24 22:05:55 +0100103 '//:libperfetto',
Michael Eastwood6cbbff12021-12-09 15:34:35 -0800104 '//:libperfetto_client_experimental',
Lalit Magantie0986f32020-09-17 15:35:47 +0100105 '//protos/perfetto/trace:perfetto_trace_protos',
Daniele Di Proiettoec4864e2022-12-14 17:32:38 +0000106 '//src/shared_lib:libperfetto_c',
Ryan Savitskie65c4052022-03-24 18:22:19 +0000107 '//src/trace_processor:demangle',
Lalit Magantie0986f32020-09-17 15:35:47 +0100108 '//src/trace_processor:trace_processor_shell',
A. Cody Schuffelen3c82a542023-05-22 20:11:25 -0700109 '//src/traced/probes:traced_probes',
A. Cody Schuffelenbf636942023-05-17 18:34:33 -0700110 '//src/traced/service:traced',
Primiano Tucci02c11762019-08-30 00:57:59 +0200111]
112
Michael Eastwood6cbbff12021-12-09 15:34:35 -0800113target_vendor_available = [
114 '//:libperfetto_client_experimental',
115]
116
Lalit Magantid7afbb12022-03-28 15:12:24 +0100117# Proto target groups which will be made public.
118proto_groups = {
119 'trace': [
120 '//protos/perfetto/trace:non_minimal_source_set',
121 '//protos/perfetto/trace:minimal_source_set'
122 ],
123}
124
Daniele Di Proiettocb426002023-02-16 12:14:38 +0000125needs_libfts = [
126 '//:perfetto_unittests',
127 '//src/trace_processor:trace_processor_shell',
128 '//src/traceconv:traceconv',
129]
130
Sami Kyostila865d1d32017-12-12 18:37:04 +0000131# All module names are prefixed with this string to avoid collisions.
132module_prefix = 'perfetto_'
133
134# Shared libraries which are directly translated to Android system equivalents.
Primiano Tuccia3645202020-08-03 16:28:18 +0200135shared_library_allowlist = [
Hector Dearman64f2e052019-12-04 20:51:14 +0000136 'android',
Hector Dearman92d7d112019-12-05 15:19:57 +0000137 'android.hardware.atrace@1.0',
138 'android.hardware.health@2.0',
Jack Wu40d043b2022-11-24 20:54:45 +0800139 'android.hardware.health-V2-ndk',
Hector Dearman92d7d112019-12-05 15:19:57 +0000140 'android.hardware.power.stats@1.0',
Hector Dearmanae979e02023-03-13 16:13:30 +0000141 'android.hardware.power.stats-V1-cpp',
Primiano Tucci676f0cc2018-12-03 20:03:26 +0100142 'base',
Sami Kyostilab5b71692018-01-12 12:16:44 +0000143 'binder',
Raymond Chiu8c4d9a22021-02-23 19:59:10 +0000144 'binder_ndk',
Hector Dearman92d7d112019-12-05 15:19:57 +0000145 'cutils',
Primiano Tucci676f0cc2018-12-03 20:03:26 +0100146 'hidlbase',
147 'hidltransport',
148 'hwbinder',
Ryan Savitski53ca60b2019-06-03 13:04:40 +0100149 'incident',
Sami Kyostila865d1d32017-12-12 18:37:04 +0000150 'log',
Sami Kyostilab5b71692018-01-12 12:16:44 +0000151 'services',
Hector Dearman92d7d112019-12-05 15:19:57 +0000152 'statssocket',
Hector Dearmanae979e02023-03-13 16:13:30 +0000153 'tracingproxy',
Primiano Tucciedf099c2018-01-08 18:27:56 +0000154 'utils',
Hector Dearmanff7abd42023-03-22 19:11:35 +0000155 'statspull',
Sami Kyostila865d1d32017-12-12 18:37:04 +0000156]
157
Hector Dearman92d7d112019-12-05 15:19:57 +0000158# Static libraries which are directly translated to Android system equivalents.
Primiano Tuccia3645202020-08-03 16:28:18 +0200159static_library_allowlist = [
Hector Dearman92d7d112019-12-05 15:19:57 +0000160 'statslog_perfetto',
161]
162
Sami Kyostila865d1d32017-12-12 18:37:04 +0000163# Name of the module which settings such as compiler flags for all other
164# modules.
165defaults_module = module_prefix + 'defaults'
166
167# Location of the project in the Android source tree.
168tree_path = 'external/perfetto'
169
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100170# Path for the protobuf sources in the standalone build.
171buildtools_protobuf_src = '//buildtools/protobuf/src'
172
173# Location of the protobuf src dir in the Android source tree.
174android_protobuf_src = 'external/protobuf/src'
175
Primiano Tucciedf099c2018-01-08 18:27:56 +0000176# Compiler flags which are passed through to the blueprint.
Primiano Tuccia3645202020-08-03 16:28:18 +0200177cflag_allowlist = r'^-DPERFETTO.*$'
Primiano Tucciedf099c2018-01-08 18:27:56 +0000178
Florian Mayer3d5e7e62018-01-19 15:22:46 +0000179# Compiler defines which are passed through to the blueprint.
Lalit Magantifa957e72023-03-16 18:22:23 +0000180define_allowlist = r'^(GOOGLE_PROTO.*)|(ZLIB_.*)|(USE_MMAP)$'
Florian Mayer3d5e7e62018-01-19 15:22:46 +0000181
Primiano Tucci8e627442019-08-28 07:58:38 +0200182# The directory where the generated perfetto_build_flags.h will be copied into.
183buildflags_dir = 'include/perfetto/base/build_configs/android_tree'
184
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100185def enumerate_data_deps():
186 with open(os.path.join(ROOT_DIR, 'tools', 'test_data.txt')) as f:
187 lines = f.readlines()
188 for line in (line.strip() for line in lines if not line.startswith('#')):
Andrew Shulaev576054d2020-01-23 13:44:51 +0000189 assert os.path.exists(line), 'file %s should exist' % line
Primiano Tucci02691162020-01-21 13:30:13 +0000190 if line.startswith('test/data/'):
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100191 # Skip test data files that require GCS. They are only for benchmarks.
192 # We don't run benchmarks in the android tree.
193 continue
Primiano Tucci17e8ae92021-05-17 17:40:50 +0100194 if line.endswith('/.'):
195 yield line[:-1] + '**/*'
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100196 else:
197 yield line
198
199
Florian Mayerb6a921f2018-10-18 18:55:23 +0100200# Additional arguments to apply to Android.bp rules.
201additional_args = {
Florian Mayer23f79372020-06-16 14:37:06 +0200202 'heapprofd_client_api': [
Florian Mayer23f79372020-06-16 14:37:06 +0200203 ('static_libs', {'libasync_safe'}),
Florian Mayer33159f72020-07-01 13:41:32 +0100204 # heapprofd_client_api MUST NOT have global constructors. Because it
205 # is loaded in an __attribute__((constructor)) of libc, we cannot
206 # guarantee that the global constructors get run before it is used.
207 ('cflags', {'-Wglobal-constructors', '-Werror=global-constructors'}),
Florian Mayer2131e362020-07-15 16:30:35 +0100208 ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
Florian Mayer7ed3a952021-01-08 10:55:25 +0000209 ('stubs', {
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100210 'versions': ['S'],
211 'symbol_file': 'src/profiling/memory/heapprofd_client_api.map.txt',
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000212 }),
213 ('export_include_dirs', {'src/profiling/memory/include'}),
214 ],
215 'heapprofd_api_noop': [
216 ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
217 ('stubs', {
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100218 'versions': ['S'],
219 'symbol_file': 'src/profiling/memory/heapprofd_client_api.map.txt',
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000220 }),
221 ('export_include_dirs', {'src/profiling/memory/include'}),
Florian Mayer23f79372020-06-16 14:37:06 +0200222 ],
Primiano Tucci676f0cc2018-12-03 20:03:26 +0100223 'heapprofd_client': [
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100224 ('include_dirs', {'bionic/libc'}),
225 ('static_libs', {'libasync_safe'}),
Primiano Tucci676f0cc2018-12-03 20:03:26 +0100226 ],
Florian Mayer50f07a62020-07-15 17:15:58 +0100227 'heapprofd_standalone_client': [
228 ('static_libs', {'libasync_safe'}),
229 ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000230 ('export_include_dirs', {'src/profiling/memory/include'}),
Florian Mayer23b75a42020-07-30 15:21:25 +0100231 ('stl', 'libc++_static'),
Florian Mayer50f07a62020-07-15 17:15:58 +0100232 ],
Ryan Savitski703bcab2019-12-18 14:38:14 +0000233 'perfetto_unittests': [
234 ('data', set(enumerate_data_deps())),
235 ('include_dirs', {'bionic/libc/kernel'}),
236 ],
Florian Mayerac4f4962020-09-15 10:03:22 +0100237 'perfetto_integrationtests': [
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100238 ('test_suites', {'general-tests'}),
239 ('test_config', 'PerfettoIntegrationTests.xml'),
Florian Mayerac4f4962020-09-15 10:03:22 +0100240 ],
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100241 'traced_probes': [('required', {
242 'libperfetto_android_internal', 'trigger_perfetto', 'traced_perf',
243 'mm_events'
Lalit Magantid7afbb12022-03-28 15:12:24 +0100244 }),],
245 'libperfetto_android_internal': [('static_libs', {'libhealthhalutils'}),],
Lalit Maganticdda9112019-11-27 14:19:49 +0000246 'trace_processor_shell': [
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100247 ('strip', {
248 'all': True
249 }),
250 ('host', {
251 'stl': 'libc++_static',
252 'dist': {
253 'targets': ['sdk_repo']
254 },
255 }),
Lalit Maganticdda9112019-11-27 14:19:49 +0000256 ],
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900257 'libperfetto_client_experimental': [
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100258 ('apex_available', {
259 '//apex_available:platform', 'com.android.art',
Ryan Zuklie101f1b72022-10-25 16:22:07 -0700260 'com.android.art.debug', 'com.android.tethering'
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100261 }),
Ryan Zuklie101f1b72022-10-25 16:22:07 -0700262 ('min_sdk_version', '30'),
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100263 ('shared_libs', {'liblog'}),
264 ('export_include_dirs', {'include', buildflags_dir}),
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900265 ],
Daniele Di Proiettoec4864e2022-12-14 17:32:38 +0000266 'libperfetto_c': [
267 ('min_sdk_version', '30'),
268 ('export_include_dirs', {'include'}),
269 ('cflags', {'-DPERFETTO_SHLIB_SDK_IMPLEMENTATION'}),
270 ],
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900271 'perfetto_trace_protos': [
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100272 ('apex_available', {
273 '//apex_available:platform', 'com.android.art',
274 'com.android.art.debug'
275 }),
276 ('min_sdk_version', 'S'),
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900277 ],
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100278 'libperfetto': [('export_include_dirs', {'include', buildflags_dir}),],
Florian Mayerb6a921f2018-10-18 18:55:23 +0100279}
280
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100281
Lalit Maganti52f13362023-01-23 16:38:01 +0000282def enable_base_platform(module):
283 module.srcs.add(':perfetto_base_default_platform')
284
285
Primiano Tuccifbf4a732019-12-11 00:32:15 +0000286def enable_gtest_and_gmock(module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100287 module.static_libs.add('libgmock')
Primiano Tuccifbf4a732019-12-11 00:32:15 +0000288 module.static_libs.add('libgtest')
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000289 if module.name != 'perfetto_gtest_logcat_printer':
290 module.whole_static_libs.add('perfetto_gtest_logcat_printer')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100291
Sami Kyostila865d1d32017-12-12 18:37:04 +0000292
Sami Kyostila865d1d32017-12-12 18:37:04 +0000293def enable_protobuf_full(module):
Lalit Magantia97798d2020-09-16 17:40:57 +0100294 if module.type == 'cc_binary_host':
295 module.static_libs.add('libprotobuf-cpp-full')
Lalit Magantie0986f32020-09-17 15:35:47 +0100296 elif module.host_supported:
297 module.host.static_libs.add('libprotobuf-cpp-full')
298 module.android.shared_libs.add('libprotobuf-cpp-full')
Lalit Magantia97798d2020-09-16 17:40:57 +0100299 else:
300 module.shared_libs.add('libprotobuf-cpp-full')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100301
Sami Kyostila865d1d32017-12-12 18:37:04 +0000302
Sami Kyostila865d1d32017-12-12 18:37:04 +0000303def enable_protobuf_lite(module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100304 module.shared_libs.add('libprotobuf-cpp-lite')
305
Sami Kyostila865d1d32017-12-12 18:37:04 +0000306
Sami Kyostila865d1d32017-12-12 18:37:04 +0000307def enable_protoc_lib(module):
Lalit Maganti3d415ec2019-10-23 17:53:17 +0100308 if module.type == 'cc_binary_host':
309 module.static_libs.add('libprotoc')
310 else:
311 module.shared_libs.add('libprotoc')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100312
Sami Kyostila865d1d32017-12-12 18:37:04 +0000313
Florian Mayera2fae262018-08-31 12:10:01 -0700314def enable_libunwindstack(module):
Florian Mayer50f07a62020-07-15 17:15:58 +0100315 if module.name != 'heapprofd_standalone_client':
316 module.shared_libs.add('libunwindstack')
317 module.shared_libs.add('libprocinfo')
318 module.shared_libs.add('libbase')
319 else:
320 module.static_libs.add('libunwindstack')
321 module.static_libs.add('libprocinfo')
322 module.static_libs.add('libbase')
323 module.static_libs.add('liblzma')
324 module.static_libs.add('libdexfile_support')
Lalit Magantid7afbb12022-03-28 15:12:24 +0100325 module.runtime_libs.add('libdexfile') # libdexfile_support dependency
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100326
Sami Kyostila865d1d32017-12-12 18:37:04 +0000327
328def enable_libunwind(module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100329 # libunwind is disabled on Darwin so we cannot depend on it.
330 pass
331
Sami Kyostila865d1d32017-12-12 18:37:04 +0000332
Lalit Maganti17aa2732019-02-08 15:47:26 +0000333def enable_sqlite(module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100334 if module.type == 'cc_binary_host':
335 module.static_libs.add('libsqlite')
Marcin Oczeretko1662f182022-08-18 10:29:46 +0100336 module.static_libs.add('sqlite_ext_percentile')
Lalit Magantie0986f32020-09-17 15:35:47 +0100337 elif module.host_supported:
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100338 # Copy what the sqlite3 command line tool does.
339 module.android.shared_libs.add('libsqlite')
Victor Changd0d65902022-03-10 11:54:27 +0000340 module.android.shared_libs.add('libicu')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100341 module.android.shared_libs.add('liblog')
342 module.android.shared_libs.add('libutils')
Marcin Oczeretko1662f182022-08-18 10:29:46 +0100343 module.android.static_libs.add('sqlite_ext_percentile')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100344 module.host.static_libs.add('libsqlite')
Marcin Oczeretko1662f182022-08-18 10:29:46 +0100345 module.host.static_libs.add('sqlite_ext_percentile')
Lalit Magantie0986f32020-09-17 15:35:47 +0100346 else:
347 module.shared_libs.add('libsqlite')
Victor Changd0d65902022-03-10 11:54:27 +0000348 module.shared_libs.add('libicu')
Lalit Magantie0986f32020-09-17 15:35:47 +0100349 module.shared_libs.add('liblog')
350 module.shared_libs.add('libutils')
Marcin Oczeretko1662f182022-08-18 10:29:46 +0100351 module.static_libs.add('sqlite_ext_percentile')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100352
Lalit Maganti17aa2732019-02-08 15:47:26 +0000353
Hector Dearmane0b993f2019-05-24 18:48:16 +0100354def enable_zlib(module):
Lalit Maganti3d415ec2019-10-23 17:53:17 +0100355 if module.type == 'cc_binary_host':
356 module.static_libs.add('libz')
Lalit Magantie0986f32020-09-17 15:35:47 +0100357 elif module.host_supported:
358 module.android.shared_libs.add('libz')
359 module.host.static_libs.add('libz')
Lalit Maganti3d415ec2019-10-23 17:53:17 +0100360 else:
361 module.shared_libs.add('libz')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100362
Hector Dearmane0b993f2019-05-24 18:48:16 +0100363
Ryan Savitski56bc0c62020-01-27 13:50:02 +0000364def enable_uapi_headers(module):
365 module.include_dirs.add('bionic/libc/kernel')
366
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100367
Florian Mayer682f05a2020-08-11 10:16:54 +0100368def enable_bionic_libc_platform_headers_on_android(module):
369 module.header_libs.add('bionic_libc_platform_headers')
370
Ryan Savitski56bc0c62020-01-27 13:50:02 +0000371
Sami Kyostila865d1d32017-12-12 18:37:04 +0000372# Android equivalents for third-party libraries that the upstream project
373# depends on.
374builtin_deps = {
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100375 '//gn:default_deps':
376 lambda x: None,
377 '//gn:gtest_main':
378 lambda x: None,
379 '//gn:protoc':
380 lambda x: None,
Lalit Maganti52f13362023-01-23 16:38:01 +0000381 '//gn:base_platform':
382 enable_base_platform,
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100383 '//gn:gtest_and_gmock':
384 enable_gtest_and_gmock,
385 '//gn:libunwind':
386 enable_libunwind,
387 '//gn:protobuf_full':
388 enable_protobuf_full,
389 '//gn:protobuf_lite':
390 enable_protobuf_lite,
391 '//gn:protoc_lib':
392 enable_protoc_lib,
393 '//gn:libunwindstack':
394 enable_libunwindstack,
395 '//gn:sqlite':
396 enable_sqlite,
397 '//gn:zlib':
398 enable_zlib,
399 '//gn:bionic_kernel_uapi_headers':
400 enable_uapi_headers,
Florian Mayer682f05a2020-08-11 10:16:54 +0100401 '//src/profiling/memory:bionic_libc_platform_headers_on_android':
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100402 enable_bionic_libc_platform_headers_on_android,
Sami Kyostila865d1d32017-12-12 18:37:04 +0000403}
404
405# ----------------------------------------------------------------------------
406# End of configuration.
407# ----------------------------------------------------------------------------
408
409
410class Error(Exception):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100411 pass
Sami Kyostila865d1d32017-12-12 18:37:04 +0000412
413
414class ThrowingArgumentParser(argparse.ArgumentParser):
Sami Kyostila865d1d32017-12-12 18:37:04 +0000415
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100416 def __init__(self, context):
417 super(ThrowingArgumentParser, self).__init__()
418 self.context = context
419
420 def error(self, message):
421 raise Error('%s: %s' % (self.context, message))
Sami Kyostila865d1d32017-12-12 18:37:04 +0000422
423
Lalit Magantiedace412019-06-18 13:28:28 +0100424def write_blueprint_key_value(output, name, value, sort=True):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100425 """Writes a Blueprint key-value pair to the output"""
Lalit Magantiedace412019-06-18 13:28:28 +0100426
Lalit Magantid7afbb12022-03-28 15:12:24 +0100427 if isinstance(value, bool):
428 if value:
429 output.append(' %s: true,' % name)
430 else:
431 output.append(' %s: false,' % name)
432 return
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100433 if not value:
434 return
435 if isinstance(value, set):
436 value = sorted(value)
437 if isinstance(value, list):
Colin Cross84172332021-09-14 16:41:33 -0700438 output.append(' %s: [' % name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100439 for item in sorted(value) if sort else value:
Colin Cross84172332021-09-14 16:41:33 -0700440 output.append(' "%s",' % item)
441 output.append(' ],')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100442 return
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100443 if isinstance(value, Target):
444 value.to_string(output)
445 return
Lalit Maganticdda9112019-11-27 14:19:49 +0000446 if isinstance(value, dict):
447 kv_output = []
448 for k, v in value.items():
449 write_blueprint_key_value(kv_output, k, v)
450
Colin Cross84172332021-09-14 16:41:33 -0700451 output.append(' %s: {' % name)
Lalit Maganticdda9112019-11-27 14:19:49 +0000452 for line in kv_output:
Colin Cross84172332021-09-14 16:41:33 -0700453 output.append(' %s' % line)
454 output.append(' },')
Lalit Maganticdda9112019-11-27 14:19:49 +0000455 return
Colin Cross84172332021-09-14 16:41:33 -0700456 output.append(' %s: "%s",' % (name, value))
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100457
Lalit Magantiedace412019-06-18 13:28:28 +0100458
459class Target(object):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100460 """A target-scoped part of a module"""
Lalit Magantiedace412019-06-18 13:28:28 +0100461
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100462 def __init__(self, name):
463 self.name = name
464 self.shared_libs = set()
465 self.static_libs = set()
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000466 self.whole_static_libs = set()
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100467 self.cflags = set()
Florian Mayer637513a2020-12-04 19:15:49 +0000468 self.dist = dict()
469 self.strip = dict()
Lalit Magantie0986f32020-09-17 15:35:47 +0100470 self.stl = None
Lalit Magantiedace412019-06-18 13:28:28 +0100471
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100472 def to_string(self, output):
473 nested_out = []
474 self._output_field(nested_out, 'shared_libs')
475 self._output_field(nested_out, 'static_libs')
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000476 self._output_field(nested_out, 'whole_static_libs')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100477 self._output_field(nested_out, 'cflags')
Lalit Magantie0986f32020-09-17 15:35:47 +0100478 self._output_field(nested_out, 'stl')
Florian Mayer637513a2020-12-04 19:15:49 +0000479 self._output_field(nested_out, 'dist')
480 self._output_field(nested_out, 'strip')
Lalit Magantiedace412019-06-18 13:28:28 +0100481
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100482 if nested_out:
Colin Cross84172332021-09-14 16:41:33 -0700483 output.append(' %s: {' % self.name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100484 for line in nested_out:
Colin Cross84172332021-09-14 16:41:33 -0700485 output.append(' %s' % line)
486 output.append(' },')
Lalit Magantiedace412019-06-18 13:28:28 +0100487
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100488 def _output_field(self, output, name, sort=True):
489 value = getattr(self, name)
490 return write_blueprint_key_value(output, name, value, sort)
491
Lalit Magantiedace412019-06-18 13:28:28 +0100492
Sami Kyostila865d1d32017-12-12 18:37:04 +0000493class Module(object):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100494 """A single module (e.g., cc_binary, cc_test) in a blueprint."""
Sami Kyostila865d1d32017-12-12 18:37:04 +0000495
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100496 def __init__(self, mod_type, name, gn_target):
Lalit Maganti01f9b052022-12-17 01:21:13 +0000497 assert (gn_target)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100498 self.type = mod_type
499 self.gn_target = gn_target
500 self.name = name
501 self.srcs = set()
Lalit Maganti921a3d62022-12-17 14:28:50 +0000502 self.main: Optional[str] = None
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100503 self.comment = 'GN: ' + gn_utils.label_without_toolchain(gn_target)
504 self.shared_libs = set()
505 self.static_libs = set()
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000506 self.whole_static_libs = set()
Martin Stjernholmbe2411d2021-08-26 21:15:10 +0100507 self.runtime_libs = set()
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100508 self.tools = set()
Lalit Maganti921a3d62022-12-17 14:28:50 +0000509 self.cmd: Optional[str] = None
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100510 self.host_supported = False
Michael Eastwood6cbbff12021-12-09 15:34:35 -0800511 self.vendor_available = False
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100512 self.init_rc = set()
513 self.out = set()
514 self.export_include_dirs = set()
515 self.generated_headers = set()
516 self.export_generated_headers = set()
517 self.defaults = set()
518 self.cflags = set()
519 self.include_dirs = set()
520 self.header_libs = set()
521 self.required = set()
522 self.user_debug_flag = False
Lalit Maganti921a3d62022-12-17 14:28:50 +0000523 self.tool_files: Optional[List[str]] = None
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100524 self.android = Target('android')
525 self.host = Target('host')
Daniele Di Proiettocb426002023-02-16 12:14:38 +0000526 self.musl = Target('musl')
Lalit Maganti921a3d62022-12-17 14:28:50 +0000527 self.lto: Optional[bool] = None
Lalit Maganticdda9112019-11-27 14:19:49 +0000528 self.stl = None
529 self.dist = dict()
Lalit Magantiaccd64b2020-03-16 19:54:10 +0000530 self.strip = dict()
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100531 self.data = set()
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900532 self.apex_available = set()
Primiano Tucci39097c52021-03-04 09:58:06 +0000533 self.min_sdk_version = None
Lalit Magantid7afbb12022-03-28 15:12:24 +0100534 self.proto = dict()
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100535 # The genrule_XXX below are properties that must to be propagated back
536 # on the module(s) that depend on the genrule.
537 self.genrule_headers = set()
538 self.genrule_srcs = set()
539 self.genrule_shared_libs = set()
Florian Mayer2131e362020-07-15 16:30:35 +0100540 self.version_script = None
Florian Mayerac4f4962020-09-15 10:03:22 +0100541 self.test_suites = set()
Florian Mayerab23f442021-02-09 15:37:45 +0000542 self.test_config = None
Florian Mayer7ed3a952021-01-08 10:55:25 +0000543 self.stubs = {}
Sami Kyostila865d1d32017-12-12 18:37:04 +0000544
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100545 def to_string(self, output):
546 if self.comment:
547 output.append('// %s' % self.comment)
548 output.append('%s {' % self.type)
549 self._output_field(output, 'name')
550 self._output_field(output, 'srcs')
551 self._output_field(output, 'shared_libs')
552 self._output_field(output, 'static_libs')
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000553 self._output_field(output, 'whole_static_libs')
Martin Stjernholmbe2411d2021-08-26 21:15:10 +0100554 self._output_field(output, 'runtime_libs')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100555 self._output_field(output, 'tools')
556 self._output_field(output, 'cmd', sort=False)
Lalit Magantid7afbb12022-03-28 15:12:24 +0100557 if self.host_supported:
558 self._output_field(output, 'host_supported')
559 if self.vendor_available:
560 self._output_field(output, 'vendor_available')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100561 self._output_field(output, 'init_rc')
562 self._output_field(output, 'out')
563 self._output_field(output, 'export_include_dirs')
564 self._output_field(output, 'generated_headers')
565 self._output_field(output, 'export_generated_headers')
566 self._output_field(output, 'defaults')
567 self._output_field(output, 'cflags')
568 self._output_field(output, 'include_dirs')
569 self._output_field(output, 'header_libs')
570 self._output_field(output, 'required')
Lalit Maganticdda9112019-11-27 14:19:49 +0000571 self._output_field(output, 'dist')
Lalit Magantiaccd64b2020-03-16 19:54:10 +0000572 self._output_field(output, 'strip')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100573 self._output_field(output, 'tool_files')
574 self._output_field(output, 'data')
Lalit Maganticdda9112019-11-27 14:19:49 +0000575 self._output_field(output, 'stl')
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900576 self._output_field(output, 'apex_available')
Primiano Tucci39097c52021-03-04 09:58:06 +0000577 self._output_field(output, 'min_sdk_version')
Florian Mayer2131e362020-07-15 16:30:35 +0100578 self._output_field(output, 'version_script')
Florian Mayerac4f4962020-09-15 10:03:22 +0100579 self._output_field(output, 'test_suites')
Florian Mayerab23f442021-02-09 15:37:45 +0000580 self._output_field(output, 'test_config')
Florian Mayer7ed3a952021-01-08 10:55:25 +0000581 self._output_field(output, 'stubs')
Lalit Magantid7afbb12022-03-28 15:12:24 +0100582 self._output_field(output, 'proto')
Lalit Maganti3dc8e302022-12-01 20:32:46 +0000583 self._output_field(output, 'main')
Lalit Magantid8b1a1d2018-05-23 14:41:43 +0100584
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100585 target_out = []
586 self._output_field(target_out, 'android')
587 self._output_field(target_out, 'host')
Daniele Di Proiettocb426002023-02-16 12:14:38 +0000588 self._output_field(target_out, 'musl')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100589 if target_out:
Colin Cross84172332021-09-14 16:41:33 -0700590 output.append(' target: {')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100591 for line in target_out:
Colin Cross84172332021-09-14 16:41:33 -0700592 output.append(' %s' % line)
593 output.append(' },')
Lalit Magantiedace412019-06-18 13:28:28 +0100594
Colin Cross162b48e2021-09-14 17:01:50 -0700595 if self.user_debug_flag:
Colin Cross84172332021-09-14 16:41:33 -0700596 output.append(' product_variables: {')
Colin Cross162b48e2021-09-14 17:01:50 -0700597 output.append(' debuggable: {')
598 output.append(
599 ' cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],')
600 output.append(' },')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100601 output.append(' },')
Colin Cross84172332021-09-14 16:41:33 -0700602 if self.lto is not None:
603 output.append(' target: {')
604 output.append(' android: {')
605 output.append(' lto: {')
Lalit Magantid7afbb12022-03-28 15:12:24 +0100606 output.append(' thin: %s,' %
607 'true' if self.lto else 'false')
Colin Cross84172332021-09-14 16:41:33 -0700608 output.append(' },')
609 output.append(' },')
610 output.append(' },')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100611 output.append('}')
612 output.append('')
Sami Kyostila865d1d32017-12-12 18:37:04 +0000613
Lalit Magantie0986f32020-09-17 15:35:47 +0100614 def add_android_static_lib(self, lib):
615 if self.type == 'cc_binary_host':
616 raise Exception('Adding Android static lib for host tool is unsupported')
617 elif self.host_supported:
618 self.android.static_libs.add(lib)
619 else:
620 self.static_libs.add(lib)
621
Lalit Magantie0986f32020-09-17 15:35:47 +0100622 def add_android_shared_lib(self, lib):
623 if self.type == 'cc_binary_host':
624 raise Exception('Adding Android shared lib for host tool is unsupported')
625 elif self.host_supported:
626 self.android.shared_libs.add(lib)
627 else:
628 self.shared_libs.add(lib)
629
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100630 def _output_field(self, output, name, sort=True):
631 value = getattr(self, name)
632 return write_blueprint_key_value(output, name, value, sort)
Sami Kyostila865d1d32017-12-12 18:37:04 +0000633
634
635class Blueprint(object):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100636 """In-memory representation of an Android.bp file."""
Sami Kyostila865d1d32017-12-12 18:37:04 +0000637
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100638 def __init__(self):
Lalit Maganti27b00af2022-12-17 01:20:38 +0000639 self.modules: Dict[str, Module] = {}
640 self.gn_target_to_module: Dict[str, Module] = {}
Sami Kyostila865d1d32017-12-12 18:37:04 +0000641
Lalit Maganti27b00af2022-12-17 01:20:38 +0000642 def add_module(self, module: Module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100643 """Adds a new module to the blueprint, replacing any existing module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000644 with the same name.
645
646 Args:
647 module: Module instance.
648 """
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100649 self.modules[module.name] = module
Lalit Maganti27b00af2022-12-17 01:20:38 +0000650 self.gn_target_to_module[module.gn_target] = module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000651
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100652 def to_string(self, output):
653 for m in sorted(itervalues(self.modules), key=lambda m: m.name):
654 m.to_string(output)
Sami Kyostila865d1d32017-12-12 18:37:04 +0000655
656
Lalit Maganti921a3d62022-12-17 14:28:50 +0000657def label_to_module_name(label: str):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100658 """Turn a GN label (e.g., //:perfetto_tests) into a module name."""
659 # If the label is explicibly listed in the default target list, don't prefix
660 # its name and return just the target name. This is so tools like
Hector Dearmana9545e52022-05-17 12:23:25 +0100661 # "traceconv" stay as such in the Android tree.
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100662 label_without_toolchain = gn_utils.label_without_toolchain(label)
663 if label in default_targets or label_without_toolchain in default_targets:
664 return label_without_toolchain.split(':')[-1]
Primiano Tucci02c11762019-08-30 00:57:59 +0200665
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100666 module = re.sub(r'^//:?', '', label_without_toolchain)
667 module = re.sub(r'[^a-zA-Z0-9_]', '_', module)
668 if not module.startswith(module_prefix):
669 return module_prefix + module
670 return module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000671
672
Lalit Maganti921a3d62022-12-17 14:28:50 +0000673def is_supported_source_file(name: str):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100674 """Returns True if |name| can appear in a 'srcs' list."""
675 return os.path.splitext(name)[1] in ['.c', '.cc', '.proto']
Sami Kyostila865d1d32017-12-12 18:37:04 +0000676
677
Lalit Maganti921a3d62022-12-17 14:28:50 +0000678def create_proto_modules(blueprint: Blueprint, gn: GnParser,
679 target: GnParser.Target):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100680 """Generate genrules for a proto GN target.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000681
682 GN actions are used to dynamically generate files during the build. The
683 Soong equivalent is a genrule. This function turns a specific kind of
684 genrule which turns .proto files into source and header files into a pair
Sami Kyostila71625d72017-12-18 10:29:49 +0000685 equivalent genrules.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000686
687 Args:
688 blueprint: Blueprint instance which is being generated.
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100689 target: gn_utils.Target object.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000690
691 Returns:
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100692 The source_genrule module.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000693 """
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100694 assert (target.type == 'proto_library')
Lalit Maganti117272f2020-09-11 14:01:18 +0100695
Lalit Maganti921a3d62022-12-17 14:28:50 +0000696 # We don't generate any targets for source_set proto modules because
697 # they will be inlined into other modules if required.
698 if target.proto_plugin == 'source_set':
699 return None
700
Lalit Maganti117272f2020-09-11 14:01:18 +0100701 tools = {'aprotoc'}
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100702 cpp_out_dir = '$(genDir)/%s/' % tree_path
Lalit Maganti117272f2020-09-11 14:01:18 +0100703 target_module_name = label_to_module_name(target.name)
704
705 # In GN builds the proto path is always relative to the output directory
706 # (out/tmp.xxx).
Primiano Tucci3aa027d2019-11-22 21:43:43 +0000707 cmd = ['mkdir -p %s &&' % cpp_out_dir, '$(location aprotoc)']
Lalit Maganti117272f2020-09-11 14:01:18 +0100708 cmd += ['--proto_path=%s' % tree_path]
709
Spandan Das34f1b982023-10-13 23:24:01 +0000710 tool_files = set()
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100711 if buildtools_protobuf_src in target.proto_paths:
712 cmd += ['--proto_path=%s' % android_protobuf_src]
Spandan Das34f1b982023-10-13 23:24:01 +0000713 # Add `google/protobuf/descriptor.proto` to implicit deps
714 tool_files.add(':libprotobuf-internal-descriptor-proto')
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100715
Lalit Maganti117272f2020-09-11 14:01:18 +0100716 # Descriptor targets only generate a single target.
717 if target.proto_plugin == 'descriptor':
718 out = '{}.bin'.format(target_module_name)
719
Lalit Magantife422eb2020-11-12 14:00:09 +0000720 cmd += ['--descriptor_set_out=$(out)']
Lalit Maganti117272f2020-09-11 14:01:18 +0100721 cmd += ['$(in)']
722
723 descriptor_module = Module('genrule', target_module_name, target.name)
724 descriptor_module.cmd = ' '.join(cmd)
Lalit Maganti921a3d62022-12-17 14:28:50 +0000725 descriptor_module.out.add(out)
Lalit Maganti117272f2020-09-11 14:01:18 +0100726 descriptor_module.tools = tools
727 blueprint.add_module(descriptor_module)
728
Lalit Magantife422eb2020-11-12 14:00:09 +0000729 # Recursively extract the .proto files of all the dependencies and
730 # add them to srcs.
Lalit Magantid7afbb12022-03-28 15:12:24 +0100731 descriptor_module.srcs.update(
732 gn_utils.label_to_path(src) for src in target.sources)
Spandan Das34f1b982023-10-13 23:24:01 +0000733 # Add the tool_files to srcs so that they get copied if this action is
734 # sandboxed in Soong.
735 # Add to `srcs` instead of `tool_files` (the latter will require a
736 # --proto_path that depends on Soong's sandbox implementation.)
737 descriptor_module.srcs.update(
738 src for src in tool_files)
Lalit Maganti01f9b052022-12-17 01:21:13 +0000739 for dep in target.transitive_proto_deps():
740 current_target = gn.get_target(dep.name)
Lalit Magantife422eb2020-11-12 14:00:09 +0000741 descriptor_module.srcs.update(
742 gn_utils.label_to_path(src) for src in current_target.sources)
Lalit Magantife422eb2020-11-12 14:00:09 +0000743
Lalit Maganti117272f2020-09-11 14:01:18 +0100744 return descriptor_module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000745
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100746 # We create two genrules for each proto target: one for the headers and
747 # another for the sources. This is because the module that depends on the
748 # generated files needs to declare two different types of dependencies --
749 # source files in 'srcs' and headers in 'generated_headers' -- and it's not
750 # valid to generate .h files from a source dependency and vice versa.
Spandan Das34f1b982023-10-13 23:24:01 +0000751 #
752 # We create an additional filegroup for .proto
753 # The .proto filegroup will be added to `tool_files` of rdeps so that the
754 # genrules can be sandboxed.
755
756 tool_files = set()
757 for proto_dep in target.proto_deps().union(target.transitive_proto_deps()):
758 tool_files.add(":" + label_to_module_name(proto_dep.name))
759
760 filegroup_module = Module('filegroup', target_module_name, target.name)
761 filegroup_module.srcs.update(
762 gn_utils.label_to_path(src) for src in target.sources)
763 blueprint.add_module(filegroup_module)
764
Lalit Maganti117272f2020-09-11 14:01:18 +0100765 source_module_name = target_module_name + '_gen'
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100766 source_module = Module('genrule', source_module_name, target.name)
Spandan Das34f1b982023-10-13 23:24:01 +0000767 # Add the "root" .proto filegroup to srcs
768 source_module.srcs = set([':' + target_module_name])
769 # Add the tool_files to srcs so that they get copied if this action is
770 # sandboxed in Soong.
771 # Add to `srcs` instead of `tool_files` (the latter will require a
772 # --proto_path that depends on Soong's sandbox implementation.)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100773 source_module.srcs.update(
Spandan Das34f1b982023-10-13 23:24:01 +0000774 src for src in tool_files)
775 blueprint.add_module(source_module)
Primiano Tucci20b760c2018-01-19 12:36:12 +0000776
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100777 header_module = Module('genrule', source_module_name + '_headers',
778 target.name)
779 blueprint.add_module(header_module)
780 header_module.srcs = set(source_module.srcs)
Primiano Tucci20b760c2018-01-19 12:36:12 +0000781
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100782 # TODO(primiano): at some point we should remove this. This was introduced
783 # by aosp/1108421 when adding "protos/" to .proto include paths, in order to
784 # avoid doing multi-repo changes and allow old clients in the android tree
785 # to still do the old #include "perfetto/..." rather than
786 # #include "protos/perfetto/...".
787 header_module.export_include_dirs = {'.', 'protos'}
Sami Kyostila865d1d32017-12-12 18:37:04 +0000788
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100789 source_module.genrule_srcs.add(':' + source_module.name)
790 source_module.genrule_headers.add(header_module.name)
Sami Kyostila865d1d32017-12-12 18:37:04 +0000791
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100792 if target.proto_plugin == 'proto':
Primiano Tucci3aa027d2019-11-22 21:43:43 +0000793 suffixes = ['pb']
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100794 source_module.genrule_shared_libs.add('libprotobuf-cpp-lite')
Primiano Tucci7b6a7882020-01-20 22:34:31 +0000795 cmd += ['--cpp_out=lite=true:' + cpp_out_dir]
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100796 elif target.proto_plugin == 'protozero':
797 suffixes = ['pbzero']
798 plugin = create_modules_from_target(blueprint, gn, protozero_plugin)
Lalit Maganti921a3d62022-12-17 14:28:50 +0000799 assert (plugin)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100800 tools.add(plugin.name)
801 cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
802 cmd += ['--plugin_out=wrapper_namespace=pbzero:' + cpp_out_dir]
Primiano Tucci57dd66b2019-10-15 23:09:04 +0100803 elif target.proto_plugin == 'cppgen':
804 suffixes = ['gen']
805 plugin = create_modules_from_target(blueprint, gn, cppgen_plugin)
Lalit Maganti921a3d62022-12-17 14:28:50 +0000806 assert (plugin)
Primiano Tucci57dd66b2019-10-15 23:09:04 +0100807 tools.add(plugin.name)
808 cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
Primiano Tuccie8020f92019-11-26 13:24:01 +0000809 cmd += ['--plugin_out=wrapper_namespace=gen:' + cpp_out_dir]
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100810 elif target.proto_plugin == 'ipc':
Primiano Tucci3aa027d2019-11-22 21:43:43 +0000811 suffixes = ['ipc']
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100812 plugin = create_modules_from_target(blueprint, gn, ipc_plugin)
Lalit Maganti921a3d62022-12-17 14:28:50 +0000813 assert (plugin)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100814 tools.add(plugin.name)
815 cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
Primiano Tuccie8020f92019-11-26 13:24:01 +0000816 cmd += ['--plugin_out=wrapper_namespace=gen:' + cpp_out_dir]
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100817 else:
818 raise Error('Unsupported proto plugin: %s' % target.proto_plugin)
Sami Kyostila865d1d32017-12-12 18:37:04 +0000819
Spandan Das34f1b982023-10-13 23:24:01 +0000820 cmd += ['$(locations :%s)' % target_module_name]
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100821 source_module.cmd = ' '.join(cmd)
822 header_module.cmd = source_module.cmd
823 source_module.tools = tools
824 header_module.tools = tools
Primiano Tucci20b760c2018-01-19 12:36:12 +0000825
Spandan Das34f1b982023-10-13 23:24:01 +0000826
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100827 for sfx in suffixes:
Matthew Clarkson63028d62019-10-10 15:48:23 +0100828 source_module.out.update('%s/%s' %
829 (tree_path, src.replace('.proto', '.%s.cc' % sfx))
Spandan Das34f1b982023-10-13 23:24:01 +0000830 for src in filegroup_module.srcs)
Matthew Clarkson63028d62019-10-10 15:48:23 +0100831 header_module.out.update('%s/%s' %
832 (tree_path, src.replace('.proto', '.%s.h' % sfx))
Spandan Das34f1b982023-10-13 23:24:01 +0000833 for src in filegroup_module.srcs)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100834 return source_module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000835
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100836
Lalit Maganti921a3d62022-12-17 14:28:50 +0000837def create_tp_tables_module(blueprint: Blueprint, gn: GnParser,
838 target: GnParser.Target):
Lalit Maganti3dc8e302022-12-01 20:32:46 +0000839 bp_module_name = label_to_module_name(target.name)
840 bp_binary_module_name = f'{bp_module_name}_binary'
841 srcs = [gn_utils.label_to_path(src) for src in target.sources]
842
Lalit Maganti921a3d62022-12-17 14:28:50 +0000843 binary_module = Module('python_binary_host', bp_binary_module_name,
844 target.name)
Lalit Maganti01f9b052022-12-17 01:21:13 +0000845 for dep in target.non_proto_or_source_set_deps():
846 binary_module.srcs.update([
847 gn_utils.label_to_path(src) for src in gn.get_target(dep.name).sources
848 ])
Lalit Maganti3dc8e302022-12-01 20:32:46 +0000849 binary_module.srcs.update(srcs)
850 binary_module.srcs.add('tools/gen_tp_table_headers.py')
851 binary_module.main = 'tools/gen_tp_table_headers.py'
852 blueprint.add_module(binary_module)
853
854 module = Module('genrule', bp_module_name, target.name)
855 module.tools = set([
856 bp_binary_module_name,
857 ])
858 module.cmd = ' '.join([
859 f'$(location {bp_binary_module_name})',
860 '--gen-dir=$(genDir)',
Lalit Maganti3df8a7e2023-04-25 14:18:17 +0100861 '--relative-input-dir=external/perfetto',
Lalit Maganti3dc8e302022-12-01 20:32:46 +0000862 '--inputs',
863 '$(in)',
Lalit Maganti3dc8e302022-12-01 20:32:46 +0000864 ])
865 module.out.update(target.outputs)
866 module.genrule_headers.add(module.name)
867 module.srcs.update(srcs)
868 blueprint.add_module(module)
869
870 return module
871
872
Lalit Maganti01f9b052022-12-17 01:21:13 +0000873def create_amalgamated_sql_module(blueprint: Blueprint, gn: GnParser,
874 target: GnParser.Target):
Anna Mayznercc18bfd2022-11-03 14:05:19 +0000875 bp_module_name = label_to_module_name(target.name)
Lalit Maganti358a7e42022-11-09 15:16:21 +0000876
877 def find_arg(name):
878 for i, arg in enumerate(target.args):
879 if arg.startswith(f'--{name}'):
880 return target.args[i + 1]
881
882 namespace = find_arg('namespace')
Lalit Maganti358a7e42022-11-09 15:16:21 +0000883
Anna Mayznercc18bfd2022-11-03 14:05:19 +0000884 module = Module('genrule', bp_module_name, target.name)
885 module.tool_files = [
886 'tools/gen_amalgamated_sql.py',
887 ]
888 module.cmd = ' '.join([
889 '$(location tools/gen_amalgamated_sql.py)',
Lalit Maganti358a7e42022-11-09 15:16:21 +0000890 f'--namespace={namespace}',
Lalit Maganti358a7e42022-11-09 15:16:21 +0000891 '--cpp-out=$(out)',
Anna Mayznercc18bfd2022-11-03 14:05:19 +0000892 '$(in)',
893 ])
894 module.genrule_headers.add(module.name)
895 module.out.update(target.outputs)
Lalit Maganti358a7e42022-11-09 15:16:21 +0000896
Lalit Maganti33619852022-12-17 01:22:36 +0000897 for dep in target.transitive_deps:
Rasika Navarangec3634b42023-11-14 19:45:04 +0000898 # Use globs for the chrome stdlib so the file does not need to be
899 # regenerated in autoroll CLs.
900 if dep.name.startswith(
901 '//src/trace_processor/perfetto_sql/stdlib/chrome:chrome_sql'):
902 module.srcs.add('src/trace_processor/perfetto_sql/stdlib/chrome/**/*.sql')
903 continue
Lalit Maganti358a7e42022-11-09 15:16:21 +0000904 module.srcs.update(
Lalit Maganti01f9b052022-12-17 01:21:13 +0000905 [gn_utils.label_to_path(src) for src in gn.get_target(dep.name).inputs])
Anna Mayznercc18bfd2022-11-03 14:05:19 +0000906 blueprint.add_module(module)
907 return module
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100908
Lalit Maganti358a7e42022-11-09 15:16:21 +0000909
Lalit Maganti921a3d62022-12-17 14:28:50 +0000910def create_cc_proto_descriptor_module(blueprint: Blueprint,
911 target: GnParser.Target):
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100912 bp_module_name = label_to_module_name(target.name)
913 module = Module('genrule', bp_module_name, target.name)
Lalit Maganti117272f2020-09-11 14:01:18 +0100914 module.tool_files = [
915 'tools/gen_cc_proto_descriptor.py',
916 ]
917 module.cmd = ' '.join([
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100918 '$(location tools/gen_cc_proto_descriptor.py)', '--gen_dir=$(genDir)',
919 '--cpp_out=$(out)', '$(in)'
Lalit Maganti117272f2020-09-11 14:01:18 +0100920 ])
921 module.genrule_headers.add(module.name)
922 module.srcs.update(
Lalit Maganti01f9b052022-12-17 01:21:13 +0000923 ':' + label_to_module_name(dep.name) for dep in target.proto_deps())
Hector Dearman24838932022-07-06 21:57:58 +0100924 module.srcs.update(
925 gn_utils.label_to_path(src)
926 for src in target.inputs
927 if "tmp.gn_utils" not in src)
Lalit Maganti117272f2020-09-11 14:01:18 +0100928 module.out.update(target.outputs)
929 blueprint.add_module(module)
930 return module
931
932
Lalit Maganti01f9b052022-12-17 01:21:13 +0000933def create_gen_version_module(blueprint: Blueprint, target: GnParser.Target,
934 bp_module_name: str):
Primiano Tucciec590132020-11-16 14:16:44 +0100935 module = Module('genrule', bp_module_name, gn_utils.GEN_VERSION_TARGET)
936 script_path = gn_utils.label_to_path(target.script)
937 module.genrule_headers.add(bp_module_name)
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100938 module.tool_files = [script_path]
Primiano Tucciec590132020-11-16 14:16:44 +0100939 module.out.update(target.outputs)
940 module.srcs.update(gn_utils.label_to_path(src) for src in target.inputs)
941 module.cmd = ' '.join([
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100942 'python3 $(location %s)' % script_path, '--no_git',
943 '--changelog=$(location CHANGELOG)', '--cpp_out=$(out)'
Primiano Tucciec590132020-11-16 14:16:44 +0100944 ])
945 blueprint.add_module(module)
946 return module
947
948
Lalit Maganti01f9b052022-12-17 01:21:13 +0000949def create_proto_group_modules(blueprint, gn: GnParser, module_name: str,
950 target_names):
Lalit Magantid7afbb12022-03-28 15:12:24 +0100951 # TODO(lalitm): today, we're only adding a Java lite module because that's
952 # the only one used in practice. In the future, if we need other target types
953 # (e.g. C++, Java full etc.) add them here.
954 bp_module_name = label_to_module_name(module_name) + '_java_protos'
955 module = Module('java_library', bp_module_name, bp_module_name)
956 module.comment = f'''GN: [{', '.join(target_names)}]'''
957 module.proto = {'type': 'lite', 'canonical_path_from_root': False}
958
959 for name in target_names:
960 target = gn.get_target(name)
961 module.srcs.update(gn_utils.label_to_path(src) for src in target.sources)
Lalit Maganti01f9b052022-12-17 01:21:13 +0000962 for dep_label in target.transitive_proto_deps():
963 dep = gn.get_target(dep_label.name)
Lalit Magantid7afbb12022-03-28 15:12:24 +0100964 module.srcs.update(gn_utils.label_to_path(src) for src in dep.sources)
965
966 blueprint.add_module(module)
967
968
Lalit Maganti921a3d62022-12-17 14:28:50 +0000969def _get_cflags(target: GnParser.Target):
Primiano Tuccia3645202020-08-03 16:28:18 +0200970 cflags = {flag for flag in target.cflags if re.match(cflag_allowlist, flag)}
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100971 cflags |= set("-D%s" % define
972 for define in target.defines
Primiano Tuccia3645202020-08-03 16:28:18 +0200973 if re.match(define_allowlist, define))
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100974 return cflags
Florian Mayer3d5e7e62018-01-19 15:22:46 +0000975
976
Lalit Maganti921a3d62022-12-17 14:28:50 +0000977def create_modules_from_target(blueprint: Blueprint, gn: GnParser,
978 gn_target_name: str) -> Optional[Module]:
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100979 """Generate module(s) for a given GN target.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000980
981 Given a GN target name, generate one or more corresponding modules into a
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100982 blueprint. The only case when this generates >1 module is proto libraries.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000983
984 Args:
985 blueprint: Blueprint instance which is being generated.
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100986 gn: gn_utils.GnParser object.
987 gn_target_name: GN target for module generation.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000988 """
Lalit Maganti27b00af2022-12-17 01:20:38 +0000989 if gn_target_name in blueprint.gn_target_to_module:
990 return blueprint.gn_target_to_module[gn_target_name]
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100991
Lalit Maganti27b00af2022-12-17 01:20:38 +0000992 target = gn.get_target(gn_target_name)
993 bp_module_name = label_to_module_name(gn_target_name)
Lalit Maganti9c2318c2021-05-20 16:21:41 +0100994 name_without_toolchain = gn_utils.label_without_toolchain(target.name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100995 if target.type == 'executable':
996 if target.toolchain == gn_utils.HOST_TOOLCHAIN:
997 module_type = 'cc_binary_host'
998 elif target.testonly:
999 module_type = 'cc_test'
Sami Kyostila865d1d32017-12-12 18:37:04 +00001000 else:
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001001 module_type = 'cc_binary'
1002 module = Module(module_type, bp_module_name, gn_target_name)
1003 elif target.type == 'static_library':
1004 module = Module('cc_library_static', bp_module_name, gn_target_name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001005 elif target.type == 'shared_library':
1006 module = Module('cc_library_shared', bp_module_name, gn_target_name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001007 elif target.type == 'source_set':
1008 module = Module('filegroup', bp_module_name, gn_target_name)
1009 elif target.type == 'group':
1010 # "group" targets are resolved recursively by gn_utils.get_target().
1011 # There's nothing we need to do at this level for them.
1012 return None
1013 elif target.type == 'proto_library':
1014 module = create_proto_modules(blueprint, gn, target)
Lalit Maganti117272f2020-09-11 14:01:18 +01001015 if module is None:
1016 return None
1017 elif target.type == 'action':
Lalit Maganti358a7e42022-11-09 15:16:21 +00001018 if target.custom_action_type == 'sql_amalgamation':
1019 return create_amalgamated_sql_module(blueprint, gn, target)
Lalit Maganti3dc8e302022-12-01 20:32:46 +00001020 if target.custom_action_type == 'tp_tables':
1021 return create_tp_tables_module(blueprint, gn, target)
Lalit Maganti358a7e42022-11-09 15:16:21 +00001022
Lalit Magantib417ff22022-11-09 15:45:02 +00001023 if target.custom_action_type == 'cc_proto_descriptor':
Lalit Maganti3b09a3f2020-09-14 13:28:44 +01001024 module = create_cc_proto_descriptor_module(blueprint, target)
Lalit Maganti358a7e42022-11-09 15:16:21 +00001025 elif name_without_toolchain == gn_utils.GEN_VERSION_TARGET:
Primiano Tucciec590132020-11-16 14:16:44 +01001026 module = create_gen_version_module(blueprint, target, bp_module_name)
Hector Dearmana1d75242020-10-02 09:47:24 +01001027 else:
1028 raise Error('Unhandled action: {}'.format(target.name))
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001029 else:
1030 raise Error('Unknown target %s (%s)' % (target.name, target.type))
Sami Kyostila865d1d32017-12-12 18:37:04 +00001031
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001032 blueprint.add_module(module)
Lalit Maganti9c2318c2021-05-20 16:21:41 +01001033 module.host_supported = (name_without_toolchain in target_host_supported)
Michael Eastwood6cbbff12021-12-09 15:34:35 -08001034 module.vendor_available = (name_without_toolchain in target_vendor_available)
Lalit Maganti921a3d62022-12-17 14:28:50 +00001035 module.init_rc.update(target_initrc.get(target.name, []))
Spandan Das34f1b982023-10-13 23:24:01 +00001036 if target.type != 'proto_library':
1037 # proto_library embeds a "root" filegroup in its srcs.
1038 # Skip to prevent adding dups
1039 module.srcs.update(
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001040 gn_utils.label_to_path(src)
1041 for src in target.sources
1042 if is_supported_source_file(src))
Primiano Tucci6067e732018-01-08 16:19:40 +00001043
Daniele Di Proiettocb426002023-02-16 12:14:38 +00001044 if name_without_toolchain in needs_libfts:
1045 module.musl.static_libs.add('libfts')
1046
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001047 if target.type in gn_utils.LINKER_UNIT_TYPES:
1048 module.cflags.update(_get_cflags(target))
Sami Kyostila865d1d32017-12-12 18:37:04 +00001049
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001050 module_is_compiled = module.type not in ('genrule', 'filegroup')
1051 if module_is_compiled:
1052 # Don't try to inject library/source dependencies into genrules or
1053 # filegroups because they are not compiled in the traditional sense.
Lalit Maganti921a3d62022-12-17 14:28:50 +00001054 module.defaults.update([defaults_module])
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001055 for lib in target.libs:
1056 # Generally library names should be mangled as 'libXXX', unless they
Yifan Hong0011c632021-12-02 18:37:21 -08001057 # are HAL libraries (e.g., android.hardware.health@2.0) or AIDL c++ / NDK
Raymond Chiu8c4d9a22021-02-23 19:59:10 +00001058 # libraries (e.g. "android.hardware.power.stats-V1-cpp")
Yifan Hong0011c632021-12-02 18:37:21 -08001059 android_lib = lib if '@' in lib or "-cpp" in lib or "-ndk" in lib \
1060 else 'lib' + lib
Primiano Tuccia3645202020-08-03 16:28:18 +02001061 if lib in shared_library_allowlist:
Lalit Magantie0986f32020-09-17 15:35:47 +01001062 module.add_android_shared_lib(android_lib)
Primiano Tuccia3645202020-08-03 16:28:18 +02001063 if lib in static_library_allowlist:
Lalit Magantie0986f32020-09-17 15:35:47 +01001064 module.add_android_static_lib(android_lib)
Lalit Magantic5bcd792018-01-12 18:38:11 +00001065
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001066 # If the module is a static library, export all the generated headers.
1067 if module.type == 'cc_library_static':
1068 module.export_generated_headers = module.generated_headers
Ryan Savitskie65beca2019-01-29 18:29:13 +00001069
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001070 # Merge in additional hardcoded arguments.
1071 for key, add_val in additional_args.get(module.name, []):
1072 curr = getattr(module, key)
1073 if add_val and isinstance(add_val, set) and isinstance(curr, set):
1074 curr.update(add_val)
Lalit Maganticdda9112019-11-27 14:19:49 +00001075 elif isinstance(add_val, str) and (not curr or isinstance(curr, str)):
Lalit Maganti3d415ec2019-10-23 17:53:17 +01001076 setattr(module, key, add_val)
Florian Mayerac4f4962020-09-15 10:03:22 +01001077 elif isinstance(add_val, bool) and (not curr or isinstance(curr, bool)):
1078 setattr(module, key, add_val)
Lalit Maganticdda9112019-11-27 14:19:49 +00001079 elif isinstance(add_val, dict) and isinstance(curr, dict):
1080 curr.update(add_val)
Lalit Magantie0986f32020-09-17 15:35:47 +01001081 elif isinstance(add_val, dict) and isinstance(curr, Target):
1082 curr.__dict__.update(add_val)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001083 else:
Florian Mayer5d09f5e2021-02-19 14:59:49 +00001084 raise Error('Unimplemented type %r of additional_args: %r' %
1085 (type(add_val), key))
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001086
1087 # dep_name is an unmangled GN target name (e.g. //foo:bar(toolchain)).
Lalit Maganti01f9b052022-12-17 01:21:13 +00001088 all_deps = target.non_proto_or_source_set_deps()
1089 all_deps |= target.transitive_source_set_deps()
1090 all_deps |= target.transitive_proto_deps()
1091 for dep in all_deps:
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001092 # If the dependency refers to a library which we can replace with an
1093 # Android equivalent, stop recursing and patch the dependency in.
1094 # Don't recurse into //buildtools, builtin_deps are intercepted at
1095 # the //gn:xxx level.
Lalit Maganti01f9b052022-12-17 01:21:13 +00001096 dep_name = dep.name
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001097 if dep_name.startswith('//buildtools'):
1098 continue
1099
1100 # Ignore the dependency on the gen_buildflags genrule. That is run
1101 # separately in this generator and the generated file is copied over
1102 # into the repo (see usage of |buildflags_dir| in this script).
1103 if dep_name.startswith(gn_utils.BUILDFLAGS_TARGET):
1104 continue
1105
1106 dep_module = create_modules_from_target(blueprint, gn, dep_name)
1107
1108 # For filegroups and genrule, recurse but don't apply the deps.
1109 if not module_is_compiled:
1110 continue
1111
1112 # |builtin_deps| override GN deps with Android-specific ones. See the
1113 # config in the top of this file.
1114 if gn_utils.label_without_toolchain(dep_name) in builtin_deps:
1115 builtin_deps[gn_utils.label_without_toolchain(dep_name)](module)
1116 continue
1117
1118 # Don't recurse in any other //gn dep if not handled by builtin_deps.
1119 if dep_name.startswith('//gn:'):
1120 continue
1121
1122 if dep_module is None:
1123 continue
1124 if dep_module.type == 'cc_library_shared':
1125 module.shared_libs.add(dep_module.name)
1126 elif dep_module.type == 'cc_library_static':
1127 module.static_libs.add(dep_module.name)
1128 elif dep_module.type == 'filegroup':
1129 module.srcs.add(':' + dep_module.name)
1130 elif dep_module.type == 'genrule':
1131 module.generated_headers.update(dep_module.genrule_headers)
1132 module.srcs.update(dep_module.genrule_srcs)
1133 module.shared_libs.update(dep_module.genrule_shared_libs)
Primiano Tuccie094eec2020-03-18 16:58:21 +00001134 elif dep_module.type == 'cc_binary':
1135 continue # Ignore executables deps (used by cmdline integration tests).
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001136 else:
1137 raise Error('Unknown dep %s (%s) for target %s' %
1138 (dep_module.name, dep_module.type, module.name))
1139
1140 return module
Sami Kyostila865d1d32017-12-12 18:37:04 +00001141
1142
Lalit Maganti921a3d62022-12-17 14:28:50 +00001143def create_blueprint_for_targets(gn: GnParser, targets: List[str]):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001144 """Generate a blueprint for a list of GN targets."""
1145 blueprint = Blueprint()
Sami Kyostila865d1d32017-12-12 18:37:04 +00001146
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001147 # Default settings used by all modules.
1148 defaults = Module('cc_defaults', defaults_module, '//gn:default_deps')
Sami Kyostila865d1d32017-12-12 18:37:04 +00001149
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001150 # We have to use include_dirs passing the path relative to the android tree.
1151 # This is because: (i) perfetto_cc_defaults is used also by
1152 # test/**/Android.bp; (ii) if we use local_include_dirs instead, paths
1153 # become relative to the Android.bp that *uses* cc_defaults (not the one
1154 # that defines it).s
1155 defaults.include_dirs = {
Florian Mayer5d09f5e2021-02-19 14:59:49 +00001156 tree_path, tree_path + '/include', tree_path + '/' + buildflags_dir,
1157 tree_path + '/src/profiling/memory/include'
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001158 }
Lalit Maganti921a3d62022-12-17 14:28:50 +00001159 defaults.cflags.update([
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001160 '-Wno-error=return-type',
1161 '-Wno-sign-compare',
1162 '-Wno-sign-promo',
1163 '-Wno-unused-parameter',
1164 '-fvisibility=hidden',
1165 '-O2',
Lalit Maganti921a3d62022-12-17 14:28:50 +00001166 ])
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001167 defaults.user_debug_flag = True
1168 defaults.lto = True
Sami Kyostila865d1d32017-12-12 18:37:04 +00001169
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001170 blueprint.add_module(defaults)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001171 for target in targets:
1172 create_modules_from_target(blueprint, gn, target)
1173 return blueprint
Sami Kyostila865d1d32017-12-12 18:37:04 +00001174
1175
1176def main():
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001177 parser = argparse.ArgumentParser(
1178 description='Generate Android.bp from a GN description.')
1179 parser.add_argument(
1180 '--check-only',
1181 help='Don\'t keep the generated files',
1182 action='store_true')
1183 parser.add_argument(
1184 '--desc',
Matthew Clarkson63028d62019-10-10 15:48:23 +01001185 help='GN description (e.g., gn desc out --format=json --all-toolchains "//*"'
1186 )
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001187 parser.add_argument(
1188 '--extras',
1189 help='Extra targets to include at the end of the Blueprint file',
1190 default=os.path.join(gn_utils.repo_root(), 'Android.bp.extras'),
1191 )
1192 parser.add_argument(
1193 '--output',
1194 help='Blueprint file to create',
1195 default=os.path.join(gn_utils.repo_root(), 'Android.bp'),
1196 )
1197 parser.add_argument(
1198 'targets',
1199 nargs=argparse.REMAINDER,
1200 help='Targets to include in the blueprint (e.g., "//:perfetto_tests")')
1201 args = parser.parse_args()
Sami Kyostila865d1d32017-12-12 18:37:04 +00001202
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001203 if args.desc:
1204 with open(args.desc) as f:
1205 desc = json.load(f)
1206 else:
1207 desc = gn_utils.create_build_description(gn_args)
Sami Kyostila865d1d32017-12-12 18:37:04 +00001208
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001209 gn = gn_utils.GnParser(desc)
Lalit Maganti921a3d62022-12-17 14:28:50 +00001210 blueprint = create_blueprint_for_targets(gn, args.targets or default_targets)
Alexander Timin129c37c2021-04-08 19:17:59 +00001211 project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
1212 tool_name = os.path.relpath(os.path.abspath(__file__), project_root)
Primiano Tucci916f4e52020-10-16 20:40:33 +02001213
1214 # TODO(primiano): enable this on Android after the TODO in
1215 # perfetto_component.gni is fixed.
1216 # Check for ODR violations
1217 # for target_name in default_targets:
Lalit Maganti9c2318c2021-05-20 16:21:41 +01001218 # checker = gn_utils.ODRChecker(gn, target_name)
Primiano Tucci916f4e52020-10-16 20:40:33 +02001219
Lalit Magantid7afbb12022-03-28 15:12:24 +01001220 # Add any proto groups to the blueprint.
1221 for l_name, t_names in proto_groups.items():
1222 create_proto_group_modules(blueprint, gn, l_name, t_names)
1223
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001224 output = [
1225 """// Copyright (C) 2017 The Android Open Source Project
Sami Kyostila865d1d32017-12-12 18:37:04 +00001226//
1227// Licensed under the Apache License, Version 2.0 (the "License");
1228// you may not use this file except in compliance with the License.
1229// You may obtain a copy of the License at
1230//
1231// http://www.apache.org/licenses/LICENSE-2.0
1232//
1233// Unless required by applicable law or agreed to in writing, software
1234// distributed under the License is distributed on an "AS IS" BASIS,
1235// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1236// See the License for the specific language governing permissions and
1237// limitations under the License.
1238//
1239// This file is automatically generated by %s. Do not edit.
Alexander Timin129c37c2021-04-08 19:17:59 +00001240""" % (tool_name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001241 ]
1242 blueprint.to_string(output)
1243 with open(args.extras, 'r') as r:
1244 for line in r:
1245 output.append(line.rstrip("\n\r"))
Primiano Tucci9c411652019-08-27 07:13:59 +02001246
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001247 out_files = []
Primiano Tucci9c411652019-08-27 07:13:59 +02001248
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001249 # Generate the Android.bp file.
1250 out_files.append(args.output + '.swp')
1251 with open(out_files[-1], 'w') as f:
1252 f.write('\n'.join(output))
Florian Mayerbbbd1ff2020-10-23 13:25:13 +01001253 # Text files should have a trailing EOL.
1254 f.write('\n')
Sami Kyostila865d1d32017-12-12 18:37:04 +00001255
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001256 # Generate the perfetto_build_flags.h file.
1257 out_files.append(os.path.join(buildflags_dir, 'perfetto_build_flags.h.swp'))
1258 gn_utils.gen_buildflags(gn_args, out_files[-1])
Sami Kyostila865d1d32017-12-12 18:37:04 +00001259
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001260 # Either check the contents or move the files to their final destination.
1261 return gn_utils.check_or_commit_generated_files(out_files, args.check_only)
Primiano Tucci9c411652019-08-27 07:13:59 +02001262
1263
Sami Kyostila865d1d32017-12-12 18:37:04 +00001264if __name__ == '__main__':
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001265 sys.exit(main())