blob: 89414f479bc38ecb61355854b2f374fe46a1e726 [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
Lalit Magantife422eb2020-11-12 14:00:09 +000029import collections
Sami Kyostila865d1d32017-12-12 18:37:04 +000030import json
31import os
32import re
33import sys
34
Sami Kyostila3c88a1d2019-05-22 18:29:42 +010035import gn_utils
36
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +010037from compat import itervalues
38
Florian Mayer246c1422019-09-18 15:40:38 +010039ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
40
Sami Kyostilab27619f2017-12-13 19:22:16 +000041# Arguments for the GN output directory.
Primiano Tucci9c411652019-08-27 07:13:59 +020042gn_args = ' '.join([
43 'is_debug=false',
Primiano Tucci7e05fc12019-08-27 17:29:47 +020044 'is_perfetto_build_generator=true',
Primiano Tucci9c411652019-08-27 07:13:59 +020045 'perfetto_build_with_android=true',
46 'target_cpu="arm"',
47 'target_os="android"',
48])
Sami Kyostilab27619f2017-12-13 19:22:16 +000049
Primiano Tucci02c11762019-08-30 00:57:59 +020050# Default targets to translate to the blueprint file.
51default_targets = [
52 '//:libperfetto_client_experimental',
53 '//:libperfetto',
54 '//:perfetto_integrationtests',
55 '//:perfetto_unittests',
56 '//protos/perfetto/trace:perfetto_trace_protos',
57 '//src/android_internal:libperfetto_android_internal',
58 '//src/perfetto_cmd:perfetto',
59 '//src/perfetto_cmd:trigger_perfetto',
60 '//src/profiling/memory:heapprofd_client',
Florian Mayer23f79372020-06-16 14:37:06 +020061 '//src/profiling/memory:heapprofd_client_api',
Florian Mayer72e87362020-12-11 19:37:25 +000062 '//src/profiling/memory:heapprofd_api_noop',
Primiano Tucci02c11762019-08-30 00:57:59 +020063 '//src/profiling/memory:heapprofd',
Florian Mayer50f07a62020-07-15 17:15:58 +010064 '//src/profiling/memory:heapprofd_standalone_client',
Ryan Savitski462b5db2019-11-20 19:06:46 +000065 '//src/profiling/perf:traced_perf',
Primiano Tucci02c11762019-08-30 00:57:59 +020066 '//src/traced/probes:traced_probes',
67 '//src/traced/service:traced',
Lalit Magantie0986f32020-09-17 15:35:47 +010068 '//src/trace_processor:trace_processor_shell',
Primiano Tuccifbf4a732019-12-11 00:32:15 +000069 '//test/cts:perfetto_cts_deps',
Lalit Maganti9782f492020-01-10 18:13:13 +000070 '//test/cts:perfetto_cts_jni_deps',
Primiano Tuccicbbe4802020-02-20 13:19:11 +000071 '//test:perfetto_gtest_logcat_printer',
Primiano Tuccif0d7ef82019-10-04 15:35:24 +010072]
73
74# Host targets
75ipc_plugin = '//src/ipc/protoc_plugin:ipc_plugin(%s)' % gn_utils.HOST_TOOLCHAIN
76protozero_plugin = '//src/protozero/protoc_plugin:protozero_plugin(%s)' % (
77 gn_utils.HOST_TOOLCHAIN)
Primiano Tucci57dd66b2019-10-15 23:09:04 +010078cppgen_plugin = '//src/protozero/protoc_plugin:cppgen_plugin(%s)' % (
79 gn_utils.HOST_TOOLCHAIN)
80
Primiano Tuccif0d7ef82019-10-04 15:35:24 +010081default_targets += [
Primiano Tuccif0d7ef82019-10-04 15:35:24 +010082 '//tools/trace_to_text:trace_to_text(%s)' % gn_utils.HOST_TOOLCHAIN,
83 protozero_plugin,
84 ipc_plugin,
Primiano Tucci02c11762019-08-30 00:57:59 +020085]
86
Primiano Tucci02c11762019-08-30 00:57:59 +020087# Defines a custom init_rc argument to be applied to the corresponding output
88# blueprint target.
89target_initrc = {
Primiano Tuccif0d7ef82019-10-04 15:35:24 +010090 '//src/traced/service:traced': {'perfetto.rc'},
91 '//src/profiling/memory:heapprofd': {'heapprofd.rc'},
Ryan Savitski29082bf2020-02-12 15:13:51 +000092 '//src/profiling/perf:traced_perf': {'traced_perf.rc'},
Primiano Tucci02c11762019-08-30 00:57:59 +020093}
94
95target_host_supported = [
Hector Dearman04cfac72019-09-24 22:05:55 +010096 '//:libperfetto',
Lalit Magantie0986f32020-09-17 15:35:47 +010097 '//protos/perfetto/trace:perfetto_trace_protos',
98 '//src/trace_processor:trace_processor_shell',
Primiano Tucci02c11762019-08-30 00:57:59 +020099]
100
Sami Kyostila865d1d32017-12-12 18:37:04 +0000101# All module names are prefixed with this string to avoid collisions.
102module_prefix = 'perfetto_'
103
104# Shared libraries which are directly translated to Android system equivalents.
Primiano Tuccia3645202020-08-03 16:28:18 +0200105shared_library_allowlist = [
Hector Dearman64f2e052019-12-04 20:51:14 +0000106 'android',
Hector Dearman92d7d112019-12-05 15:19:57 +0000107 'android.hardware.atrace@1.0',
108 'android.hardware.health@2.0',
109 'android.hardware.power.stats@1.0',
Primiano Tucci676f0cc2018-12-03 20:03:26 +0100110 'base',
Sami Kyostilab5b71692018-01-12 12:16:44 +0000111 'binder',
Hector Dearman92d7d112019-12-05 15:19:57 +0000112 'cutils',
Primiano Tucci676f0cc2018-12-03 20:03:26 +0100113 'hidlbase',
114 'hidltransport',
115 'hwbinder',
Ryan Savitski53ca60b2019-06-03 13:04:40 +0100116 'incident',
Sami Kyostila865d1d32017-12-12 18:37:04 +0000117 'log',
Sami Kyostilab5b71692018-01-12 12:16:44 +0000118 'services',
Hector Dearman92d7d112019-12-05 15:19:57 +0000119 'statssocket',
Collin Fijalkovichef96fb72021-01-06 16:14:33 -0800120 "tracingproxy",
Primiano Tucciedf099c2018-01-08 18:27:56 +0000121 'utils',
Sami Kyostila865d1d32017-12-12 18:37:04 +0000122]
123
Hector Dearman92d7d112019-12-05 15:19:57 +0000124# Static libraries which are directly translated to Android system equivalents.
Primiano Tuccia3645202020-08-03 16:28:18 +0200125static_library_allowlist = [
Hector Dearman92d7d112019-12-05 15:19:57 +0000126 'statslog_perfetto',
127]
128
Sami Kyostila865d1d32017-12-12 18:37:04 +0000129# Name of the module which settings such as compiler flags for all other
130# modules.
131defaults_module = module_prefix + 'defaults'
132
133# Location of the project in the Android source tree.
134tree_path = 'external/perfetto'
135
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100136# Path for the protobuf sources in the standalone build.
137buildtools_protobuf_src = '//buildtools/protobuf/src'
138
139# Location of the protobuf src dir in the Android source tree.
140android_protobuf_src = 'external/protobuf/src'
141
Primiano Tucciedf099c2018-01-08 18:27:56 +0000142# Compiler flags which are passed through to the blueprint.
Primiano Tuccia3645202020-08-03 16:28:18 +0200143cflag_allowlist = r'^-DPERFETTO.*$'
Primiano Tucciedf099c2018-01-08 18:27:56 +0000144
Florian Mayer3d5e7e62018-01-19 15:22:46 +0000145# Compiler defines which are passed through to the blueprint.
Primiano Tuccia3645202020-08-03 16:28:18 +0200146define_allowlist = r'^(GOOGLE_PROTO.*)|(ZLIB_.*)|(USE_MMAP)|(HAVE_HIDDEN)$'
Florian Mayer3d5e7e62018-01-19 15:22:46 +0000147
Logan Chien9bfaaf92018-02-13 18:49:24 +0800148# Shared libraries which are not in PDK.
149library_not_in_pdk = {
150 'libandroid',
151 'libservices',
152}
153
Primiano Tucci8e627442019-08-28 07:58:38 +0200154# The directory where the generated perfetto_build_flags.h will be copied into.
155buildflags_dir = 'include/perfetto/base/build_configs/android_tree'
156
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100157
158def enumerate_data_deps():
159 with open(os.path.join(ROOT_DIR, 'tools', 'test_data.txt')) as f:
160 lines = f.readlines()
161 for line in (line.strip() for line in lines if not line.startswith('#')):
Andrew Shulaev576054d2020-01-23 13:44:51 +0000162 assert os.path.exists(line), 'file %s should exist' % line
Primiano Tucci02691162020-01-21 13:30:13 +0000163 if line.startswith('test/data/'):
164 # Skip test data files that require GCS. They are only for benchmarks.
165 # We don't run benchmarks in the android tree.
166 continue
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100167 if line.endswith('/'):
168 yield line + '**/*'
169 else:
170 yield line
171
172
Florian Mayerb6a921f2018-10-18 18:55:23 +0100173# Additional arguments to apply to Android.bp rules.
174additional_args = {
Florian Mayer23f79372020-06-16 14:37:06 +0200175 'heapprofd_client_api': [
Florian Mayer23f79372020-06-16 14:37:06 +0200176 ('static_libs', {'libasync_safe'}),
Florian Mayer33159f72020-07-01 13:41:32 +0100177 # heapprofd_client_api MUST NOT have global constructors. Because it
178 # is loaded in an __attribute__((constructor)) of libc, we cannot
179 # guarantee that the global constructors get run before it is used.
180 ('cflags', {'-Wglobal-constructors', '-Werror=global-constructors'}),
Florian Mayer2131e362020-07-15 16:30:35 +0100181 ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
Florian Mayer7ed3a952021-01-08 10:55:25 +0000182 ('stubs', {
183 'versions': ['S'],
184 'symbol_file': 'src/profiling/memory/heapprofd_client_api.map.txt',
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000185 }),
186 ('export_include_dirs', {'src/profiling/memory/include'}),
187 ],
188 'heapprofd_api_noop': [
189 ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
190 ('stubs', {
191 'versions': ['S'],
192 'symbol_file': 'src/profiling/memory/heapprofd_client_api.map.txt',
193 }),
194 ('export_include_dirs', {'src/profiling/memory/include'}),
Florian Mayer23f79372020-06-16 14:37:06 +0200195 ],
Primiano Tucci676f0cc2018-12-03 20:03:26 +0100196 'heapprofd_client': [
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100197 ('include_dirs', {'bionic/libc'}),
198 ('static_libs', {'libasync_safe'}),
Primiano Tucci676f0cc2018-12-03 20:03:26 +0100199 ],
Florian Mayer50f07a62020-07-15 17:15:58 +0100200 'heapprofd_standalone_client': [
201 ('static_libs', {'libasync_safe'}),
202 ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000203 ('export_include_dirs', {'src/profiling/memory/include'}),
Florian Mayer23b75a42020-07-30 15:21:25 +0100204 ('stl', 'libc++_static'),
Florian Mayer50f07a62020-07-15 17:15:58 +0100205 ],
Ryan Savitski703bcab2019-12-18 14:38:14 +0000206 'perfetto_unittests': [
207 ('data', set(enumerate_data_deps())),
208 ('include_dirs', {'bionic/libc/kernel'}),
209 ],
Florian Mayerac4f4962020-09-15 10:03:22 +0100210 'perfetto_integrationtests': [
Florian Mayerac4f4962020-09-15 10:03:22 +0100211 ('test_suites', {'general-tests'}),
Florian Mayerab23f442021-02-09 15:37:45 +0000212 ('test_config', 'PerfettoIntegrationTests.xml'),
Florian Mayerac4f4962020-09-15 10:03:22 +0100213 ],
Matthew Clarkson63028d62019-10-10 15:48:23 +0100214 'traced_probes': [
Ryan Savitski29082bf2020-02-12 15:13:51 +0000215 ('required', {'libperfetto_android_internal',
216 'trigger_perfetto',
217 'traced_perf'}),
Matthew Clarkson63028d62019-10-10 15:48:23 +0100218 ],
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100219 'libperfetto_android_internal': [('static_libs', {'libhealthhalutils'}),],
Lalit Maganticdda9112019-11-27 14:19:49 +0000220 'trace_processor_shell': [
Lalit Maganti1eebcca2021-01-13 12:40:45 +0000221 ('strip', {'all': True}),
Lalit Magantie0986f32020-09-17 15:35:47 +0100222 ('host', {
Florian Mayer637513a2020-12-04 19:15:49 +0000223 'stl': 'libc++_static',
Florian Mayer637513a2020-12-04 19:15:49 +0000224 'dist': {'targets': ['sdk_repo']},
Lalit Magantie0986f32020-09-17 15:35:47 +0100225 }),
Lalit Maganticdda9112019-11-27 14:19:49 +0000226 ],
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900227 'libperfetto_client_experimental': [
228 ('apex_available', {
229 '//apex_available:platform',
Martin Stjernholm0b8c5422020-10-12 15:11:12 +0100230 'com.android.art',
231 'com.android.art.debug'}),
Nicolas Geoffray542864d2020-10-09 11:12:45 +0100232 ('shared_libs', {'liblog'}),
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000233 ('export_include_dirs', {'include', buildflags_dir}),
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900234 ],
235 'perfetto_trace_protos': [
236 ('apex_available', {
237 '//apex_available:platform',
Martin Stjernholm0b8c5422020-10-12 15:11:12 +0100238 'com.android.art',
239 'com.android.art.debug'}),
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900240 ],
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000241 'libperfetto': [
242 ('export_include_dirs', {'include', buildflags_dir}),
243 ],
Florian Mayerb6a921f2018-10-18 18:55:23 +0100244}
245
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100246
Primiano Tuccifbf4a732019-12-11 00:32:15 +0000247def enable_gtest_and_gmock(module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100248 module.static_libs.add('libgmock')
Primiano Tuccifbf4a732019-12-11 00:32:15 +0000249 module.static_libs.add('libgtest')
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000250 if module.name != 'perfetto_gtest_logcat_printer':
251 module.whole_static_libs.add('perfetto_gtest_logcat_printer')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100252
Sami Kyostila865d1d32017-12-12 18:37:04 +0000253
Sami Kyostila865d1d32017-12-12 18:37:04 +0000254def enable_protobuf_full(module):
Lalit Magantia97798d2020-09-16 17:40:57 +0100255 if module.type == 'cc_binary_host':
256 module.static_libs.add('libprotobuf-cpp-full')
Lalit Magantie0986f32020-09-17 15:35:47 +0100257 elif module.host_supported:
258 module.host.static_libs.add('libprotobuf-cpp-full')
259 module.android.shared_libs.add('libprotobuf-cpp-full')
Lalit Magantia97798d2020-09-16 17:40:57 +0100260 else:
261 module.shared_libs.add('libprotobuf-cpp-full')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100262
Sami Kyostila865d1d32017-12-12 18:37:04 +0000263
Sami Kyostila865d1d32017-12-12 18:37:04 +0000264def enable_protobuf_lite(module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100265 module.shared_libs.add('libprotobuf-cpp-lite')
266
Sami Kyostila865d1d32017-12-12 18:37:04 +0000267
Sami Kyostila865d1d32017-12-12 18:37:04 +0000268def enable_protoc_lib(module):
Lalit Maganti3d415ec2019-10-23 17:53:17 +0100269 if module.type == 'cc_binary_host':
270 module.static_libs.add('libprotoc')
271 else:
272 module.shared_libs.add('libprotoc')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100273
Sami Kyostila865d1d32017-12-12 18:37:04 +0000274
Florian Mayera2fae262018-08-31 12:10:01 -0700275def enable_libunwindstack(module):
Florian Mayer50f07a62020-07-15 17:15:58 +0100276 if module.name != 'heapprofd_standalone_client':
277 module.shared_libs.add('libunwindstack')
278 module.shared_libs.add('libprocinfo')
279 module.shared_libs.add('libbase')
280 else:
281 module.static_libs.add('libunwindstack')
282 module.static_libs.add('libprocinfo')
283 module.static_libs.add('libbase')
284 module.static_libs.add('liblzma')
285 module.static_libs.add('libdexfile_support')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100286
Sami Kyostila865d1d32017-12-12 18:37:04 +0000287
288def enable_libunwind(module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100289 # libunwind is disabled on Darwin so we cannot depend on it.
290 pass
291
Sami Kyostila865d1d32017-12-12 18:37:04 +0000292
Lalit Maganti17aa2732019-02-08 15:47:26 +0000293def enable_sqlite(module):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100294 if module.type == 'cc_binary_host':
295 module.static_libs.add('libsqlite')
Lalit Magantie0986f32020-09-17 15:35:47 +0100296 elif module.host_supported:
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100297 # Copy what the sqlite3 command line tool does.
298 module.android.shared_libs.add('libsqlite')
299 module.android.shared_libs.add('libandroidicu')
300 module.android.shared_libs.add('liblog')
301 module.android.shared_libs.add('libutils')
302 module.host.static_libs.add('libsqlite')
Lalit Magantie0986f32020-09-17 15:35:47 +0100303 else:
304 module.shared_libs.add('libsqlite')
305 module.shared_libs.add('libandroidicu')
306 module.shared_libs.add('liblog')
307 module.shared_libs.add('libutils')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100308
Lalit Maganti17aa2732019-02-08 15:47:26 +0000309
Hector Dearmane0b993f2019-05-24 18:48:16 +0100310def enable_zlib(module):
Lalit Maganti3d415ec2019-10-23 17:53:17 +0100311 if module.type == 'cc_binary_host':
312 module.static_libs.add('libz')
Lalit Magantie0986f32020-09-17 15:35:47 +0100313 elif module.host_supported:
314 module.android.shared_libs.add('libz')
315 module.host.static_libs.add('libz')
Lalit Maganti3d415ec2019-10-23 17:53:17 +0100316 else:
317 module.shared_libs.add('libz')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100318
Hector Dearmane0b993f2019-05-24 18:48:16 +0100319
Ryan Savitski56bc0c62020-01-27 13:50:02 +0000320def enable_uapi_headers(module):
321 module.include_dirs.add('bionic/libc/kernel')
322
Florian Mayer682f05a2020-08-11 10:16:54 +0100323def enable_bionic_libc_platform_headers_on_android(module):
324 module.header_libs.add('bionic_libc_platform_headers')
325
Ryan Savitski56bc0c62020-01-27 13:50:02 +0000326
Sami Kyostila865d1d32017-12-12 18:37:04 +0000327# Android equivalents for third-party libraries that the upstream project
328# depends on.
329builtin_deps = {
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100330 '//gn:default_deps': lambda x: None,
331 '//gn:gtest_main': lambda x: None,
332 '//gn:protoc': lambda x: None,
Primiano Tuccifbf4a732019-12-11 00:32:15 +0000333 '//gn:gtest_and_gmock': enable_gtest_and_gmock,
Primiano Tuccib7ebffd2019-09-09 07:42:35 -0700334 '//gn:libunwind': enable_libunwind,
335 '//gn:protobuf_full': enable_protobuf_full,
336 '//gn:protobuf_lite': enable_protobuf_lite,
337 '//gn:protoc_lib': enable_protoc_lib,
338 '//gn:libunwindstack': enable_libunwindstack,
339 '//gn:sqlite': enable_sqlite,
340 '//gn:zlib': enable_zlib,
Ryan Savitski56bc0c62020-01-27 13:50:02 +0000341 '//gn:bionic_kernel_uapi_headers' : enable_uapi_headers,
Florian Mayer682f05a2020-08-11 10:16:54 +0100342 '//src/profiling/memory:bionic_libc_platform_headers_on_android':
343 enable_bionic_libc_platform_headers_on_android,
Sami Kyostila865d1d32017-12-12 18:37:04 +0000344}
345
346# ----------------------------------------------------------------------------
347# End of configuration.
348# ----------------------------------------------------------------------------
349
350
351class Error(Exception):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100352 pass
Sami Kyostila865d1d32017-12-12 18:37:04 +0000353
354
355class ThrowingArgumentParser(argparse.ArgumentParser):
Sami Kyostila865d1d32017-12-12 18:37:04 +0000356
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100357 def __init__(self, context):
358 super(ThrowingArgumentParser, self).__init__()
359 self.context = context
360
361 def error(self, message):
362 raise Error('%s: %s' % (self.context, message))
Sami Kyostila865d1d32017-12-12 18:37:04 +0000363
364
Lalit Magantiedace412019-06-18 13:28:28 +0100365def write_blueprint_key_value(output, name, value, sort=True):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100366 """Writes a Blueprint key-value pair to the output"""
Lalit Magantiedace412019-06-18 13:28:28 +0100367
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100368 if not value:
369 return
370 if isinstance(value, set):
371 value = sorted(value)
372 if isinstance(value, list):
373 output.append(' %s: [' % name)
374 for item in sorted(value) if sort else value:
375 output.append(' "%s",' % item)
376 output.append(' ],')
377 return
378 if isinstance(value, bool):
379 output.append(' %s: true,' % name)
380 return
381 if isinstance(value, Target):
382 value.to_string(output)
383 return
Lalit Maganticdda9112019-11-27 14:19:49 +0000384 if isinstance(value, dict):
385 kv_output = []
386 for k, v in value.items():
387 write_blueprint_key_value(kv_output, k, v)
388
389 output.append(' %s: {' % name)
390 for line in kv_output:
391 output.append(' %s' % line)
392 output.append(' },')
393 return
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100394 output.append(' %s: "%s",' % (name, value))
395
Lalit Magantiedace412019-06-18 13:28:28 +0100396
397class Target(object):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100398 """A target-scoped part of a module"""
Lalit Magantiedace412019-06-18 13:28:28 +0100399
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100400 def __init__(self, name):
401 self.name = name
402 self.shared_libs = set()
403 self.static_libs = set()
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000404 self.whole_static_libs = set()
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100405 self.cflags = set()
Florian Mayer637513a2020-12-04 19:15:49 +0000406 self.dist = dict()
407 self.strip = dict()
Lalit Magantie0986f32020-09-17 15:35:47 +0100408 self.stl = None
Lalit Magantiedace412019-06-18 13:28:28 +0100409
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100410 def to_string(self, output):
411 nested_out = []
412 self._output_field(nested_out, 'shared_libs')
413 self._output_field(nested_out, 'static_libs')
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000414 self._output_field(nested_out, 'whole_static_libs')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100415 self._output_field(nested_out, 'cflags')
Lalit Magantie0986f32020-09-17 15:35:47 +0100416 self._output_field(nested_out, 'stl')
Florian Mayer637513a2020-12-04 19:15:49 +0000417 self._output_field(nested_out, 'dist')
418 self._output_field(nested_out, 'strip')
Lalit Magantiedace412019-06-18 13:28:28 +0100419
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100420 if nested_out:
421 output.append(' %s: {' % self.name)
422 for line in nested_out:
423 output.append(' %s' % line)
424 output.append(' },')
Lalit Magantiedace412019-06-18 13:28:28 +0100425
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100426 def _output_field(self, output, name, sort=True):
427 value = getattr(self, name)
428 return write_blueprint_key_value(output, name, value, sort)
429
Lalit Magantiedace412019-06-18 13:28:28 +0100430
Sami Kyostila865d1d32017-12-12 18:37:04 +0000431class Module(object):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100432 """A single module (e.g., cc_binary, cc_test) in a blueprint."""
Sami Kyostila865d1d32017-12-12 18:37:04 +0000433
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100434 def __init__(self, mod_type, name, gn_target):
435 self.type = mod_type
436 self.gn_target = gn_target
437 self.name = name
438 self.srcs = set()
439 self.comment = 'GN: ' + gn_utils.label_without_toolchain(gn_target)
440 self.shared_libs = set()
441 self.static_libs = set()
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000442 self.whole_static_libs = set()
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100443 self.tools = set()
444 self.cmd = None
445 self.host_supported = False
446 self.init_rc = set()
447 self.out = set()
448 self.export_include_dirs = set()
449 self.generated_headers = set()
450 self.export_generated_headers = set()
451 self.defaults = set()
452 self.cflags = set()
453 self.include_dirs = set()
454 self.header_libs = set()
455 self.required = set()
456 self.user_debug_flag = False
457 self.tool_files = None
458 self.android = Target('android')
459 self.host = Target('host')
460 self.lto = None
Lalit Maganticdda9112019-11-27 14:19:49 +0000461 self.stl = None
462 self.dist = dict()
Lalit Magantiaccd64b2020-03-16 19:54:10 +0000463 self.strip = dict()
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100464 self.data = set()
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900465 self.apex_available = set()
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100466 # The genrule_XXX below are properties that must to be propagated back
467 # on the module(s) that depend on the genrule.
468 self.genrule_headers = set()
469 self.genrule_srcs = set()
470 self.genrule_shared_libs = set()
Florian Mayer2131e362020-07-15 16:30:35 +0100471 self.version_script = None
Florian Mayerac4f4962020-09-15 10:03:22 +0100472 self.test_suites = set()
Florian Mayerab23f442021-02-09 15:37:45 +0000473 self.test_config = None
Florian Mayer7ed3a952021-01-08 10:55:25 +0000474 self.stubs = {}
Sami Kyostila865d1d32017-12-12 18:37:04 +0000475
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100476 def to_string(self, output):
477 if self.comment:
478 output.append('// %s' % self.comment)
479 output.append('%s {' % self.type)
480 self._output_field(output, 'name')
481 self._output_field(output, 'srcs')
482 self._output_field(output, 'shared_libs')
483 self._output_field(output, 'static_libs')
Primiano Tuccicbbe4802020-02-20 13:19:11 +0000484 self._output_field(output, 'whole_static_libs')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100485 self._output_field(output, 'tools')
486 self._output_field(output, 'cmd', sort=False)
487 self._output_field(output, 'host_supported')
488 self._output_field(output, 'init_rc')
489 self._output_field(output, 'out')
490 self._output_field(output, 'export_include_dirs')
491 self._output_field(output, 'generated_headers')
492 self._output_field(output, 'export_generated_headers')
493 self._output_field(output, 'defaults')
494 self._output_field(output, 'cflags')
495 self._output_field(output, 'include_dirs')
496 self._output_field(output, 'header_libs')
497 self._output_field(output, 'required')
Lalit Maganticdda9112019-11-27 14:19:49 +0000498 self._output_field(output, 'dist')
Lalit Magantiaccd64b2020-03-16 19:54:10 +0000499 self._output_field(output, 'strip')
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100500 self._output_field(output, 'tool_files')
501 self._output_field(output, 'data')
Lalit Maganticdda9112019-11-27 14:19:49 +0000502 self._output_field(output, 'stl')
Jiyong Parkd5ea0112020-04-28 18:22:00 +0900503 self._output_field(output, 'apex_available')
Florian Mayer2131e362020-07-15 16:30:35 +0100504 self._output_field(output, 'version_script')
Florian Mayerac4f4962020-09-15 10:03:22 +0100505 self._output_field(output, 'test_suites')
Florian Mayerab23f442021-02-09 15:37:45 +0000506 self._output_field(output, 'test_config')
Florian Mayer7ed3a952021-01-08 10:55:25 +0000507 self._output_field(output, 'stubs')
Lalit Magantid8b1a1d2018-05-23 14:41:43 +0100508
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100509 target_out = []
510 self._output_field(target_out, 'android')
511 self._output_field(target_out, 'host')
512 if target_out:
513 output.append(' target: {')
514 for line in target_out:
515 output.append(' %s' % line)
516 output.append(' },')
Lalit Magantiedace412019-06-18 13:28:28 +0100517
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100518 disable_pdk = any(name in library_not_in_pdk for name in self.shared_libs)
519 if self.user_debug_flag or disable_pdk:
520 output.append(' product_variables: {')
521 if disable_pdk:
522 output.append(' pdk: {')
523 output.append(' enabled: false,')
524 output.append(' },')
525 if self.user_debug_flag:
526 output.append(' debuggable: {')
527 output.append(
528 ' cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],')
529 output.append(' },')
530 output.append(' },')
531 if self.lto is not None:
532 output.append(' target: {')
533 output.append(' android: {')
534 output.append(' lto: {')
535 output.append(' thin: %s,' % 'true' if self.lto else 'false')
536 output.append(' },')
537 output.append(' },')
538 output.append(' },')
539 output.append('}')
540 output.append('')
Sami Kyostila865d1d32017-12-12 18:37:04 +0000541
Lalit Magantie0986f32020-09-17 15:35:47 +0100542
543 def add_android_static_lib(self, lib):
544 if self.type == 'cc_binary_host':
545 raise Exception('Adding Android static lib for host tool is unsupported')
546 elif self.host_supported:
547 self.android.static_libs.add(lib)
548 else:
549 self.static_libs.add(lib)
550
551
552 def add_android_shared_lib(self, lib):
553 if self.type == 'cc_binary_host':
554 raise Exception('Adding Android shared lib for host tool is unsupported')
555 elif self.host_supported:
556 self.android.shared_libs.add(lib)
557 else:
558 self.shared_libs.add(lib)
559
560
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100561 def _output_field(self, output, name, sort=True):
562 value = getattr(self, name)
563 return write_blueprint_key_value(output, name, value, sort)
Sami Kyostila865d1d32017-12-12 18:37:04 +0000564
565
566class Blueprint(object):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100567 """In-memory representation of an Android.bp file."""
Sami Kyostila865d1d32017-12-12 18:37:04 +0000568
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100569 def __init__(self):
570 self.modules = {}
Sami Kyostila865d1d32017-12-12 18:37:04 +0000571
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100572 def add_module(self, module):
573 """Adds a new module to the blueprint, replacing any existing module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000574 with the same name.
575
576 Args:
577 module: Module instance.
578 """
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100579 self.modules[module.name] = module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000580
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100581 def to_string(self, output):
582 for m in sorted(itervalues(self.modules), key=lambda m: m.name):
583 m.to_string(output)
Sami Kyostila865d1d32017-12-12 18:37:04 +0000584
585
Sami Kyostila865d1d32017-12-12 18:37:04 +0000586def label_to_module_name(label):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100587 """Turn a GN label (e.g., //:perfetto_tests) into a module name."""
588 # If the label is explicibly listed in the default target list, don't prefix
589 # its name and return just the target name. This is so tools like
590 # "trace_to_text" stay as such in the Android tree.
591 label_without_toolchain = gn_utils.label_without_toolchain(label)
592 if label in default_targets or label_without_toolchain in default_targets:
593 return label_without_toolchain.split(':')[-1]
Primiano Tucci02c11762019-08-30 00:57:59 +0200594
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100595 module = re.sub(r'^//:?', '', label_without_toolchain)
596 module = re.sub(r'[^a-zA-Z0-9_]', '_', module)
597 if not module.startswith(module_prefix):
598 return module_prefix + module
599 return module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000600
601
Sami Kyostila865d1d32017-12-12 18:37:04 +0000602def is_supported_source_file(name):
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100603 """Returns True if |name| can appear in a 'srcs' list."""
604 return os.path.splitext(name)[1] in ['.c', '.cc', '.proto']
Sami Kyostila865d1d32017-12-12 18:37:04 +0000605
606
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100607def create_proto_modules(blueprint, gn, target):
608 """Generate genrules for a proto GN target.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000609
610 GN actions are used to dynamically generate files during the build. The
611 Soong equivalent is a genrule. This function turns a specific kind of
612 genrule which turns .proto files into source and header files into a pair
Sami Kyostila71625d72017-12-18 10:29:49 +0000613 equivalent genrules.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000614
615 Args:
616 blueprint: Blueprint instance which is being generated.
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100617 target: gn_utils.Target object.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000618
619 Returns:
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100620 The source_genrule module.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000621 """
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100622 assert (target.type == 'proto_library')
Lalit Maganti117272f2020-09-11 14:01:18 +0100623
624 tools = {'aprotoc'}
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100625 cpp_out_dir = '$(genDir)/%s/' % tree_path
Lalit Maganti117272f2020-09-11 14:01:18 +0100626 target_module_name = label_to_module_name(target.name)
627
628 # In GN builds the proto path is always relative to the output directory
629 # (out/tmp.xxx).
Primiano Tucci3aa027d2019-11-22 21:43:43 +0000630 cmd = ['mkdir -p %s &&' % cpp_out_dir, '$(location aprotoc)']
Lalit Maganti117272f2020-09-11 14:01:18 +0100631 cmd += ['--proto_path=%s' % tree_path]
632
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100633 if buildtools_protobuf_src in target.proto_paths:
634 cmd += ['--proto_path=%s' % android_protobuf_src]
635
Lalit Maganti117272f2020-09-11 14:01:18 +0100636 # We don't generate any targets for source_set proto modules because
637 # they will be inlined into other modules if required.
638 if target.proto_plugin == 'source_set':
639 return None
640
641 # Descriptor targets only generate a single target.
642 if target.proto_plugin == 'descriptor':
643 out = '{}.bin'.format(target_module_name)
644
Lalit Magantife422eb2020-11-12 14:00:09 +0000645 cmd += ['--descriptor_set_out=$(out)']
Lalit Maganti117272f2020-09-11 14:01:18 +0100646 cmd += ['$(in)']
647
648 descriptor_module = Module('genrule', target_module_name, target.name)
649 descriptor_module.cmd = ' '.join(cmd)
650 descriptor_module.out = [out]
651 descriptor_module.tools = tools
652 blueprint.add_module(descriptor_module)
653
Lalit Magantife422eb2020-11-12 14:00:09 +0000654 # Recursively extract the .proto files of all the dependencies and
655 # add them to srcs.
656 target_queue = collections.deque([target.name])
657 seen_targets = set()
658 while target_queue:
659 dep = target_queue.popleft()
660 if dep in seen_targets:
661 continue
662 seen_targets.add(dep)
663
664 current_target = gn.get_target(dep)
665 descriptor_module.srcs.update(
666 gn_utils.label_to_path(src) for src in current_target.sources)
667 target_queue.extend(current_target.proto_deps)
668
Lalit Maganti117272f2020-09-11 14:01:18 +0100669 return descriptor_module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000670
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100671 # We create two genrules for each proto target: one for the headers and
672 # another for the sources. This is because the module that depends on the
673 # generated files needs to declare two different types of dependencies --
674 # source files in 'srcs' and headers in 'generated_headers' -- and it's not
675 # valid to generate .h files from a source dependency and vice versa.
Lalit Maganti117272f2020-09-11 14:01:18 +0100676 source_module_name = target_module_name + '_gen'
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100677 source_module = Module('genrule', source_module_name, target.name)
678 blueprint.add_module(source_module)
679 source_module.srcs.update(
680 gn_utils.label_to_path(src) for src in target.sources)
Primiano Tucci20b760c2018-01-19 12:36:12 +0000681
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100682 header_module = Module('genrule', source_module_name + '_headers',
683 target.name)
684 blueprint.add_module(header_module)
685 header_module.srcs = set(source_module.srcs)
Primiano Tucci20b760c2018-01-19 12:36:12 +0000686
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100687 # TODO(primiano): at some point we should remove this. This was introduced
688 # by aosp/1108421 when adding "protos/" to .proto include paths, in order to
689 # avoid doing multi-repo changes and allow old clients in the android tree
690 # to still do the old #include "perfetto/..." rather than
691 # #include "protos/perfetto/...".
692 header_module.export_include_dirs = {'.', 'protos'}
Sami Kyostila865d1d32017-12-12 18:37:04 +0000693
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100694 source_module.genrule_srcs.add(':' + source_module.name)
695 source_module.genrule_headers.add(header_module.name)
Sami Kyostila865d1d32017-12-12 18:37:04 +0000696
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100697 if target.proto_plugin == 'proto':
Primiano Tucci3aa027d2019-11-22 21:43:43 +0000698 suffixes = ['pb']
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100699 source_module.genrule_shared_libs.add('libprotobuf-cpp-lite')
Primiano Tucci7b6a7882020-01-20 22:34:31 +0000700 cmd += ['--cpp_out=lite=true:' + cpp_out_dir]
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100701 elif target.proto_plugin == 'protozero':
702 suffixes = ['pbzero']
703 plugin = create_modules_from_target(blueprint, gn, protozero_plugin)
704 tools.add(plugin.name)
705 cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
706 cmd += ['--plugin_out=wrapper_namespace=pbzero:' + cpp_out_dir]
Primiano Tucci57dd66b2019-10-15 23:09:04 +0100707 elif target.proto_plugin == 'cppgen':
708 suffixes = ['gen']
709 plugin = create_modules_from_target(blueprint, gn, cppgen_plugin)
710 tools.add(plugin.name)
711 cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
Primiano Tuccie8020f92019-11-26 13:24:01 +0000712 cmd += ['--plugin_out=wrapper_namespace=gen:' + cpp_out_dir]
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100713 elif target.proto_plugin == 'ipc':
Primiano Tucci3aa027d2019-11-22 21:43:43 +0000714 suffixes = ['ipc']
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100715 plugin = create_modules_from_target(blueprint, gn, ipc_plugin)
716 tools.add(plugin.name)
717 cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
Primiano Tuccie8020f92019-11-26 13:24:01 +0000718 cmd += ['--plugin_out=wrapper_namespace=gen:' + cpp_out_dir]
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100719 else:
720 raise Error('Unsupported proto plugin: %s' % target.proto_plugin)
Sami Kyostila865d1d32017-12-12 18:37:04 +0000721
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100722 cmd += ['$(in)']
723 source_module.cmd = ' '.join(cmd)
724 header_module.cmd = source_module.cmd
725 source_module.tools = tools
726 header_module.tools = tools
Primiano Tucci20b760c2018-01-19 12:36:12 +0000727
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100728 for sfx in suffixes:
Matthew Clarkson63028d62019-10-10 15:48:23 +0100729 source_module.out.update('%s/%s' %
730 (tree_path, src.replace('.proto', '.%s.cc' % sfx))
731 for src in source_module.srcs)
732 header_module.out.update('%s/%s' %
733 (tree_path, src.replace('.proto', '.%s.h' % sfx))
734 for src in header_module.srcs)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100735 return source_module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000736
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100737
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100738def create_merged_sql_metrics_module(blueprint, target):
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100739 bp_module_name = label_to_module_name(target.name)
740 module = Module('genrule', bp_module_name, target.name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100741 module.tool_files = [
742 'tools/gen_merged_sql_metrics.py',
743 ]
744 module.cmd = ' '.join([
745 '$(location tools/gen_merged_sql_metrics.py)',
746 '--cpp_out=$(out)',
747 '$(in)',
748 ])
Lalit Maganti117272f2020-09-11 14:01:18 +0100749 module.genrule_headers.add(module.name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100750 module.out.update(target.outputs)
751 module.srcs.update(gn_utils.label_to_path(src) for src in target.inputs)
752 blueprint.add_module(module)
753 return module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000754
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100755
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100756def create_cc_proto_descriptor_module(blueprint, target):
757 bp_module_name = label_to_module_name(target.name)
758 module = Module('genrule', bp_module_name, target.name)
Lalit Maganti117272f2020-09-11 14:01:18 +0100759 module.tool_files = [
760 'tools/gen_cc_proto_descriptor.py',
761 ]
762 module.cmd = ' '.join([
763 '$(location tools/gen_cc_proto_descriptor.py)',
764 '--gen_dir=$(genDir)',
765 '--cpp_out=$(out)',
766 '$(in)'
767 ])
768 module.genrule_headers.add(module.name)
769 module.srcs.update(
770 ':' + label_to_module_name(dep) for dep in target.proto_deps)
771 module.out.update(target.outputs)
772 blueprint.add_module(module)
773 return module
774
775
Primiano Tucciec590132020-11-16 14:16:44 +0100776def create_gen_version_module(blueprint, target, bp_module_name):
777 module = Module('genrule', bp_module_name, gn_utils.GEN_VERSION_TARGET)
778 script_path = gn_utils.label_to_path(target.script)
779 module.genrule_headers.add(bp_module_name)
780 module.tool_files = [ script_path ]
781 module.out.update(target.outputs)
782 module.srcs.update(gn_utils.label_to_path(src) for src in target.inputs)
783 module.cmd = ' '.join([
784 'python3 $(location %s)' % script_path,
785 '--no_git',
Primiano Tuccif0ed1d42020-11-18 16:30:18 +0100786 '--changelog=$(location CHANGELOG)',
Primiano Tucciec590132020-11-16 14:16:44 +0100787 '--cpp_out=$(out)'
788 ])
789 blueprint.add_module(module)
790 return module
791
792
Florian Mayer3d5e7e62018-01-19 15:22:46 +0000793def _get_cflags(target):
Primiano Tuccia3645202020-08-03 16:28:18 +0200794 cflags = {flag for flag in target.cflags if re.match(cflag_allowlist, flag)}
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100795 cflags |= set("-D%s" % define
796 for define in target.defines
Primiano Tuccia3645202020-08-03 16:28:18 +0200797 if re.match(define_allowlist, define))
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100798 return cflags
Florian Mayer3d5e7e62018-01-19 15:22:46 +0000799
800
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100801def create_modules_from_target(blueprint, gn, gn_target_name):
802 """Generate module(s) for a given GN target.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000803
804 Given a GN target name, generate one or more corresponding modules into a
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100805 blueprint. The only case when this generates >1 module is proto libraries.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000806
807 Args:
808 blueprint: Blueprint instance which is being generated.
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100809 gn: gn_utils.GnParser object.
810 gn_target_name: GN target for module generation.
Sami Kyostila865d1d32017-12-12 18:37:04 +0000811 """
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100812 bp_module_name = label_to_module_name(gn_target_name)
813 if bp_module_name in blueprint.modules:
814 return blueprint.modules[bp_module_name]
815 target = gn.get_target(gn_target_name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100816
817 if target.type == 'executable':
818 if target.toolchain == gn_utils.HOST_TOOLCHAIN:
819 module_type = 'cc_binary_host'
820 elif target.testonly:
821 module_type = 'cc_test'
Sami Kyostila865d1d32017-12-12 18:37:04 +0000822 else:
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100823 module_type = 'cc_binary'
824 module = Module(module_type, bp_module_name, gn_target_name)
825 elif target.type == 'static_library':
826 module = Module('cc_library_static', bp_module_name, gn_target_name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100827 elif target.type == 'shared_library':
828 module = Module('cc_library_shared', bp_module_name, gn_target_name)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100829 elif target.type == 'source_set':
830 module = Module('filegroup', bp_module_name, gn_target_name)
831 elif target.type == 'group':
832 # "group" targets are resolved recursively by gn_utils.get_target().
833 # There's nothing we need to do at this level for them.
834 return None
835 elif target.type == 'proto_library':
836 module = create_proto_modules(blueprint, gn, target)
Lalit Maganti117272f2020-09-11 14:01:18 +0100837 if module is None:
838 return None
839 elif target.type == 'action':
840 if 'gen_merged_sql_metrics' in target.name:
841 module = create_merged_sql_metrics_module(blueprint, target)
Hector Dearmana1d75242020-10-02 09:47:24 +0100842 elif re.match('.*gen_cc_.*_descriptor$', target.name):
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100843 module = create_cc_proto_descriptor_module(blueprint, target)
Primiano Tucciec590132020-11-16 14:16:44 +0100844 elif target.type == 'action' and gn_utils.label_without_toolchain(
845 target.name) == gn_utils.GEN_VERSION_TARGET:
846 module = create_gen_version_module(blueprint, target, bp_module_name)
Hector Dearmana1d75242020-10-02 09:47:24 +0100847 else:
848 raise Error('Unhandled action: {}'.format(target.name))
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100849 else:
850 raise Error('Unknown target %s (%s)' % (target.name, target.type))
Sami Kyostila865d1d32017-12-12 18:37:04 +0000851
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100852 blueprint.add_module(module)
Primiano Tucci916f4e52020-10-16 20:40:33 +0200853 module.host_supported = (gn_utils.label_without_toolchain(target.name) in
854 target_host_supported)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100855 module.init_rc = target_initrc.get(target.name, [])
856 module.srcs.update(
857 gn_utils.label_to_path(src)
858 for src in target.sources
859 if is_supported_source_file(src))
Primiano Tucci6067e732018-01-08 16:19:40 +0000860
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100861 if target.type in gn_utils.LINKER_UNIT_TYPES:
862 module.cflags.update(_get_cflags(target))
Sami Kyostila865d1d32017-12-12 18:37:04 +0000863
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100864 module_is_compiled = module.type not in ('genrule', 'filegroup')
865 if module_is_compiled:
866 # Don't try to inject library/source dependencies into genrules or
867 # filegroups because they are not compiled in the traditional sense.
868 module.defaults = [defaults_module]
869 for lib in target.libs:
870 # Generally library names should be mangled as 'libXXX', unless they
871 # are HAL libraries (e.g., android.hardware.health@2.0).
872 android_lib = lib if '@' in lib else 'lib' + lib
Primiano Tuccia3645202020-08-03 16:28:18 +0200873 if lib in shared_library_allowlist:
Lalit Magantie0986f32020-09-17 15:35:47 +0100874 module.add_android_shared_lib(android_lib)
Primiano Tuccia3645202020-08-03 16:28:18 +0200875 if lib in static_library_allowlist:
Lalit Magantie0986f32020-09-17 15:35:47 +0100876 module.add_android_static_lib(android_lib)
Lalit Magantic5bcd792018-01-12 18:38:11 +0000877
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100878 # If the module is a static library, export all the generated headers.
879 if module.type == 'cc_library_static':
880 module.export_generated_headers = module.generated_headers
Ryan Savitskie65beca2019-01-29 18:29:13 +0000881
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100882 # Merge in additional hardcoded arguments.
883 for key, add_val in additional_args.get(module.name, []):
884 curr = getattr(module, key)
885 if add_val and isinstance(add_val, set) and isinstance(curr, set):
886 curr.update(add_val)
Lalit Maganticdda9112019-11-27 14:19:49 +0000887 elif isinstance(add_val, str) and (not curr or isinstance(curr, str)):
Lalit Maganti3d415ec2019-10-23 17:53:17 +0100888 setattr(module, key, add_val)
Florian Mayerac4f4962020-09-15 10:03:22 +0100889 elif isinstance(add_val, bool) and (not curr or isinstance(curr, bool)):
890 setattr(module, key, add_val)
Lalit Maganticdda9112019-11-27 14:19:49 +0000891 elif isinstance(add_val, dict) and isinstance(curr, dict):
892 curr.update(add_val)
Lalit Magantie0986f32020-09-17 15:35:47 +0100893 elif isinstance(add_val, dict) and isinstance(curr, Target):
894 curr.__dict__.update(add_val)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100895 else:
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000896 raise Error('Unimplemented type %r of additional_args: %r' %
897 (type(add_val), key))
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100898
899 # dep_name is an unmangled GN target name (e.g. //foo:bar(toolchain)).
900 for dep_name in target.deps | target.source_set_deps | target.proto_deps:
901 # If the dependency refers to a library which we can replace with an
902 # Android equivalent, stop recursing and patch the dependency in.
903 # Don't recurse into //buildtools, builtin_deps are intercepted at
904 # the //gn:xxx level.
905 if dep_name.startswith('//buildtools'):
906 continue
907
908 # Ignore the dependency on the gen_buildflags genrule. That is run
909 # separately in this generator and the generated file is copied over
910 # into the repo (see usage of |buildflags_dir| in this script).
911 if dep_name.startswith(gn_utils.BUILDFLAGS_TARGET):
912 continue
913
914 dep_module = create_modules_from_target(blueprint, gn, dep_name)
915
916 # For filegroups and genrule, recurse but don't apply the deps.
917 if not module_is_compiled:
918 continue
919
920 # |builtin_deps| override GN deps with Android-specific ones. See the
921 # config in the top of this file.
922 if gn_utils.label_without_toolchain(dep_name) in builtin_deps:
923 builtin_deps[gn_utils.label_without_toolchain(dep_name)](module)
924 continue
925
926 # Don't recurse in any other //gn dep if not handled by builtin_deps.
927 if dep_name.startswith('//gn:'):
928 continue
929
930 if dep_module is None:
931 continue
932 if dep_module.type == 'cc_library_shared':
933 module.shared_libs.add(dep_module.name)
934 elif dep_module.type == 'cc_library_static':
935 module.static_libs.add(dep_module.name)
936 elif dep_module.type == 'filegroup':
937 module.srcs.add(':' + dep_module.name)
938 elif dep_module.type == 'genrule':
939 module.generated_headers.update(dep_module.genrule_headers)
940 module.srcs.update(dep_module.genrule_srcs)
941 module.shared_libs.update(dep_module.genrule_shared_libs)
Primiano Tuccie094eec2020-03-18 16:58:21 +0000942 elif dep_module.type == 'cc_binary':
943 continue # Ignore executables deps (used by cmdline integration tests).
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100944 else:
945 raise Error('Unknown dep %s (%s) for target %s' %
946 (dep_module.name, dep_module.type, module.name))
947
948 return module
Sami Kyostila865d1d32017-12-12 18:37:04 +0000949
950
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100951def create_blueprint_for_targets(gn, desc, targets):
952 """Generate a blueprint for a list of GN targets."""
953 blueprint = Blueprint()
Sami Kyostila865d1d32017-12-12 18:37:04 +0000954
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100955 # Default settings used by all modules.
956 defaults = Module('cc_defaults', defaults_module, '//gn:default_deps')
Sami Kyostila865d1d32017-12-12 18:37:04 +0000957
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100958 # We have to use include_dirs passing the path relative to the android tree.
959 # This is because: (i) perfetto_cc_defaults is used also by
960 # test/**/Android.bp; (ii) if we use local_include_dirs instead, paths
961 # become relative to the Android.bp that *uses* cc_defaults (not the one
962 # that defines it).s
963 defaults.include_dirs = {
Florian Mayer5d09f5e2021-02-19 14:59:49 +0000964 tree_path, tree_path + '/include', tree_path + '/' + buildflags_dir,
965 tree_path + '/src/profiling/memory/include'
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100966 }
967 defaults.cflags = [
968 '-Wno-error=return-type',
969 '-Wno-sign-compare',
970 '-Wno-sign-promo',
971 '-Wno-unused-parameter',
972 '-fvisibility=hidden',
973 '-O2',
974 ]
975 defaults.user_debug_flag = True
976 defaults.lto = True
Sami Kyostila865d1d32017-12-12 18:37:04 +0000977
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100978 blueprint.add_module(defaults)
979 gn = gn_utils.GnParser(desc)
980 for target in targets:
981 create_modules_from_target(blueprint, gn, target)
982 return blueprint
Sami Kyostila865d1d32017-12-12 18:37:04 +0000983
984
985def main():
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100986 parser = argparse.ArgumentParser(
987 description='Generate Android.bp from a GN description.')
988 parser.add_argument(
989 '--check-only',
990 help='Don\'t keep the generated files',
991 action='store_true')
992 parser.add_argument(
993 '--desc',
Matthew Clarkson63028d62019-10-10 15:48:23 +0100994 help='GN description (e.g., gn desc out --format=json --all-toolchains "//*"'
995 )
Primiano Tuccif0d7ef82019-10-04 15:35:24 +0100996 parser.add_argument(
997 '--extras',
998 help='Extra targets to include at the end of the Blueprint file',
999 default=os.path.join(gn_utils.repo_root(), 'Android.bp.extras'),
1000 )
1001 parser.add_argument(
1002 '--output',
1003 help='Blueprint file to create',
1004 default=os.path.join(gn_utils.repo_root(), 'Android.bp'),
1005 )
1006 parser.add_argument(
1007 'targets',
1008 nargs=argparse.REMAINDER,
1009 help='Targets to include in the blueprint (e.g., "//:perfetto_tests")')
1010 args = parser.parse_args()
Sami Kyostila865d1d32017-12-12 18:37:04 +00001011
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001012 if args.desc:
1013 with open(args.desc) as f:
1014 desc = json.load(f)
1015 else:
1016 desc = gn_utils.create_build_description(gn_args)
Sami Kyostila865d1d32017-12-12 18:37:04 +00001017
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001018 gn = gn_utils.GnParser(desc)
1019 blueprint = create_blueprint_for_targets(gn, desc, args.targets or
1020 default_targets)
Primiano Tucci916f4e52020-10-16 20:40:33 +02001021
1022 # TODO(primiano): enable this on Android after the TODO in
1023 # perfetto_component.gni is fixed.
1024 # Check for ODR violations
1025 # for target_name in default_targets:
1026 # checker = gn_utils.ODRChecker(gn, target_name)
1027
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001028 output = [
1029 """// Copyright (C) 2017 The Android Open Source Project
Sami Kyostila865d1d32017-12-12 18:37:04 +00001030//
1031// Licensed under the Apache License, Version 2.0 (the "License");
1032// you may not use this file except in compliance with the License.
1033// You may obtain a copy of the License at
1034//
1035// http://www.apache.org/licenses/LICENSE-2.0
1036//
1037// Unless required by applicable law or agreed to in writing, software
1038// distributed under the License is distributed on an "AS IS" BASIS,
1039// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1040// See the License for the specific language governing permissions and
1041// limitations under the License.
1042//
1043// This file is automatically generated by %s. Do not edit.
1044""" % (__file__)
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001045 ]
1046 blueprint.to_string(output)
1047 with open(args.extras, 'r') as r:
1048 for line in r:
1049 output.append(line.rstrip("\n\r"))
Primiano Tucci9c411652019-08-27 07:13:59 +02001050
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001051 out_files = []
Primiano Tucci9c411652019-08-27 07:13:59 +02001052
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001053 # Generate the Android.bp file.
1054 out_files.append(args.output + '.swp')
1055 with open(out_files[-1], 'w') as f:
1056 f.write('\n'.join(output))
Florian Mayerbbbd1ff2020-10-23 13:25:13 +01001057 # Text files should have a trailing EOL.
1058 f.write('\n')
Sami Kyostila865d1d32017-12-12 18:37:04 +00001059
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001060 # Generate the perfetto_build_flags.h file.
1061 out_files.append(os.path.join(buildflags_dir, 'perfetto_build_flags.h.swp'))
1062 gn_utils.gen_buildflags(gn_args, out_files[-1])
Sami Kyostila865d1d32017-12-12 18:37:04 +00001063
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001064 # Either check the contents or move the files to their final destination.
1065 return gn_utils.check_or_commit_generated_files(out_files, args.check_only)
Primiano Tucci9c411652019-08-27 07:13:59 +02001066
1067
Sami Kyostila865d1d32017-12-12 18:37:04 +00001068if __name__ == '__main__':
Primiano Tuccif0d7ef82019-10-04 15:35:24 +01001069 sys.exit(main())