1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import("//build/config/jumbo.gni") 6 7# TODO(rockot): Maybe we can factor these dependencies out of //mojo. They're 8# used to conditionally enable message ID scrambling in a way which is 9# consistent across toolchains and which is affected by branded vs non-branded 10# Chrome builds. Ideally we could create some generic knobs here that could be 11# flipped elsewhere though. 12import("//build/config/chrome_build.gni") 13import("//build/config/nacl/config.gni") 14import("//components/nacl/features.gni") 15import("//third_party/jinja2/jinja2.gni") 16import("//tools/ipc_fuzzer/ipc_fuzzer.gni") 17 18declare_args() { 19 # Indicates whether typemapping should be supported in this build 20 # configuration. This may be disabled when building external projects which 21 # depend on //mojo but which do not need/want all of the Chromium tree 22 # dependencies that come with typemapping. 23 # 24 # Note that (perhaps obviously) a huge amount of Chromium code will not build 25 # with typemapping disabled, so it is never valid to set this to |false| in 26 # any Chromium build configuration. 27 enable_mojom_typemapping = true 28 29 # Controls message ID scrambling behavior. If |true|, message IDs are 30 # scrambled (i.e. randomized based on the contents of //chrome/VERSION) on 31 # non-Chrome OS desktop platforms. Set to |false| to disable message ID 32 # scrambling on all platforms. 33 enable_mojom_message_id_scrambling = true 34} 35 36# NOTE: We would like to avoid scrambling message IDs where it doesn't add 37# value, so we limit the behavior to desktop builds for now. There is some 38# redundancy in the conditions here, but it is tolerated for clarity: 39# We're explicit about Mac, Windows, and Linux desktop support, but it's 40# also necessary to ensure that bindings in alternate toolchains (e.g. 41# NaCl IRT) are always consistent with the default toolchain; for that 42# reason we always enable scrambling within NaCl toolchains when possible, 43# as well as within the default toolchain when NaCl is enabled. 44# 45# Finally, because we *cannot* enable scrambling on Chrome OS (it would break 46# ARC) we have to explicitly opt out there even when NaCl is enabled (and 47# consequently also when building for NaCl toolchains.) For this reason we 48# check |target_os| explicitly, as it's consistent across all toolchains. 49enable_scrambled_message_ids = 50 enable_mojom_message_id_scrambling && 51 (is_mac || is_win || (is_linux && !is_chromeos) || 52 ((enable_nacl || is_nacl || is_nacl_nonsfi) && target_os != "chromeos")) 53 54mojom_generator_root = "//mojo/public/tools/bindings" 55mojom_generator_script = "$mojom_generator_root/mojom_bindings_generator.py" 56mojom_generator_sources = [ 57 "$mojom_generator_root/generators/mojom_cpp_generator.py", 58 "$mojom_generator_root/generators/mojom_js_generator.py", 59 "$mojom_generator_root/generators/mojom_java_generator.py", 60 "$mojom_generator_root/pylib/mojom/__init__.py", 61 "$mojom_generator_root/pylib/mojom/error.py", 62 "$mojom_generator_root/pylib/mojom/generate/__init__.py", 63 "$mojom_generator_root/pylib/mojom/generate/constant_resolver.py", 64 "$mojom_generator_root/pylib/mojom/generate/generator.py", 65 "$mojom_generator_root/pylib/mojom/generate/module.py", 66 "$mojom_generator_root/pylib/mojom/generate/pack.py", 67 "$mojom_generator_root/pylib/mojom/generate/template_expander.py", 68 "$mojom_generator_root/pylib/mojom/generate/translate.py", 69 "$mojom_generator_root/pylib/mojom/parse/__init__.py", 70 "$mojom_generator_root/pylib/mojom/parse/ast.py", 71 "$mojom_generator_root/pylib/mojom/parse/lexer.py", 72 "$mojom_generator_root/pylib/mojom/parse/parser.py", 73 "$mojom_generator_script", 74] 75 76if (enable_scrambled_message_ids) { 77 declare_args() { 78 # The path to a file whose contents can be used as the basis for a message 79 # ID scrambling salt. 80 mojom_message_id_salt_path = "//chrome/VERSION" 81 82 # The path to a file whose contents will be concatenated to the contents of 83 # the file at |mojom_message_id_salt_path| to form a complete salt for 84 # message ID scrambling. May be the empty string, in which case the contents 85 # of the above file alone are used as the complete salt. 86 if (is_chrome_branded) { 87 mojom_message_id_salt_suffix_path = 88 "//mojo/internal/chrome-message-id-salt-suffix" 89 } else { 90 mojom_message_id_salt_suffix_path = "" 91 } 92 } 93 94 assert(mojom_message_id_salt_path != "") 95 message_scrambling_args = [ 96 "--scrambled_message_id_salt_path", 97 rebase_path(mojom_message_id_salt_path, root_build_dir), 98 ] 99 message_scrambling_inputs = [ mojom_message_id_salt_path ] 100 101 if (mojom_message_id_salt_suffix_path != "") { 102 message_scrambling_args += [ 103 "--scrambled_message_id_salt_path", 104 rebase_path(mojom_message_id_salt_suffix_path, root_build_dir), 105 ] 106 message_scrambling_inputs += [ mojom_message_id_salt_suffix_path ] 107 } 108} else { 109 message_scrambling_args = [] 110 message_scrambling_inputs = [] 111} 112 113if (enable_mojom_typemapping) { 114 if (!is_ios) { 115 _bindings_configuration_files = [ 116 "//mojo/public/tools/bindings/chromium_bindings_configuration.gni", 117 "//mojo/public/tools/bindings/blink_bindings_configuration.gni", 118 ] 119 } else { 120 _bindings_configuration_files = 121 [ "//mojo/public/tools/bindings/chromium_bindings_configuration.gni" ] 122 } 123 _bindings_configurations = [] 124 foreach(config_file, _bindings_configuration_files) { 125 _bindings_configurations += [ read_file(config_file, "scope") ] 126 } 127 foreach(configuration, _bindings_configurations) { 128 # Check that the mojom field of each typemap refers to a mojom that exists. 129 foreach(typemap, configuration.typemaps) { 130 _typemap_config = { 131 } 132 _typemap_config = typemap.config 133 read_file(_typemap_config.mojom, "") 134 } 135 } 136} else { 137 _bindings_configuration_files = [] 138 _bindings_configurations = [ 139 { 140 typemaps = [] 141 component_macro_suffix = "" 142 }, 143 { 144 variant = "blink" 145 component_macro_suffix = "_BLINK" 146 for_blink = true 147 typemaps = [] 148 }, 149 ] 150} 151 152# Generates targets for building C++, JavaScript and Java bindings from mojom 153# files. The output files will go under the generated file directory tree with 154# the same path as each input file. 155# 156# Other targets should depend on one of these generated targets (where "foo" 157# is the target name): 158# 159# foo 160# C++ bindings. 161# 162# foo_blink 163# C++ bindings using Blink standard types. 164# 165# foo_java 166# Java bindings. 167# 168# foo_js 169# JavaScript bindings; used as compile-time dependency. 170# 171# foo_js_data_deps 172# JavaScript bindings; used as run-time dependency. 173# 174# Parameters: 175# 176# sources (optional if one of the deps sets listed below is present) 177# List of source .mojom files to compile. 178# 179# deps (optional) 180# Note: this can contain only other mojom targets. 181# 182# DEPRECATED: This is synonymous with public_deps because all mojom 183# dependencies must be public by design. Please use public_deps. 184# 185# public_deps (optional) 186# Note: this can contain only other mojom targets. 187# 188# import_dirs (optional) 189# List of import directories that will get added when processing sources. 190# 191# testonly (optional) 192# 193# visibility (optional) 194# 195# visibility_blink (optional) 196# The value to use for visibility for the blink variant. If unset, 197# |visibility| is used. 198# 199# use_once_callback (optional) 200# If set to true, generated classes will use base::OnceCallback instead of 201# base::RepeatingCallback. 202# Default value is true. 203# TODO(dcheng): 204# - Convert everything to use OnceCallback. 205# - Remove support for the old mode. 206# 207# cpp_only (optional) 208# If set to true, only the C++ bindings targets will be generated. 209# 210# support_lazy_serialization (optional) 211# If set to |true|, generated C++ bindings will effectively prefer to 212# transmit messages in an unserialized form when going between endpoints 213# in the same process. This avoids the runtime cost of serialization, 214# deserialization, and validation logic at the expensive of increased 215# code size. Defaults to |false|. 216# 217# disable_variants (optional) 218# If |true|, no variant sources will be generated for the target. Defaults 219# to |false|. 220# 221# disallow_native_types (optional) 222# If set to |true|, mojoms in this target may not apply the [Native] 223# attribute to struct or enum declarations. This avoids emitting code 224# which depends on legacy IPC serialization. Default is |false|, meaning 225# [Native] types are allowed. 226# 227# disallow_interfaces (optional) 228# If set to |true|, mojoms in this target may not define interfaces. 229# Generates bindings with a smaller set of dependencies. Defaults to 230# |false|. 231# 232# scramble_message_ids (optional) 233# If set to |true| (the default), generated mojom interfaces will use 234# scrambled ordinal identifiers in encoded messages. 235# 236# component_output_prefix (optional) 237# The prefix to use for the output_name of any component library emitted 238# for generated C++ bindings. If this is omitted, C++ bindings targets are 239# emitted as source_sets instead. Because this controls the name of the 240# output shared library binary in the root output directory, it must be 241# unique across the entire build configuration. 242# 243# This is required if |component_macro_prefix| is specified. 244# 245# component_macro_prefix (optional) 246# This specifies a macro prefix to use for component export macros and 247# should therefore be globally unique in the project. For example if this 248# is "FOO_BAR", then the generated C++ sources will be built with 249# IS_FOO_BAR_{suffix}_IMPL defined, and the generated public headers will 250# annotate public symbol definitions with 251# COMPONENT_EXPORT(FOO_BAR_{suffix}). "suffix" in this case depends on 252# which internal subtarget is generating the code (e.g. "SHARED", or a 253# variant name like "BLINK"). 254# 255# enabled_features (optional) 256# Definitions in a mojom file can be guarded by an EnableIf attribute. If 257# the value specified by the attribute does not match any items in the 258# list of enabled_features, the definition will be disabled, with no code 259# emitted for it. 260# 261# The following parameters are used to support the component build. They are 262# needed so that bindings which are linked with a component can use the same 263# export settings for classes. The first three are for the chromium variant, and 264# the last three are for the blink variant. These parameters are mutually 265# exclusive to |component_macro_prefix|, but |component_output_prefix| may still 266# be used to uniqueify the generated invariant (i.e. shared) output component. 267# export_class_attribute (optional) 268# The attribute to add to the class declaration. e.g. "CONTENT_EXPORT" 269# export_define (optional) 270# A define to be added to the source_set which is needed by the export 271# header. e.g. "CONTENT_IMPLEMENTATION=1" 272# export_header (optional) 273# A header to be added to the generated bindings to support the component 274# build. e.g. "content/common/content_export.h" 275# export_class_attribute_blink (optional) 276# export_define_blink (optional) 277# export_header_blink (optional) 278# These three parameters are the blink variants of the previous 3. 279# 280# The following parameters are used to correct component build dependencies. 281# They are needed so mojom-mojom dependencies follow the rule that dependencies 282# on a source set in another component are replaced by a dependency on the 283# containing component. The first two are for the chromium variant; the other 284# two are for the blink variant. 285# overridden_deps (optional) 286# The list of mojom deps to be overridden. 287# component_deps (optional) 288# The list of component deps to add to replace overridden_deps. 289# overridden_deps_blink (optional) 290# component_deps_blink (optional) 291# These two parameters are the blink variants of the previous two. 292# 293# check_includes_blink (optional) 294# Overrides the check_includes variable for the blink variant. 295# If check_includes_blink is not defined, the check_includes variable 296# retains its original value. 297template("mojom") { 298 assert( 299 defined(invoker.sources) || defined(invoker.deps) || 300 defined(invoker.public_deps), 301 "\"sources\" or \"deps\" must be defined for the $target_name template.") 302 303 if (defined(invoker.export_class_attribute) || 304 defined(invoker.export_define) || defined(invoker.export_header)) { 305 assert(defined(invoker.export_class_attribute)) 306 assert(defined(invoker.export_define)) 307 assert(defined(invoker.export_header)) 308 assert(!defined(invoker.component_macro_prefix)) 309 } 310 if (defined(invoker.export_class_attribute_blink) || 311 defined(invoker.export_define_blink) || 312 defined(invoker.export_header_blink)) { 313 assert(defined(invoker.export_class_attribute_blink)) 314 assert(defined(invoker.export_define_blink)) 315 assert(defined(invoker.export_header_blink)) 316 assert(!defined(invoker.component_macro_prefix)) 317 } 318 if (defined(invoker.overridden_deps) || defined(invoker.component_deps)) { 319 assert(defined(invoker.overridden_deps)) 320 assert(defined(invoker.component_deps)) 321 } 322 323 if (defined(invoker.overridden_deps_blink) || 324 defined(invoker.component_deps_blink)) { 325 assert(defined(invoker.overridden_deps_blink)) 326 assert(defined(invoker.component_deps_blink)) 327 } 328 329 require_full_cpp_deps = 330 !defined(invoker.disallow_native_types) || 331 !invoker.disallow_native_types || !defined(invoker.disallow_interfaces) || 332 !invoker.disallow_interfaces 333 334 all_deps = [] 335 if (defined(invoker.deps)) { 336 all_deps += invoker.deps 337 } 338 if (defined(invoker.public_deps)) { 339 all_deps += invoker.public_deps 340 } 341 342 if (defined(invoker.component_macro_prefix)) { 343 assert(defined(invoker.component_output_prefix)) 344 } 345 346 group("${target_name}__is_mojom") { 347 } 348 349 # Explicitly ensure that all dependencies (invoker.deps and 350 # invoker.public_deps) are mojom targets. 351 group("${target_name}__check_deps_are_all_mojom") { 352 deps = [] 353 foreach(d, all_deps) { 354 name = get_label_info(d, "label_no_toolchain") 355 toolchain = get_label_info(d, "toolchain") 356 deps += [ "${name}__is_mojom(${toolchain})" ] 357 } 358 } 359 360 target_sources_list = "$target_gen_dir/$target_name.sources_list" 361 sources_list = [] 362 if (defined(invoker.sources)) { 363 sources_list = invoker.sources 364 } 365 write_file(target_sources_list, sources_list) 366 367 # a target implicitly depends on its own sources 368 deps_sources = [ rebase_path(target_sources_list, root_build_dir) ] 369 foreach(d, all_deps) { 370 dep_dir = get_label_info("$d", "target_gen_dir") 371 dep_short_name = get_label_info("$d", "name") 372 deps_sources += 373 [ rebase_path("$dep_dir/$dep_short_name.sources_list", root_build_dir) ] 374 } 375 376 write_file("$target_gen_dir/$target_name.deps_sources_list", deps_sources) 377 378 if (defined(invoker.sources)) { 379 parser_target_name = "${target_name}__parser" 380 enabled_features = [] 381 if (defined(invoker.enabled_features)) { 382 enabled_features += invoker.enabled_features 383 } 384 if (is_posix) { 385 enabled_features += [ "is_posix" ] 386 } 387 if (is_android) { 388 enabled_features += [ "is_android" ] 389 } else if (is_chromeos) { 390 enabled_features += [ "is_chromeos" ] 391 } else if (is_fuchsia) { 392 enabled_features += [ "is_fuchsia" ] 393 } else if (is_ios) { 394 enabled_features += [ "is_ios" ] 395 } else if (is_linux) { 396 enabled_features += [ "is_linux" ] 397 } else if (is_mac) { 398 enabled_features += [ "is_mac" ] 399 } else if (is_win) { 400 enabled_features += [ "is_win" ] 401 } 402 403 action(parser_target_name) { 404 script = mojom_generator_script 405 inputs = mojom_generator_sources + jinja2_sources 406 sources = invoker.sources 407 outputs = [] 408 filelist = [] 409 foreach(source, invoker.sources) { 410 filename = get_path_info("$source", "name") 411 dirname = get_path_info("$source", "gen_dir") 412 outputs += [ "$dirname/$filename.p" ] 413 filelist += [ rebase_path("$source", root_build_dir) ] 414 } 415 416 response_file_contents = filelist 417 418 args = [ 419 "parse", 420 "--filelist={{response_file_name}}", 421 "-o", 422 rebase_path(root_gen_dir, root_build_dir), 423 "-d", 424 rebase_path("//", root_build_dir), 425 ] 426 foreach(enabled_feature, enabled_features) { 427 args += [ 428 "--enable_feature", 429 enabled_feature, 430 ] 431 } 432 } 433 } 434 435 parsed_target_name = "${target_name}__parsed" 436 group(parsed_target_name) { 437 public_deps = [] 438 if (defined(invoker.sources)) { 439 public_deps += [ ":$parser_target_name" ] 440 } 441 foreach(d, all_deps) { 442 # Resolve the name, so that a target //mojo/something becomes 443 # //mojo/something:something and we can append the parsed 444 # suffix to get the mojom dependency name. 445 full_name = get_label_info("$d", "label_no_toolchain") 446 public_deps += [ "${full_name}__parsed" ] 447 } 448 } 449 450 if (defined(invoker.sources)) { 451 verify_deps_target_names = [] 452 if (!defined(invoker.skip_deps_check) || !invoker.skip_deps_check) { 453 verify_deps_target_name = "${target_name}__verify_deps" 454 verify_deps_target_names += [ ":$verify_deps_target_name" ] 455 source_file_name = target_name 456 457 action(verify_deps_target_name) { 458 script = mojom_generator_script 459 inputs = mojom_generator_sources + jinja2_sources 460 sources = invoker.sources 461 deps = [ 462 ":$parsed_target_name", 463 ] 464 outputs = [] 465 filelist = [] 466 foreach(source, invoker.sources) { 467 filename = get_path_info("$source", "name") 468 dirname = get_path_info("$source", "gen_dir") 469 outputs += [ "$dirname/$filename.v" ] 470 filelist += [ rebase_path("$source", root_build_dir) ] 471 } 472 473 response_file_contents = filelist 474 475 args = [ 476 "verify", 477 "--filelist={{response_file_name}}", 478 "-f", 479 rebase_path("$target_gen_dir/$source_file_name.deps_sources_list", 480 root_build_dir), 481 "--gen_dir", 482 rebase_path(root_gen_dir, root_build_dir), 483 "--depth", 484 rebase_path("//", root_build_dir), 485 ] 486 } 487 } 488 } 489 490 generator_cpp_message_ids_target_name = "${target_name}__generate_message_ids" 491 492 # Generate code that is shared by different variants. 493 if (defined(invoker.sources)) { 494 common_generator_args = [ 495 "--use_bundled_pylibs", 496 "generate", 497 "-d", 498 rebase_path("//", root_build_dir), 499 "-I", 500 rebase_path("//", root_build_dir), 501 "-o", 502 rebase_path(root_gen_dir, root_build_dir), 503 "--bytecode_path", 504 rebase_path("$root_gen_dir/mojo/public/tools/bindings", root_build_dir), 505 ] 506 507 if (defined(invoker.disallow_native_types) && 508 invoker.disallow_native_types) { 509 common_generator_args += [ "--disallow_native_types" ] 510 } 511 512 if (defined(invoker.disallow_interfaces) && invoker.disallow_interfaces) { 513 common_generator_args += [ "--disallow_interfaces" ] 514 } 515 516 if (defined(invoker.import_dirs)) { 517 foreach(import_dir, invoker.import_dirs) { 518 common_generator_args += [ 519 "-I", 520 rebase_path(import_dir, root_build_dir), 521 ] 522 } 523 } 524 525 if (defined(invoker.component_macro_prefix)) { 526 shared_component_export_macro = 527 "COMPONENT_EXPORT(${invoker.component_macro_prefix}_SHARED)" 528 shared_component_impl_macro = 529 "IS_${invoker.component_macro_prefix}_SHARED_IMPL" 530 shared_component_output_name = "${invoker.component_output_prefix}_shared" 531 } else if (defined(invoker.export_class_attribute_shared) || 532 defined(invoker.export_class_attribute)) { 533 if (defined(invoker.export_class_attribute_shared)) { 534 assert(defined(invoker.export_header_shared)) 535 shared_component_export_macro = invoker.export_class_attribute_shared 536 shared_component_impl_macro = invoker.export_define_shared 537 } else { 538 assert(!defined(invoker.export_header_shared)) 539 540 # If no explicit shared attribute/define was provided by the invoker, 541 # we derive some reasonable settings frorm the default variant. 542 shared_component_export_macro = "COMPONENT_EXPORT(MOJOM_SHARED_" + 543 invoker.export_class_attribute + ")" 544 shared_component_impl_macro = 545 "IS_MOJOM_SHARED_" + invoker.export_class_attribute + "_IMPL" 546 } 547 548 if (defined(invoker.component_output_prefix)) { 549 shared_component_output_name = 550 "${invoker.component_output_prefix}_shared" 551 } else { 552 shared_component_output_name = "${target_name}_shared" 553 } 554 } 555 556 action(generator_cpp_message_ids_target_name) { 557 script = mojom_generator_script 558 inputs = mojom_generator_sources + jinja2_sources 559 sources = invoker.sources 560 deps = [ 561 ":$parsed_target_name", 562 "//mojo/public/tools/bindings:precompile_templates", 563 ] 564 outputs = [] 565 args = common_generator_args 566 filelist = [] 567 foreach(source, invoker.sources) { 568 outputs += [ "$target_gen_dir/$source-shared-message-ids.h" ] 569 filelist += [ rebase_path("$source", root_build_dir) ] 570 } 571 572 response_file_contents = filelist 573 574 args += [ 575 "--filelist={{response_file_name}}", 576 "--generate_non_variant_code", 577 "--generate_message_ids", 578 "-g", 579 "c++", 580 ] 581 582 if (!defined(invoker.scramble_message_ids) || 583 invoker.scramble_message_ids) { 584 inputs += message_scrambling_inputs 585 args += message_scrambling_args 586 } 587 } 588 589 generator_shared_cpp_outputs = [ 590 "{{source_gen_dir}}/{{source_name_part}}.mojom-shared-internal.h", 591 "{{source_gen_dir}}/{{source_name_part}}.mojom-shared.cc", 592 "{{source_gen_dir}}/{{source_name_part}}.mojom-shared.h", 593 ] 594 generator_shared_target_name = "${target_name}_shared__generator" 595 action(generator_shared_target_name) { 596 script = mojom_generator_script 597 inputs = mojom_generator_sources + jinja2_sources 598 sources = invoker.sources 599 deps = [ 600 ":$parsed_target_name", 601 "//mojo/public/tools/bindings:precompile_templates", 602 ] + verify_deps_target_names 603 604 outputs = [] 605 args = common_generator_args 606 filelist = [] 607 foreach(source, invoker.sources) { 608 filelist += [ rebase_path("$source", root_build_dir) ] 609 outputs += [ 610 "$target_gen_dir/$source-shared-internal.h", 611 "$target_gen_dir/$source-shared.cc", 612 "$target_gen_dir/$source-shared.h", 613 ] 614 } 615 616 response_file_contents = filelist 617 618 args += [ 619 "--filelist={{response_file_name}}", 620 "--generate_non_variant_code", 621 "-g", 622 "c++", 623 ] 624 625 if (defined(shared_component_export_macro)) { 626 args += [ 627 "--export_attribute", 628 shared_component_export_macro, 629 "--export_header", 630 "base/component_export.h", 631 ] 632 } 633 } 634 } else { 635 group(generator_cpp_message_ids_target_name) { 636 } 637 } 638 639 shared_cpp_sources_target_name = "${target_name}_shared_cpp_sources" 640 jumbo_source_set(shared_cpp_sources_target_name) { 641 if (defined(invoker.testonly)) { 642 testonly = invoker.testonly 643 } 644 deps = [] 645 if (defined(invoker.sources)) { 646 sources = 647 process_file_template(invoker.sources, generator_shared_cpp_outputs) 648 deps += [ ":$generator_shared_target_name" ] 649 } 650 if (require_full_cpp_deps) { 651 public_deps = [ 652 "//mojo/public/cpp/bindings", 653 ] 654 } else { 655 public_deps = [ 656 "//mojo/public/cpp/bindings:bindings_base", 657 ] 658 } 659 foreach(d, all_deps) { 660 # Resolve the name, so that a target //mojo/something becomes 661 # //mojo/something:something and we can append shared_cpp_sources_suffix 662 # to get the cpp dependency name. 663 full_name = get_label_info("$d", "label_no_toolchain") 664 public_deps += [ "${full_name}_shared" ] 665 } 666 if (defined(shared_component_impl_macro)) { 667 defines = [ shared_component_impl_macro ] 668 } 669 } 670 671 shared_cpp_library_target_name = "${target_name}_shared" 672 if (defined(shared_component_output_name)) { 673 component(shared_cpp_library_target_name) { 674 if (defined(invoker.testonly)) { 675 testonly = invoker.testonly 676 } 677 output_name = "$shared_component_output_name" 678 public_deps = [ 679 ":$shared_cpp_sources_target_name", 680 ] 681 } 682 } else { 683 group(shared_cpp_library_target_name) { 684 if (defined(invoker.testonly)) { 685 testonly = invoker.testonly 686 } 687 public_deps = [ 688 ":$shared_cpp_sources_target_name", 689 ] 690 } 691 } 692 693 # Generate code for variants. 694 if (!defined(invoker.disable_variants) || !invoker.disable_variants) { 695 enabled_configurations = _bindings_configurations 696 } else { 697 first_config = _bindings_configurations[0] 698 assert(!defined(first_config.variant)) 699 enabled_configurations = [ first_config ] 700 } 701 foreach(bindings_configuration, enabled_configurations) { 702 cpp_only = false 703 if (defined(invoker.cpp_only)) { 704 cpp_only = invoker.cpp_only 705 } 706 variant_suffix = "" 707 if (defined(bindings_configuration.variant)) { 708 variant = bindings_configuration.variant 709 variant_suffix = "_${variant}" 710 cpp_only = true 711 } 712 type_mappings_target_name = "${target_name}${variant_suffix}__type_mappings" 713 type_mappings_path = 714 "$target_gen_dir/${target_name}${variant_suffix}__type_mappings" 715 active_typemaps = [] 716 enabled_sources = [] 717 if (defined(invoker.sources)) { 718 generator_cpp_outputs = [] 719 variant_dash_suffix = "" 720 if (defined(variant)) { 721 variant_dash_suffix = "-${variant}" 722 } 723 generator_cpp_outputs += [ 724 "{{source_gen_dir}}/{{source_name_part}}.mojom${variant_dash_suffix}.cc", 725 "{{source_gen_dir}}/{{source_name_part}}.mojom${variant_dash_suffix}.h", 726 ] 727 enabled_sources = [] 728 if (defined(bindings_configuration.blacklist)) { 729 foreach(source, invoker.sources) { 730 blacklisted = false 731 foreach(blacklisted_source, bindings_configuration.blacklist) { 732 if (get_path_info(source, "abspath") == blacklisted_source) { 733 blacklisted = true 734 } 735 } 736 if (!blacklisted) { 737 enabled_sources += [ source ] 738 } 739 } 740 } else { 741 enabled_sources = invoker.sources 742 } 743 foreach(source, enabled_sources) { 744 # TODO(sammc): Use a map instead of a linear scan when GN supports maps. 745 foreach(typemap, bindings_configuration.typemaps) { 746 _typemap_config = { 747 } 748 _typemap_config = typemap.config 749 if (get_path_info(source, "abspath") == _typemap_config.mojom) { 750 enabled = false 751 if (!defined(_typemap_config.os_whitelist)) { 752 enabled = true 753 } else { 754 foreach(os, _typemap_config.os_whitelist) { 755 if (os == "android" && is_android) { 756 enabled = true 757 } else if (os == "chromeos" && is_chromeos) { 758 enabled = true 759 } else if (os == "fuchsia" && is_fuchsia) { 760 enabled = true 761 } else if (os == "ios" && is_ios) { 762 enabled = true 763 } else if (os == "linux" && is_linux) { 764 enabled = true 765 } else if (os == "mac" && is_mac) { 766 enabled = true 767 } else if (os == "posix" && is_posix) { 768 enabled = true 769 } else if (os == "win" && is_win) { 770 enabled = true 771 } 772 } 773 } 774 if (enabled) { 775 active_typemaps += [ typemap ] 776 } 777 } 778 } 779 } 780 781 generator_target_name = "${target_name}${variant_suffix}__generator" 782 action(generator_target_name) { 783 script = mojom_generator_script 784 inputs = mojom_generator_sources + jinja2_sources 785 sources = invoker.sources 786 deps = [ 787 ":$parsed_target_name", 788 ":$type_mappings_target_name", 789 "//mojo/public/tools/bindings:precompile_templates", 790 ] + verify_deps_target_names 791 outputs = [] 792 args = common_generator_args 793 filelist = [] 794 foreach(source, invoker.sources) { 795 filelist += [ rebase_path("$source", root_build_dir) ] 796 outputs += [ 797 "$target_gen_dir/${source}${variant_dash_suffix}.cc", 798 "$target_gen_dir/${source}${variant_dash_suffix}.h", 799 ] 800 } 801 802 response_file_contents = filelist 803 804 args += [ 805 "--filelist={{response_file_name}}", 806 "-g", 807 "c++", 808 ] 809 810 if (defined(bindings_configuration.variant)) { 811 args += [ 812 "--variant", 813 bindings_configuration.variant, 814 ] 815 } 816 817 args += [ 818 "--typemap", 819 rebase_path(type_mappings_path, root_build_dir), 820 ] 821 822 if (defined(invoker.component_macro_prefix)) { 823 args += [ 824 "--export_attribute", 825 "COMPONENT_EXPORT(${invoker.component_macro_prefix}" + 826 "${bindings_configuration.component_macro_suffix})", 827 "--export_header", 828 "base/component_export.h", 829 ] 830 } 831 832 if (defined(bindings_configuration.for_blink) && 833 bindings_configuration.for_blink) { 834 args += [ "--for_blink" ] 835 if (defined(invoker.export_class_attribute_blink)) { 836 args += [ 837 "--export_attribute", 838 invoker.export_class_attribute_blink, 839 "--export_header", 840 invoker.export_header_blink, 841 ] 842 } 843 } else { 844 if (defined(invoker.export_class_attribute)) { 845 args += [ 846 "--export_attribute", 847 invoker.export_class_attribute, 848 "--export_header", 849 invoker.export_header, 850 ] 851 } 852 } 853 854 if (!defined(invoker.use_once_callback) || invoker.use_once_callback) { 855 args += [ "--use_once_callback" ] 856 } 857 858 if (defined(invoker.support_lazy_serialization) && 859 invoker.support_lazy_serialization) { 860 args += [ "--support_lazy_serialization" ] 861 } 862 } 863 } 864 865 action(type_mappings_target_name) { 866 inputs = _bindings_configuration_files + mojom_generator_sources + 867 jinja2_sources 868 outputs = [ 869 type_mappings_path, 870 ] 871 script = "$mojom_generator_root/generate_type_mappings.py" 872 deps = [] 873 args = [ 874 "--output", 875 rebase_path(type_mappings_path, root_build_dir), 876 ] 877 878 foreach(d, all_deps) { 879 name = get_label_info(d, "label_no_toolchain") 880 toolchain = get_label_info(d, "toolchain") 881 dependency_output = "${name}${variant_suffix}__type_mappings" 882 dependency_target = "${dependency_output}(${toolchain})" 883 deps += [ dependency_target ] 884 dependency_output_dir = 885 get_label_info(dependency_output, "target_gen_dir") 886 dependency_name = get_label_info(dependency_output, "name") 887 dependency_path = 888 rebase_path("$dependency_output_dir/${dependency_name}", 889 root_build_dir) 890 args += [ 891 "--dependency", 892 dependency_path, 893 ] 894 } 895 896 if (enabled_sources != []) { 897 # TODO(sammc): Pass the typemap description in a file to avoid command 898 # line length limitations. 899 typemap_description = [] 900 foreach(typemap, active_typemaps) { 901 _typemap_config = { 902 } 903 _typemap_config = typemap.config 904 typemap_description += [ "--start-typemap" ] 905 if (defined(_typemap_config.public_headers)) { 906 foreach(value, _typemap_config.public_headers) { 907 typemap_description += [ "public_headers=$value" ] 908 } 909 } 910 if (defined(_typemap_config.traits_headers)) { 911 foreach(value, _typemap_config.traits_headers) { 912 typemap_description += [ "traits_headers=$value" ] 913 } 914 } 915 foreach(value, _typemap_config.type_mappings) { 916 typemap_description += [ "type_mappings=$value" ] 917 } 918 919 # The typemap configuration files are not actually used as inputs here 920 # but this establishes a necessary build dependency to ensure that 921 # typemap changes force a rebuild of affected targets. 922 inputs += [ typemap.filename ] 923 } 924 args += typemap_description 925 } 926 } 927 928 if (defined(invoker.component_macro_prefix)) { 929 output_target_type = "component" 930 } else { 931 output_target_type = "source_set" 932 } 933 934 js_data_deps_target_name = target_name + "_js_data_deps" 935 not_needed([ "js_data_deps_target_name" ]) 936 937 target("jumbo_" + output_target_type, "${target_name}${variant_suffix}") { 938 if (defined(bindings_configuration.for_blink) && 939 bindings_configuration.for_blink && 940 defined(invoker.visibility_blink)) { 941 visibility = invoker.visibility_blink 942 } else if (defined(invoker.visibility)) { 943 visibility = invoker.visibility 944 } 945 if (defined(invoker.testonly)) { 946 testonly = invoker.testonly 947 } 948 defines = [] 949 if (defined(invoker.export_define)) { 950 defines += [ invoker.export_define ] 951 } 952 if (defined(invoker.export_define_blink)) { 953 defines += [ invoker.export_define_blink ] 954 } 955 if (enabled_sources != []) { 956 sources = process_file_template(enabled_sources, generator_cpp_outputs) 957 } 958 deps = [ 959 ":$generator_cpp_message_ids_target_name", 960 "//mojo/public/cpp/bindings:struct_traits", 961 "//mojo/public/interfaces/bindings:bindings__generator", 962 "//mojo/public/interfaces/bindings:bindings_shared__generator", 963 ] 964 public_deps = [ 965 ":$shared_cpp_library_target_name", 966 "//base", 967 ] 968 if (require_full_cpp_deps) { 969 public_deps += [ "//mojo/public/cpp/bindings" ] 970 } else { 971 public_deps += [ "//mojo/public/cpp/bindings:bindings_base" ] 972 } 973 974 if (enabled_sources != []) { 975 public_deps += [ ":$generator_target_name" ] 976 } 977 if (defined(invoker.component_macro_prefix)) { 978 output_name = "${invoker.component_output_prefix}${variant_suffix}" 979 defines += [ "IS_${invoker.component_macro_prefix}" + 980 "${bindings_configuration.component_macro_suffix}_IMPL" ] 981 } 982 foreach(d, all_deps) { 983 # Resolve the name, so that a target //mojo/something becomes 984 # //mojo/something:something and we can append variant_suffix to 985 # get the cpp dependency name. 986 full_name = get_label_info("$d", "label_no_toolchain") 987 public_deps += [ "${full_name}${variant_suffix}" ] 988 } 989 if (defined(bindings_configuration.for_blink) && 990 bindings_configuration.for_blink) { 991 if (defined(invoker.overridden_deps_blink)) { 992 foreach(d, invoker.overridden_deps_blink) { 993 # Resolve the name, so that a target //mojo/something becomes 994 # //mojo/something:something and we can append variant_suffix 995 # to get the cpp dependency name. 996 full_name = get_label_info("$d", "label_no_toolchain") 997 public_deps -= [ "${full_name}${variant_suffix}" ] 998 } 999 public_deps += invoker.component_deps_blink 1000 } 1001 if (defined(invoker.check_includes_blink)) { 1002 check_includes = invoker.check_includes_blink 1003 } 1004 } else { 1005 if (defined(invoker.check_includes_blink)) { 1006 not_needed(invoker, [ "check_includes_blink" ]) 1007 } 1008 if (defined(invoker.overridden_deps)) { 1009 foreach(d, invoker.overridden_deps) { 1010 # Resolve the name, so that a target //mojo/something becomes 1011 # //mojo/something:something and we can append variant_suffix 1012 # to get the cpp dependency name. 1013 full_name = get_label_info("$d", "label_no_toolchain") 1014 public_deps -= [ "${full_name}${variant_suffix}" ] 1015 } 1016 public_deps += invoker.component_deps 1017 } 1018 } 1019 foreach(typemap, active_typemaps) { 1020 _typemap_config = { 1021 } 1022 _typemap_config = typemap.config 1023 if (defined(_typemap_config.sources)) { 1024 sources += _typemap_config.sources 1025 } 1026 if (defined(_typemap_config.public_deps)) { 1027 public_deps += _typemap_config.public_deps 1028 } 1029 if (defined(_typemap_config.deps)) { 1030 deps += _typemap_config.deps 1031 } 1032 } 1033 if (defined(invoker.export_header)) { 1034 sources += [ "//" + invoker.export_header ] 1035 } 1036 if (defined(bindings_configuration.for_blink) && 1037 bindings_configuration.for_blink) { 1038 public_deps += [ "//mojo/public/cpp/bindings:wtf_support" ] 1039 } 1040 1041 if (enable_ipc_fuzzer) { 1042 # Generate JS bindings by default if IPC fuzzer is enabled. 1043 public_deps += [ ":$js_data_deps_target_name" ] 1044 } 1045 } 1046 1047 if (!cpp_only && is_android) { 1048 import("//build/config/android/rules.gni") 1049 1050 java_generator_target_name = target_name + "_java__generator" 1051 if (enabled_sources != []) { 1052 generator_java_outputs = 1053 [ "{{source_gen_dir}}/{{source_name_part}}.mojom.srcjar" ] 1054 action(java_generator_target_name) { 1055 script = mojom_generator_script 1056 inputs = mojom_generator_sources + jinja2_sources 1057 sources = enabled_sources 1058 deps = [ 1059 ":$parsed_target_name", 1060 ":$type_mappings_target_name", 1061 "//mojo/public/tools/bindings:precompile_templates", 1062 ] + verify_deps_target_names 1063 outputs = [] 1064 args = common_generator_args 1065 filelist = [] 1066 foreach(source, invoker.sources) { 1067 filelist += [ rebase_path("$source", root_build_dir) ] 1068 outputs += [ "$target_gen_dir/$source.srcjar" ] 1069 } 1070 1071 response_file_contents = filelist 1072 1073 args += [ 1074 "--filelist={{response_file_name}}", 1075 "-g", 1076 "java", 1077 ] 1078 1079 if (!defined(invoker.scramble_message_ids) || 1080 invoker.scramble_message_ids) { 1081 inputs += message_scrambling_inputs 1082 args += message_scrambling_args 1083 } 1084 } 1085 } else { 1086 group(java_generator_target_name) { 1087 } 1088 } 1089 1090 java_srcjar_target_name = target_name + "_java_sources" 1091 action(java_srcjar_target_name) { 1092 script = "//mojo/public/tools/gn/zip.py" 1093 inputs = [] 1094 if (enabled_sources != []) { 1095 inputs = 1096 process_file_template(enabled_sources, generator_java_outputs) 1097 } 1098 output = "$target_gen_dir/$target_name.srcjar" 1099 outputs = [ 1100 output, 1101 ] 1102 rebase_inputs = rebase_path(inputs, root_build_dir) 1103 rebase_output = rebase_path(output, root_build_dir) 1104 args = [ 1105 "--zip-inputs=$rebase_inputs", 1106 "--output=$rebase_output", 1107 ] 1108 deps = [] 1109 if (enabled_sources != []) { 1110 deps = [ 1111 ":$java_generator_target_name", 1112 ] 1113 } 1114 } 1115 1116 java_target_name = target_name + "_java" 1117 android_library(java_target_name) { 1118 deps = [ 1119 "//base:base_java", 1120 "//mojo/public/java:bindings_java", 1121 "//mojo/public/java:system_java", 1122 ] 1123 1124 # Disable warnings/checks on these generated files. 1125 chromium_code = false 1126 1127 foreach(d, all_deps) { 1128 # Resolve the name, so that a target //mojo/something becomes 1129 # //mojo/something:something and we can append "_java" to get the java 1130 # dependency name. 1131 full_name = get_label_info(d, "label_no_toolchain") 1132 deps += [ "${full_name}_java" ] 1133 } 1134 1135 srcjar_deps = [ ":$java_srcjar_target_name" ] 1136 } 1137 } 1138 } 1139 1140 if (enable_ipc_fuzzer || !defined(invoker.cpp_only) || !invoker.cpp_only) { 1141 if (defined(invoker.sources)) { 1142 generator_js_target_name = "${target_name}_js__generator" 1143 generator_js_outputs = [ 1144 "{{source_gen_dir}}/{{source_name_part}}.mojom.js", 1145 "{{source_gen_dir}}/{{source_name_part}}.mojom.externs.js", 1146 ] 1147 action(generator_js_target_name) { 1148 script = mojom_generator_script 1149 inputs = mojom_generator_sources + jinja2_sources 1150 sources = [] 1151 if (defined(invoker.sources)) { 1152 sources += invoker.sources 1153 } 1154 deps = [ 1155 ":$parsed_target_name", 1156 "//mojo/public/tools/bindings:precompile_templates", 1157 ] + verify_deps_target_names 1158 outputs = [] 1159 args = common_generator_args 1160 filelist = [] 1161 foreach(source, invoker.sources) { 1162 filelist += [ rebase_path("$source", root_build_dir) ] 1163 outputs += [ 1164 "$target_gen_dir/$source.js", 1165 "$target_gen_dir/$source.externs.js", 1166 ] 1167 } 1168 1169 response_file_contents = filelist 1170 1171 args += [ 1172 "--filelist={{response_file_name}}", 1173 "-g", 1174 "javascript", 1175 ] 1176 1177 if (!defined(invoker.scramble_message_ids) || 1178 invoker.scramble_message_ids) { 1179 inputs += message_scrambling_inputs 1180 args += message_scrambling_args 1181 } 1182 1183 if (enable_ipc_fuzzer) { 1184 args += [ "--generate_fuzzing" ] 1185 } 1186 } 1187 } 1188 1189 js_target_name = target_name + "_js" 1190 group(js_target_name) { 1191 public_deps = [] 1192 if (defined(invoker.sources)) { 1193 public_deps += [ ":$generator_js_target_name" ] 1194 } 1195 1196 foreach(d, all_deps) { 1197 full_name = get_label_info(d, "label_no_toolchain") 1198 public_deps += [ "${full_name}_js" ] 1199 } 1200 } 1201 1202 group(js_data_deps_target_name) { 1203 deps = [] 1204 if (defined(invoker.sources)) { 1205 data = process_file_template(invoker.sources, generator_js_outputs) 1206 deps += [ ":$generator_js_target_name" ] 1207 } 1208 1209 data_deps = [] 1210 foreach(d, all_deps) { 1211 full_name = get_label_info(d, "label_no_toolchain") 1212 data_deps += [ "${full_name}_js_data_deps" ] 1213 } 1214 } 1215 } 1216} 1217 1218# A helper for the mojom() template above when component libraries are desired 1219# for generated C++ bindings units. Supports all the same arguments as mojom() 1220# except for the optional |component_output_prefix| and |component_macro_prefix| 1221# arguments. These are instead shortened to |output_prefix| and |macro_prefix| 1222# and are *required*. 1223template("mojom_component") { 1224 assert(defined(invoker.output_prefix) && defined(invoker.macro_prefix)) 1225 1226 mojom(target_name) { 1227 forward_variables_from(invoker, 1228 "*", 1229 [ 1230 "output_prefix", 1231 "macro_prefix", 1232 ]) 1233 component_output_prefix = invoker.output_prefix 1234 component_macro_prefix = invoker.macro_prefix 1235 } 1236} 1237