diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2024-08-08 18:13:00 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2024-08-15 23:59:08 +0300 |
commit | 50c92cc7e2924009ecab3e4004448b01d687707c (patch) | |
tree | c22b49816a3c79dae4727780962aa0928df42b52 /utils/codegen/ipc/mojo/public/tools/bindings/mojom.gni | |
parent | d3bf27180ef1d91b86b7b87a2378e559eaff5455 (diff) |
meson: Move all code generation scripts to utils/codegen/
We have multiple code generation scripts in utils/, mixed with other
miscellaneous utilities, as well as a larger code base based on mojom in
utils/ipc/. To make code sharing easier between the generator scripts,
without creating a mess in the utils/ directory, move all the code
generation code to utils/codegen/.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Diffstat (limited to 'utils/codegen/ipc/mojo/public/tools/bindings/mojom.gni')
-rw-r--r-- | utils/codegen/ipc/mojo/public/tools/bindings/mojom.gni | 2118 |
1 files changed, 2118 insertions, 0 deletions
diff --git a/utils/codegen/ipc/mojo/public/tools/bindings/mojom.gni b/utils/codegen/ipc/mojo/public/tools/bindings/mojom.gni new file mode 100644 index 00000000..3f6e54e0 --- /dev/null +++ b/utils/codegen/ipc/mojo/public/tools/bindings/mojom.gni @@ -0,0 +1,2118 @@ +# Copyright 2014 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/closure_args.gni") +import("//third_party/closure_compiler/compile_js.gni") +import("//third_party/protobuf/proto_library.gni") +import("//ui/webui/resources/tools/generate_grd.gni") +import("//ui/webui/webui_features.gni") + +import("//build/config/cast.gni") + +# TODO(rockot): Maybe we can factor these dependencies out of //mojo. They're +# used to conditionally enable message ID scrambling in a way which is +# consistent across toolchains and which is affected by branded vs non-branded +# Chrome builds. Ideally we could create some generic knobs here that could be +# flipped elsewhere though. +import("//build/config/chrome_build.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/features.gni") +import("//build/config/nacl/config.gni") +import("//build/toolchain/kythe.gni") +import("//components/nacl/features.gni") +import("//third_party/jinja2/jinja2.gni") +import("//third_party/ply/ply.gni") +import("//tools/ipc_fuzzer/ipc_fuzzer.gni") +declare_args() { + # Indicates whether typemapping should be supported in this build + # configuration. This may be disabled when building external projects which + # depend on //mojo but which do not need/want all of the Chromium tree + # dependencies that come with typemapping. + # + # Note that (perhaps obviously) a huge amount of Chromium code will not build + # with typemapping disabled, so it is never valid to set this to |false| in + # any Chromium build configuration. + enable_mojom_typemapping = true + + # Controls message ID scrambling behavior. If |true|, message IDs are + # scrambled (i.e. randomized based on the contents of //chrome/VERSION) on + # non-Chrome OS desktop platforms. Enabled on official builds by default. + # Set to |true| to enable message ID scrambling on a specific build. + # See also `enable_scrambled_message_ids` below for more details. + enable_mojom_message_id_scrambling = is_official_build + + # Enables generating javascript fuzzing-related code and the bindings for the + # MojoLPM fuzzer targets. Off by default. + enable_mojom_fuzzer = false + + # Enables Closure compilation of generated JS lite bindings. In environments + # where compilation is supported, any mojom target "foo" will also have a + # corresponding "foo_js_library_for_compile" target generated. + if (is_chromeos_ash) { + enable_mojom_closure_compile = enable_js_type_check && optimize_webui + } +} + +# Closure libraries are needed for mojom_closure_compile, and when +# js_type_check is enabled on Ash. +if (is_chromeos_ash) { + generate_mojom_closure_libraries = + enable_mojom_closure_compile || enable_js_type_check +} else { + generate_mojom_closure_libraries = false +} + +# NOTE: We would like to avoid scrambling message IDs where it doesn't add +# value, so we limit the behavior to desktop builds for now. There is some +# redundancy in the conditions here, but it is tolerated for clarity: +# We're explicit about Mac, Windows, and Linux desktop support, but it's +# also necessary to ensure that bindings in alternate toolchains (e.g. +# NaCl IRT) are always consistent with the default toolchain; for that +# reason we always enable scrambling within NaCl toolchains when possible, +# as well as within the default toolchain when NaCl is enabled. +# +# Finally, because we *cannot* enable scrambling on Chrome OS (it would break +# ARC) we have to explicitly opt out there even when NaCl is enabled (and +# consequently also when building for NaCl toolchains.) For this reason we +# check |target_os| explicitly, as it's consistent across all toolchains. +# +# TODO(crbug.com/1052397): Remove !chromeos_is_browser_only once +# lacros-chrome switches to target_os="chromeos" +enable_scrambled_message_ids = + enable_mojom_message_id_scrambling && + (is_mac || is_win || (is_linux && !is_castos) || + ((enable_nacl || is_nacl) && + (target_os != "chromeos" && !chromeos_is_browser_only))) + +_mojom_tools_root = "//mojo/public/tools" +_mojom_library_root = "$_mojom_tools_root/mojom/mojom" +mojom_parser_script = "$_mojom_tools_root/mojom/mojom_parser.py" +mojom_parser_sources = [ + "$_mojom_library_root/__init__.py", + "$_mojom_library_root/error.py", + "$_mojom_library_root/fileutil.py", + "$_mojom_library_root/generate/__init__.py", + "$_mojom_library_root/generate/check.py", + "$_mojom_library_root/generate/generator.py", + "$_mojom_library_root/generate/module.py", + "$_mojom_library_root/generate/pack.py", + "$_mojom_library_root/generate/template_expander.py", + "$_mojom_library_root/generate/translate.py", + "$_mojom_library_root/parse/__init__.py", + "$_mojom_library_root/parse/ast.py", + "$_mojom_library_root/parse/conditional_features.py", + "$_mojom_library_root/parse/lexer.py", + "$_mojom_library_root/parse/parser.py", + "//tools/diagnosis/crbug_1001171.py", +] + +mojom_generator_root = "$_mojom_tools_root/bindings" +mojom_generator_script = "$mojom_generator_root/mojom_bindings_generator.py" +mojom_generator_sources = + mojom_parser_sources + [ + "$mojom_generator_root/checks/__init__.py", + "$mojom_generator_root/checks/mojom_attributes_check.py", + "$mojom_generator_root/checks/mojom_definitions_check.py", + "$mojom_generator_root/checks/mojom_interface_feature_check.py", + "$mojom_generator_root/checks/mojom_restrictions_check.py", + "$mojom_generator_root/generators/__init__.py", + "$mojom_generator_root/generators/cpp_util.py", + "$mojom_generator_root/generators/mojom_cpp_generator.py", + "$mojom_generator_root/generators/mojom_java_generator.py", + "$mojom_generator_root/generators/mojom_js_generator.py", + "$mojom_generator_root/generators/mojom_mojolpm_generator.py", + "$mojom_generator_root/generators/mojom_ts_generator.py", + "$mojom_generator_script", + "//build/action_helpers.py", + "//build/gn_helpers.py", + "//build/zip_helpers.py", + ] + +if (enable_scrambled_message_ids) { + declare_args() { + # The path to a file whose contents can be used as the basis for a message + # ID scrambling salt. + mojom_message_id_salt_path = "//chrome/VERSION" + } + + assert(mojom_message_id_salt_path != "") + message_scrambling_args = [ + "--scrambled_message_id_salt_path", + rebase_path(mojom_message_id_salt_path, root_build_dir), + ] + message_scrambling_inputs = [ mojom_message_id_salt_path ] +} else { + message_scrambling_args = [] + message_scrambling_inputs = [] +} + +# Generates targets for building C++, JavaScript and Java bindings from mojom +# files. The output files will go under the generated file directory tree with +# the same path as each input file. +# +# Other targets should depend on one of these generated targets (where "foo" +# is the target name): +# +# foo +# C++ bindings. +# +# foo_blink +# C++ bindings using Blink standard types. +# +# foo_java +# Java bindings. +# +# foo_js +# JavaScript bindings; used as compile-time dependency. +# +# foo_js_data_deps +# JavaScript bindings; used as run-time dependency. +# +# Parameters: +# +# sources (optional if one of the deps sets listed below is present) +# List of source .mojom files to compile. +# +# deps (optional) +# Note: this can contain only other mojom targets. +# +# DEPRECATED: This is synonymous with public_deps because all mojom +# dependencies must be public by design. Please use public_deps. +# +# public_deps (optional) +# Note: this can contain only other mojom targets. +# +# parser_deps (optional) +# List of non-mojom targets required for the mojom sources to be parsed. +# +# import_dirs (optional) +# List of import directories that will get added when processing sources. +# +# input_root_override (optional) +# Root path for the .mojom files used to generate the namespaces for +# interfaces. Useful with targets outside //, e.g. in parent directories +# above "//". The default input root is // +# Example: Vivaldi's source root is "//vivaldi/", +# and "//vivaldi/chromium/" is "//" +# In such cases, not using this argument lead to the output files being +# located in different directories than expected. +# +# testonly (optional) +# +# visibility (optional) +# +# visibility_blink (optional) +# The value to use for visibility for the blink variant. If unset, +# |visibility| is used. +# +# cpp_only (optional) +# If set to true, only the C++ bindings targets will be generated. +# +# NOTE: If the global |enable_mojom_fuzzer| build arg is true, JS bindings +# will still be generated even when |cpp_only| is set to |true|, unless +# you also set |enable_fuzzing| to |false| in your mojom target. +# +# cpp_typemaps (optional) +# A list of typemaps to be applied to the generated C++ bindings for this +# mojom target. Note that this only applies to the non-Blink variant of +# generated C++ bindings. +# +# Every typemap is a GN scope describing how one or more mojom types maps +# to a non-mojom C++ type, including necessary deps and headers required +# for the mapping to work. See the Typemaps section below. +# +# blink_cpp_typemaps (optional) +# Same as above, but for the Blink variant of generated C++ bindings. +# +# cpp_proxy_target (optional) +# The name of a target which all C++ dependencies will link against +# instead of linking directly against this mojom target's generated C++ +# sources. Normally when declaring invoking the mojom("foo") target, GN +# emits a source_set or component target named "foo" which encompasses the +# default variant of generated C++ bindings. This changes that to instead +# emit a group("foo") which merely forwards public_deps to the named +# `cpp_proxy_target`. That target must in turn depend on +# "foo_cpp_sources". +# +# This is useful primarily in conjunction with export_define et al to +# embed generated C++ bindings within an existing component target. +# +# blink_cpp_proxy_target (optional) +# Same concept as `cpp_proxy_target` above, but affects the generated +# "foo_blink" Blink-variant C++ bindings. +# +# cpp_configs (optional) +# A list of extra configs to apply to the default variant of generated C++ +# bindings. +# +# blink_cpp_configs (optional) +# A list of extra configs to apply to the Blink variant of generated C++ +# bindings. +# +# mojom_source_deps (optional) +# A list of mojoms this target depends upon. This is equivalent to +# public_deps except that the C++ bindings depend on each of the named +# "foo" targets' "foo_cpp_sources" rather than on foo's +# `cpp_proxy_target`. It only makes sense to use this for dependencies +# that set `cpp_proxy_target`, and only when the dependent mojom() would +# otherwise have circular dependencies with that proxy target. +# +# mojom_blink_source_deps (optional) +# Same as above but depends on "foo_blink_cpp_sources" and is used for +# dependencies that specify a `blink_cpp_proxy_target`. +# +# generate_java (optional) +# If set to true, Java bindings are generated for Android builds. If +# |cpp_only| is set to true, it overrides this to prevent generation of +# Java bindings. +# +# enable_js_fuzzing (optional) +# Enables generation of javascript fuzzing sources for the target if the +# global build arg |enable_mojom_fuzzer| is also set to |true|. +# Defaults to |true|. If JS fuzzing generation is enabled for a target, +# the target will always generate JS bindings even if |cpp_only| is set to +# |true|. See note above. +# +# enable_mojolpm_fuzzing (optional) +# Enables generation of fuzzing sources for the target if the global build +# arg |enable_mojom_fuzzer| is also set to |true|. Defaults to |true|. +# +# support_lazy_serialization (optional) +# If set to |true|, generated C++ bindings will effectively prefer to +# transmit messages in an unserialized form when going between endpoints +# in the same process. This avoids the runtime cost of serialization, +# deserialization, and validation logic at the expensive of increased +# code size. Defaults to |false|. +# +# disable_variants (optional) +# If |true|, no variant sources will be generated for the target. Defaults +# to |false|. +# +# disallow_native_types (optional) +# If set to |true|, mojoms in this target may not apply the [Native] +# attribute to struct or enum declarations. This avoids emitting code +# which depends on legacy IPC serialization. Default is |false|, meaning +# [Native] types are allowed. +# +# disallow_interfaces (optional) +# If set to |true|, mojoms in this target may not define interfaces. +# Generates bindings with a smaller set of dependencies. Defaults to +# |false|. +# +# scramble_message_ids (optional) +# If set to |true| (the default), generated mojom interfaces will use +# scrambled ordinal identifiers in encoded messages. +# +# component_output_prefix (optional) +# The prefix to use for the output_name of any component library emitted +# for generated C++ bindings. If this is omitted, C++ bindings targets are +# emitted as source_sets instead. Because this controls the name of the +# output shared library binary in the root output directory, it must be +# unique across the entire build configuration. +# +# This is required if |component_macro_prefix| is specified. +# +# component_macro_prefix (optional) +# This specifies a macro prefix to use for component export macros and +# should therefore be globally unique in the project. For example if this +# is "FOO_BAR", then the generated C++ sources will be built with +# IS_FOO_BAR_{suffix}_IMPL defined, and the generated public headers will +# annotate public symbol definitions with +# COMPONENT_EXPORT(FOO_BAR_{suffix}). "suffix" in this case depends on +# which internal subtarget is generating the code (e.g. "SHARED", or a +# variant name like "BLINK"). +# +# enabled_features (optional) +# Definitions in a mojom file can be guarded by an EnableIf attribute. If +# the value specified by the attribute does not match any items in the +# list of enabled_features, the definition will be disabled, with no code +# emitted for it. +# +# generate_closure_exports (optional) +# Generates JS lite bindings will use goog.provide and goog.require +# annotations to export its symbols and import core Mojo bindings support +# and other mojom dependency modules. Use this if you plan to compile your +# bindings into a larger JS binary. Defaults to |false|, instead +# generating JS lite bindings which assume they will be manually loaded in +# correct dependency order. Note that this only has an effect if +# the |enable_mojom_closure_compile| global arg is set to |true| as well. +# +# generate_webui_js_bindings (optional) +# Generate WebUI bindings in JavaScript rather than TypeScript. Defaults +# to false. ChromeOS only parameter. +# +# generate_legacy_js_bindings (optional) +# Generate js_data_deps target containing legacy JavaScript bindings files +# for Blink tests and other non-WebUI users when generating TypeScript +# bindings for WebUI. Ignored if generate_webui_js_bindings is set to +# true. +# +# js_generate_struct_deserializers (optional) +# Generates JS deerialize methods for structs. +# +# extra_cpp_template_paths (optional) +# List of extra C++ templates that are used to generate additional source +# and/or header files. The templates should end with extension ".tmpl". +# +# webui_module_path (optional) +# The path or URL at which modules generated by this target will be +# accessible to WebUI pages. This may either be an absolute path or +# a full URL path starting with "chrome://resources/mojo". If this path +# is not specified, WebUI bindings will not be generated. +# +# If an absolute path, a WebUI page may only import these modules if +# they are added to that page's data source (usually by adding the +# modules to the mojo_files list for build_webui(), or by listing the +# files as inputs to the page's ts_library() and/or generate_grd() build +# steps. +# +# If this is is instead a URL string starting with +# "chrome://resources/mojo", the resulting bindings files should +# be added to one of the lists in ui/webui/resources/mojo/BUILD.gn, +# at which point they will be made available to all WebUI pages at the +# given URL. +# +# Note: WebUI module bindings are generated in TypeScript by default, +# unless |generate_webui_js_bindings| is specified as true. +# +# The following parameters are used to support the component build. They are +# needed so that bindings which are linked with a component can use the same +# export settings for classes. The first three are for the chromium variant, and +# the last three are for the blink variant. These parameters can also override +# |component_macro_prefix| for a specific variant, allowing e.g. one variant +# to be linked into a larger non-mojom component target, while all other +# variants get their own unique component target. +# export_class_attribute (optional) +# The attribute to add to the class declaration. e.g. "CONTENT_EXPORT" +# export_define (optional) +# A define to be added to the source_set which is needed by the export +# header. e.g. "CONTENT_IMPLEMENTATION=1" +# export_header (optional) +# A header to be added to the generated bindings to support the component +# build. e.g. "content/common/content_export.h" +# export_class_attribute_blink (optional) +# export_define_blink (optional) +# export_header_blink (optional) +# These three parameters are the blink variants of the previous 3. +# +# The following parameters are used to correct component build dependencies. +# They are needed so mojom-mojom dependencies follow the rule that dependencies +# on a source set in another component are replaced by a dependency on the +# containing component. The first two are for the chromium variant; the other +# two are for the blink variant. +# overridden_deps (optional) +# The list of mojom deps to be overridden. +# component_deps (optional) +# The list of component deps to add to replace overridden_deps. +# overridden_deps_blink (optional) +# component_deps_blink (optional) +# These two parameters are the blink variants of the previous two. +# +# check_includes_blink (optional) +# Overrides the check_includes variable for the blink variant. +# If check_includes_blink is not defined, the check_includes variable +# retains its original value. +# +# Typemaps +# ======== +# The cpp_typemaps and blink_cpp_typemaps each specify an optional list of +# typemapping configurations. Each configuration is a GN scope with metadata +# describing what and how to map. +# +# Typemap scope parameters: +# types +# A list of type specifications for this typemap. Each type specification +# is a nested GN scope which can be expressed with the following syntax: +# +# { +# mojom = "foo.mojom.Bar" +# cpp = "::foo::LegitBar" +# move_only = true +# # etc... +# } +# +# Each type specification supports the following values: +# +# mojom (required) +# The fully qualified name of a mojom type to be mapped. This is a +# string like "foo.mojom.Bar". +# +# cpp (required) +# The fully qualified name of the C++ type to which the mojom type +# should be mapped in generated bindings. This is a string like +# "::base::Value" or "std::vector<::base::Value>". +# +# copyable_pass_by_value (optional) +# A boolean value (default false) which effectively indicates +# whether the C++ type is very cheap to copy. If so, generated +# bindings will pass by value but not use std::move() at call sites. +# +# default_constructible (optional) +# A boolean value (default true) which indicates whether the C++ +# type is default constructible. If a C++ type is not default +# constructible (e.g. the implementor of the type prefers not to +# publicly expose a default constructor that creates an object in an +# invalid state), Mojo will instead construct C++ type with an +# argument of the type `mojo::DefaultConstruct::Tag` (essentially a +# passkey-like type specifically for this use case). +# +# force_serialize (optional) +# A boolean value (default false) which disables lazy serialization +# of the typemapped type if lazy serialization is enabled for the +# mojom target applying this typemap. +# +# forward_declaration (optional) +# A forward declaration of the C++ type, which bindings that don't +# need the full type definition can use to reduce the size of +# the generated code. This is a string like +# "namespace base { class Value; }". +# +# hashable (optional) +# A boolean value (default false) indicating whether the C++ type is +# hashable. Set to true if true AND needed (i.e. you need to use the +# type as the key of a mojom map). +# +# move_only (optional) +# A boolean value (default false) which indicates whether the C++ +# type is move-only. If true, generated bindings will pass the type +# by value and use std::move() at call sites. +# +# nullable_is_same_type (optional) +# A boolean value (default false) which indicates that the C++ type +# has some baked-in semantic notion of a "null" state. If true, the +# traits for the type must define IsNull and SetToNull methods. +# +# When false, nullable fields are represented by wrapping the C++ +# type with absl::optional, and null values are simply +# absl::nullopt. +# +# Additional typemap scope parameters: +# +# traits_headers (optional) +# Headers which must be included in the generated mojom in order for +# serialization to be possible. This generally means including at least +# the header for the corresponding mojom traits definitions. +# +# traits_private_headers (optional) +# Headers which must be included in generated C++ serialization code for +# a mojom using the typemap. This should be used only when including a +# header in |traits_headers| is problematic for compilation, as is +# sometimes the case with legacy IPC message headers. +# +# traits_sources (optional) +# The references to the source files (typically a single .cc and .h file) +# defining an appropriate set of EnumTraits or StructTraits, etc for the +# the type-mapping. Using this will cause the listed sources to be +# integrated directly into the dependent mojom's generated type-mapping +# targets. +# +# Prefer using |traits_public_deps| over inlined |traits_sources|, as this +# will generally lead to easier build maintenance over time. +# +# NOTE: If a typemap is shared by Blink and non-Blink bindings, you cannot +# use this and MUST use |traits_public_deps| to reference traits built +# within a separate target. +# +# traits_deps / traits_public_deps (optional) +# Any dependencies of sources in |traits_headers| or |traits_sources| must +# be listed here. +# +template("mojom") { + assert( + defined(invoker.sources) || defined(invoker.deps) || + defined(invoker.public_deps), + "\"sources\" or \"deps\" must be defined for the $target_name template.") + + if (defined(invoker.export_class_attribute) || + defined(invoker.export_define) || defined(invoker.export_header)) { + assert(defined(invoker.export_class_attribute)) + assert(defined(invoker.export_define) || defined(invoker.cpp_configs)) + assert(defined(invoker.export_header)) + } + if (defined(invoker.export_class_attribute_blink) || + defined(invoker.export_define_blink) || + defined(invoker.export_header_blink)) { + assert(defined(invoker.export_class_attribute_blink)) + assert(defined(invoker.export_define_blink) || + defined(invoker.blink_cpp_configs)) + assert(defined(invoker.export_header_blink)) + + # Not all platforms use the Blink variant, so make sure GN doesn't complain + # about these values being inconsequential. + not_needed(invoker, + [ + "export_class_attribute_blink", + "export_define_blink", + "export_header_blink", + ]) + } + if (defined(invoker.overridden_deps) || defined(invoker.component_deps)) { + assert(defined(invoker.overridden_deps)) + assert(defined(invoker.component_deps)) + } + + if (defined(invoker.overridden_deps_blink) || + defined(invoker.component_deps_blink)) { + assert(defined(invoker.overridden_deps_blink)) + assert(defined(invoker.component_deps_blink)) + } + + # Type-mapping may be disabled or we may not generate C++ bindings. + not_needed(invoker, + [ + "cpp_typemaps", + "blink_cpp_typemaps", + ]) + + require_full_cpp_deps = + !defined(invoker.disallow_native_types) || + !invoker.disallow_native_types || !defined(invoker.disallow_interfaces) || + !invoker.disallow_interfaces + + all_deps = [] + mojom_cpp_deps = [] + if (defined(invoker.deps)) { + all_deps += invoker.deps + mojom_cpp_deps += invoker.deps + } + if (defined(invoker.public_deps)) { + all_deps += invoker.public_deps + mojom_cpp_deps += invoker.public_deps + } + if (defined(invoker.mojom_source_deps)) { + all_deps += invoker.mojom_source_deps + } + if (defined(invoker.mojom_blink_source_deps)) { + all_deps += invoker.mojom_blink_source_deps + } + not_needed([ "mojom_deps" ]) + + if (defined(invoker.component_macro_prefix)) { + assert(defined(invoker.component_output_prefix)) + } + + group("${target_name}__is_mojom") { + } + + # Explicitly ensure that all dependencies (invoker.deps and + # invoker.public_deps) are mojom targets. + group("${target_name}__check_deps_are_all_mojom") { + deps = [] + foreach(d, all_deps) { + name = get_label_info(d, "label_no_toolchain") + toolchain = get_label_info(d, "toolchain") + deps += [ "${name}__is_mojom(${toolchain})" ] + } + } + + sources_list = [] + if (defined(invoker.sources)) { + sources_list = invoker.sources + } + + # Listed sources may be relative to the current target dir, or they may be + # absolute paths, including paths to generated mojom files. While those are + # fine as-is for input references, deriving output paths can be more subtle. + # + # Here we rewrite all source paths to be relative to the root build dir and + # strip any root_gen_dir prefixes. + # + # So for a target in //foo/bar with: + # + # sources = [ + # "a.mojom", + # "b/c.mojom", + # "//baz/d.mojom", + # "$target_gen_dir/e.mojom", + # ] + # + # output_file_base_paths will be: + # + # [ + # "foo/bar/a.mojom", + # "foo/bar/b/c.mojom", + # "baz/d.mojom", + # "foo/bar/e.mojom", + # ] + # + # This result is essentially a list of base filename paths which are suitable + # for the naming of any generated output files derived from their + # corresponding input mojoms. These paths are always considered to be relative + # to root_gen_dir. + if (defined(invoker.input_root_override)) { + source_abspaths = rebase_path(sources_list, invoker.input_root_override) + } else { + source_abspaths = rebase_path(sources_list, "//") + } + output_file_base_paths = [] + foreach(path, source_abspaths) { + output_file_base_paths += + [ string_replace(path, rebase_path(root_gen_dir, "//") + "/", "") ] + } + + # Sanity check that either all input files have a .mojom extension, or + # all input files have a .test-mojom extension AND |testonly| is |true|. + sources_list_filenames = + process_file_template(sources_list, "{{source_file_part}}") + sources_list_filenames_with_mojom_extension = + process_file_template(sources_list, "{{source_name_part}}.mojom") + if (sources_list_filenames != sources_list_filenames_with_mojom_extension) { + sources_list_filenames_with_test_mojom_extension = + process_file_template(sources_list, "{{source_name_part}}.test-mojom") + if (sources_list_filenames == + sources_list_filenames_with_test_mojom_extension) { + assert( + defined(invoker.testonly) && invoker.testonly, + "mojom targets for .test-mojom files must set |testonly| to |true|") + } else { + assert( + false, + "One or more mojom files has an invalid extension. The only " + + "allowed extensions are .mojom and .test-mojom, and any given " + + "mojom target must use one or the other exclusively.") + } + } + + build_metadata_filename = "$target_gen_dir/$target_name.build_metadata" + build_metadata = { + } + build_metadata.sources = rebase_path(sources_list, target_gen_dir) + build_metadata.deps = [] + foreach(dep, all_deps) { + dep_target_gen_dir = get_label_info(dep, "target_gen_dir") + dep_name = get_label_info(dep, "name") + build_metadata.deps += + [ rebase_path("$dep_target_gen_dir/$dep_name.build_metadata", + target_gen_dir) ] + } + write_file(build_metadata_filename, build_metadata, "json") + + generate_js_fuzzing = + (!defined(invoker.enable_js_fuzzing) || invoker.enable_js_fuzzing) && + enable_mojom_fuzzer && (!defined(invoker.testonly) || !invoker.testonly) + + generate_mojolpm_fuzzing = + (!defined(invoker.enable_mojolpm_fuzzing) || + invoker.enable_mojolpm_fuzzing) && enable_mojom_fuzzer && + (!defined(invoker.testonly) || !invoker.testonly) + + parser_target_name = "${target_name}__parser" + parser_deps = [] + foreach(dep, all_deps) { + _label = get_label_info(dep, "label_no_toolchain") + parser_deps += [ "${_label}__parser" ] + } + if (defined(invoker.parser_deps)) { + parser_deps += invoker.parser_deps + } + if (sources_list == []) { + # Even without sources we generate a parser target to at least forward + # other parser dependencies. + group(parser_target_name) { + public_deps = parser_deps + } + } else { + enabled_features = [] + if (defined(invoker.enabled_features)) { + enabled_features += invoker.enabled_features + } + if (is_posix) { + enabled_features += [ "is_posix" ] + } + if (is_android) { + enabled_features += [ "is_android" ] + } else if (is_chromeos_ash) { + enabled_features += [ + "is_chromeos", + "is_chromeos_ash", + ] + } else if (is_chromeos_lacros) { + enabled_features += [ + "is_chromeos", + "is_chromeos_lacros", + ] + } else if (is_fuchsia) { + enabled_features += [ "is_fuchsia" ] + } else if (is_ios) { + enabled_features += [ "is_ios" ] + } else if (is_linux) { + enabled_features += [ "is_linux" ] + } else if (is_mac) { + enabled_features += [ "is_mac" ] + } else if (is_win) { + enabled_features += [ "is_win" ] + } + + if (is_apple) { + enabled_features += [ "is_apple" ] + } + + action(parser_target_name) { + allow_remote = true + custom_processor = "mojom_parser" + script = mojom_parser_script + inputs = mojom_parser_sources + ply_sources + [ build_metadata_filename ] + sources = sources_list + public_deps = parser_deps + outputs = [] + foreach(base_path, output_file_base_paths) { + filename = get_path_info(base_path, "file") + dirname = get_path_info(base_path, "dir") + outputs += [ "$root_gen_dir/$dirname/${filename}-module" ] + } + + filelist = [] + foreach(source, sources_list) { + filelist += [ rebase_path(source, root_build_dir) ] + } + + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] + + args = [ + # Resolve relative input mojom paths against both the root src dir and + # the root gen dir. + "--input-root", + rebase_path("//.", root_build_dir), + "--input-root", + rebase_path(root_gen_dir, root_build_dir), + + "--output-root", + rebase_path(root_gen_dir, root_build_dir), + + "--mojom-file-list=" + rebase_path(rsp_file, root_build_dir), + + "--check-imports", + rebase_path(build_metadata_filename, root_build_dir), + ] + + if (defined(invoker.input_root_override)) { + args += [ + "--input-root", + rebase_path(invoker.input_root_override, root_build_dir), + ] + } + + foreach(enabled_feature, enabled_features) { + args += [ + "--enable-feature", + enabled_feature, + ] + } + + if (defined(invoker.webui_module_path)) { + args += [ + "--add-module-metadata", + "webui_module_path=${invoker.webui_module_path}", + ] + if (defined(invoker.generate_webui_js_bindings) && + invoker.generate_webui_js_bindings) { + args += [ + "--add-module-metadata", + "generate_webui_js=True", + ] + } + } + } + } + + generator_cpp_message_ids_target_name = "${target_name}__generate_message_ids" + + # Generate code that is shared by different variants. + if (sources_list != []) { + base_dir = "//" + if (defined(invoker.input_root_override)) { + base_dir = invoker.input_root_override + } + + common_generator_args = [ + "--use_bundled_pylibs", + "-o", + rebase_path(root_gen_dir, root_build_dir), + "generate", + "-d", + rebase_path(base_dir, root_build_dir), + "-I", + rebase_path("//", root_build_dir), + "--bytecode_path", + rebase_path("$root_gen_dir/mojo/public/tools/bindings", root_build_dir), + ] + if (defined(invoker.input_root_override)) { + common_generator_args += [ + "-I", + rebase_path(invoker.input_root_override, root_build_dir), + ] + } + + if (defined(invoker.disallow_native_types) && + invoker.disallow_native_types) { + common_generator_args += [ "--disallow_native_types" ] + } + + if (defined(invoker.disallow_interfaces) && invoker.disallow_interfaces) { + common_generator_args += [ "--disallow_interfaces" ] + } + + if (defined(invoker.import_dirs)) { + foreach(import_dir, invoker.import_dirs) { + common_generator_args += [ + "-I", + rebase_path(import_dir, root_build_dir), + ] + } + } + + if (defined(invoker.component_macro_prefix)) { + shared_component_export_macro = + "COMPONENT_EXPORT(${invoker.component_macro_prefix}_SHARED)" + shared_component_impl_macro = + "IS_${invoker.component_macro_prefix}_SHARED_IMPL" + shared_component_output_name = "${invoker.component_output_prefix}_shared" + } else if (defined(invoker.export_class_attribute_shared) || + defined(invoker.export_class_attribute)) { + if (defined(invoker.export_class_attribute_shared)) { + assert(defined(invoker.export_header_shared)) + shared_component_export_macro = invoker.export_class_attribute_shared + shared_component_impl_macro = invoker.export_define_shared + } else { + assert(!defined(invoker.export_header_shared)) + + # If no explicit shared attribute/define was provided by the invoker, + # we derive some reasonable settings frorm the default variant. + shared_component_export_macro = "COMPONENT_EXPORT(MOJOM_SHARED_" + + invoker.export_class_attribute + ")" + shared_component_impl_macro = + "IS_MOJOM_SHARED_" + invoker.export_class_attribute + "_IMPL" + } + + if (defined(invoker.component_output_prefix)) { + shared_component_output_name = + "${invoker.component_output_prefix}_shared" + } else { + shared_component_output_name = "${target_name}_shared" + } + } + + action(generator_cpp_message_ids_target_name) { + allow_remote = true + script = mojom_generator_script + inputs = mojom_generator_sources + jinja2_sources + sources = sources_list + + [ "$root_gen_dir/mojo/public/tools/bindings/cpp_templates.zip" ] + deps = [ + ":$parser_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + if (defined(invoker.parser_deps)) { + deps += invoker.parser_deps + } + outputs = [] + args = common_generator_args + filelist = [] + foreach(source, sources_list) { + filelist += [ rebase_path(source, root_build_dir) ] + } + foreach(base_path, output_file_base_paths) { + filename = get_path_info(base_path, "file") + dirname = get_path_info(base_path, "dir") + inputs += [ "$root_gen_dir/$dirname/${filename}-module" ] + outputs += [ "$root_gen_dir/$base_path-shared-message-ids.h" ] + } + + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] + + args += [ + "--filelist=" + rebase_path(rsp_file, root_build_dir), + "--generate_non_variant_code", + "--generate_message_ids", + "-g", + "c++", + ] + + if (!defined(invoker.scramble_message_ids) || + invoker.scramble_message_ids) { + inputs += message_scrambling_inputs + args += message_scrambling_args + } + } + + generator_shared_target_name = "${target_name}_shared__generator" + + action(generator_shared_target_name) { + allow_remote = true + visibility = [ ":*" ] + script = mojom_generator_script + inputs = mojom_generator_sources + jinja2_sources + sources = sources_list + + [ "$root_gen_dir/mojo/public/tools/bindings/cpp_templates.zip" ] + deps = [ + ":$parser_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + if (defined(invoker.parser_deps)) { + deps += invoker.parser_deps + } + + outputs = [] + args = common_generator_args + filelist = [] + foreach(source, sources_list) { + filelist += [ rebase_path(source, root_build_dir) ] + } + foreach(base_path, output_file_base_paths) { + # Need the mojom-module as an input to this action. + filename = get_path_info(base_path, "file") + dirname = get_path_info(base_path, "dir") + inputs += [ "$root_gen_dir/$dirname/${filename}-module" ] + + outputs += [ + "$root_gen_dir/$base_path-features.h", + "$root_gen_dir/$base_path-params-data.h", + "$root_gen_dir/$base_path-shared-internal.h", + "$root_gen_dir/$base_path-shared.cc", + "$root_gen_dir/$base_path-shared.h", + ] + } + + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] + + args += [ + "--filelist=" + rebase_path(rsp_file, root_build_dir), + "--generate_non_variant_code", + "-g", + "c++", + ] + + if (defined(shared_component_export_macro)) { + args += [ + "--export_attribute", + shared_component_export_macro, + "--export_header", + "base/component_export.h", + ] + } + + # Enable adding annotations to generated C++ headers that are used for + # cross-references in CodeSearch. + if (enable_kythe_annotations) { + args += [ "--enable_kythe_annotations" ] + } + } + } else { + group(generator_cpp_message_ids_target_name) { + } + } + + shared_cpp_sources_target_name = "${target_name}_shared_cpp_sources" + source_set(shared_cpp_sources_target_name) { + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + configs += [ "//build/config/compiler:wexit_time_destructors" ] + deps = [] + public_deps = [] + if (output_file_base_paths != []) { + sources = [] + foreach(base_path, output_file_base_paths) { + sources += [ + "$root_gen_dir/$base_path-features.h", + "$root_gen_dir/$base_path-params-data.h", + "$root_gen_dir/$base_path-shared-internal.h", + "$root_gen_dir/$base_path-shared.cc", + "$root_gen_dir/$base_path-shared.h", + ] + } + public_deps += [ ":$generator_shared_target_name" ] + } + if (require_full_cpp_deps) { + public_deps += [ "//mojo/public/cpp/bindings" ] + } else { + public_deps += [ "//mojo/public/cpp/bindings:bindings_base" ] + } + foreach(d, all_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append shared_cpp_sources_suffix + # to get the cpp dependency name. + full_name = get_label_info("$d", "label_no_toolchain") + public_deps += [ "${full_name}_shared" ] + } + if (defined(shared_component_impl_macro)) { + defines = [ shared_component_impl_macro ] + } + } + + shared_cpp_library_target_name = "${target_name}_shared" + if (defined(shared_component_output_name)) { + component(shared_cpp_library_target_name) { + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + output_name = "$shared_component_output_name" + public_deps = [ ":$shared_cpp_sources_target_name" ] + } + } else { + group(shared_cpp_library_target_name) { + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + public_deps = [ ":$shared_cpp_sources_target_name" ] + } + } + + if (generate_mojolpm_fuzzing) { + # This block generates the proto files used for the MojoLPM fuzzer, + # and the corresponding proto targets that will be linked in the fuzzer + # targets. These are independent of the typemappings, and can be done + # separately here. + + generator_mojolpm_proto_target_name = + "${target_name}_mojolpm_proto_generator" + + action(generator_mojolpm_proto_target_name) { + allow_remote = true + script = mojom_generator_script + inputs = mojom_generator_sources + jinja2_sources + sources = + invoker.sources + [ + "$root_gen_dir/mojo/public/tools/bindings/cpp_templates.zip", + "$root_gen_dir/mojo/public/tools/bindings/mojolpm_templates.zip", + ] + deps = [ + ":$parser_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + + outputs = [] + args = common_generator_args + filelist = [] + + # Split the input into generated and non-generated source files. They + # need to be processed separately. + gen_dir_path_wildcard = get_path_info("//", "gen_dir") + "/*" + non_gen_sources = + filter_exclude(invoker.sources, [ gen_dir_path_wildcard ]) + gen_sources = filter_include(invoker.sources, [ gen_dir_path_wildcard ]) + + foreach(source, non_gen_sources) { + filelist += [ rebase_path(source, root_build_dir) ] + inputs += [ "$target_gen_dir/$source-module" ] + outputs += [ "$target_gen_dir/$source.mojolpm.proto" ] + } + + foreach(source, gen_sources) { + filelist += [ rebase_path(source, root_build_dir) ] + + # For generated files, we assume they're in the target_gen_dir or a + # sub-folder of it. Rebase the path so we can get the relative location. + source_file = rebase_path(source, target_gen_dir) + inputs += [ "$target_gen_dir/$source_file-module" ] + outputs += [ "$target_gen_dir/$source_file.mojolpm.proto" ] + } + + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] + + args += [ + "--filelist=" + rebase_path(rsp_file, root_build_dir), + "--generate_non_variant_code", + "-g", + "mojolpm", + ] + } + + mojolpm_proto_target_name = "${target_name}_mojolpm_proto" + if (defined(invoker.sources)) { + proto_library(mojolpm_proto_target_name) { + testonly = true + generate_python = false + + # Split the input into generated and non-generated source files. They + # need to be processed separately. + gen_dir_path_wildcard = get_path_info("//", "gen_dir") + "/*" + non_gen_sources = + filter_exclude(invoker.sources, [ gen_dir_path_wildcard ]) + gen_sources = filter_include(invoker.sources, [ gen_dir_path_wildcard ]) + sources = process_file_template( + non_gen_sources, + [ "{{source_gen_dir}}/{{source_file_part}}.mojolpm.proto" ]) + sources += process_file_template( + gen_sources, + [ "{{source_dir}}/{{source_file_part}}.mojolpm.proto" ]) + + import_dirs = [ "//" ] + proto_in_dir = "${root_gen_dir}" + proto_out_dir = "." + proto_deps = [ ":$generator_mojolpm_proto_target_name" ] + link_deps = [ "//mojo/public/tools/fuzzers:mojolpm_proto" ] + + foreach(d, all_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append mojolpm_proto_suffix + # to get the proto dependency name. + full_name = get_label_info("$d", "label_no_toolchain") + proto_deps += [ "${full_name}_mojolpm_proto" ] + link_deps += [ "${full_name}_mojolpm_proto" ] + } + } + } else { + group(mojolpm_proto_target_name) { + testonly = true + public_deps = [ "//mojo/public/tools/fuzzers:mojolpm_proto" ] + if (defined(generator_shared_target_name)) { + public_deps += [ ":$generator_shared_target_name" ] + } + foreach(d, all_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append #mojolpm_proto_suffix + # to get the proto dependency name. + full_name = get_label_info("$d", "label_no_toolchain") + public_deps += [ "${full_name}_mojolpm_proto" ] + } + } + } + } + + # Generate code for variants. + default_variant = { + component_macro_suffix = "" + } + if ((!defined(invoker.disable_variants) || !invoker.disable_variants) && + use_blink) { + blink_variant = { + variant = "blink" + component_macro_suffix = "_BLINK" + for_blink = true + } + enabled_configurations = [ + default_variant, + blink_variant, + ] + } else { + enabled_configurations = [ default_variant ] + } + foreach(bindings_configuration, enabled_configurations) { + cpp_only = false + if (defined(invoker.cpp_only)) { + cpp_only = invoker.cpp_only + } + variant_suffix = "" + if (defined(bindings_configuration.variant)) { + variant = bindings_configuration.variant + variant_suffix = "_${variant}" + cpp_only = true + } + + cpp_typemap_configs = [] + export_defines = [] + export_defines_overridden = false + force_source_set = false + proxy_target = "" + extra_configs = [] + output_visibility = [] + output_visibility = [ "*" ] + cpp_source_deps = [] + if (defined(bindings_configuration.for_blink) && + bindings_configuration.for_blink) { + if (defined(invoker.blink_cpp_typemaps)) { + cpp_typemap_configs = invoker.blink_cpp_typemaps + } + if (defined(invoker.export_define_blink)) { + export_defines_overridden = true + export_defines = [ invoker.export_define_blink ] + force_source_set = true + } + if (defined(invoker.blink_cpp_configs)) { + extra_configs += invoker.blink_cpp_configs + } + if (defined(invoker.blink_cpp_proxy_target)) { + proxy_target = invoker.blink_cpp_proxy_target + } + if (defined(invoker.visibility_blink)) { + output_visibility = [] + output_visibility = invoker.visibility_blink + } + if (defined(invoker.mojom_blink_source_deps)) { + cpp_source_deps = invoker.mojom_blink_source_deps + } + } else { + if (defined(invoker.cpp_typemaps)) { + cpp_typemap_configs = invoker.cpp_typemaps + } + if (defined(invoker.export_define)) { + export_defines_overridden = true + export_defines = [ invoker.export_define ] + force_source_set = true + } + if (defined(invoker.cpp_configs)) { + extra_configs += invoker.cpp_configs + } + if (defined(invoker.cpp_proxy_target)) { + proxy_target = invoker.cpp_proxy_target + } + if (defined(invoker.visibility)) { + output_visibility = [] + output_visibility = invoker.visibility + } + if (defined(invoker.mojom_source_deps)) { + cpp_source_deps = invoker.mojom_source_deps + } + } + not_needed([ "cpp_typemap_configs" ]) + if (proxy_target != "") { + group("${target_name}${variant_suffix}__has_cpp_proxy") { + } + } + + if (!export_defines_overridden && defined(invoker.component_macro_prefix)) { + output_name_override = + "${invoker.component_output_prefix}${variant_suffix}" + export_defines = + [ "IS_${invoker.component_macro_prefix}" + + "${bindings_configuration.component_macro_suffix}_IMPL" ] + } + + generate_java = false + if (!cpp_only && defined(invoker.generate_java)) { + generate_java = invoker.generate_java + } + type_mappings_target_name = "${target_name}${variant_suffix}__type_mappings" + type_mappings_path = + "$target_gen_dir/${target_name}${variant_suffix}__type_mappings" + if (sources_list != []) { + export_args = [] + export_args_overridden = false + if (defined(bindings_configuration.for_blink) && + bindings_configuration.for_blink) { + if (defined(invoker.export_class_attribute_blink)) { + export_args_overridden = true + export_args += [ + "--export_attribute", + invoker.export_class_attribute_blink, + "--export_header", + invoker.export_header_blink, + ] + } + } else if (defined(invoker.export_class_attribute)) { + export_args_overridden = true + export_args += [ + "--export_attribute", + invoker.export_class_attribute, + "--export_header", + invoker.export_header, + ] + } + if (!export_args_overridden && defined(invoker.component_macro_prefix)) { + export_args += [ + "--export_attribute", + "COMPONENT_EXPORT(${invoker.component_macro_prefix}" + + "${bindings_configuration.component_macro_suffix})", + "--export_header", + "base/component_export.h", + ] + } + + generator_cpp_output_suffixes = [] + variant_dash_suffix = "" + if (defined(variant)) { + variant_dash_suffix = "-${variant}" + } + generator_cpp_output_suffixes += [ + "${variant_dash_suffix}-forward.h", + "${variant_dash_suffix}-import-headers.h", + "${variant_dash_suffix}-test-utils.h", + "${variant_dash_suffix}.cc", + "${variant_dash_suffix}.h", + ] + + generator_target_name = "${target_name}${variant_suffix}__generator" + + # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. + action(generator_target_name) { + allow_remote = true + visibility = [ ":*" ] + script = mojom_generator_script + inputs = mojom_generator_sources + jinja2_sources + sources = + sources_list + [ + "$root_gen_dir/mojo/public/tools/bindings/cpp_templates.zip", + type_mappings_path, + ] + if (generate_mojolpm_fuzzing && + !defined(bindings_configuration.variant)) { + sources += [ + "$root_gen_dir/mojo/public/tools/bindings/mojolpm_templates.zip", + ] + } + deps = [ + ":$parser_target_name", + ":$type_mappings_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + + if (defined(invoker.parser_deps)) { + deps += invoker.parser_deps + } + outputs = [] + args = common_generator_args + export_args + filelist = [] + foreach(source, sources_list) { + filelist += [ rebase_path(source, root_build_dir) ] + } + foreach(base_path, output_file_base_paths) { + filename = get_path_info(base_path, "file") + dirname = get_path_info(base_path, "dir") + inputs += [ "$root_gen_dir/$dirname/${filename}-module" ] + + outputs += [ + "$root_gen_dir/${base_path}${variant_dash_suffix}-forward.h", + "$root_gen_dir/${base_path}${variant_dash_suffix}-import-headers.h", + "$root_gen_dir/${base_path}${variant_dash_suffix}-test-utils.h", + "$root_gen_dir/${base_path}${variant_dash_suffix}.cc", + "$root_gen_dir/${base_path}${variant_dash_suffix}.h", + ] + if (generate_mojolpm_fuzzing && + !defined(bindings_configuration.variant)) { + outputs += [ + "$root_gen_dir/${base_path}${variant_dash_suffix}-mojolpm.cc", + "$root_gen_dir/${base_path}${variant_dash_suffix}-mojolpm.h", + ] + } + } + + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] + args += [ + "--filelist=" + rebase_path("$rsp_file", root_build_dir), + "-g", + ] + + if (generate_mojolpm_fuzzing && + !defined(bindings_configuration.variant)) { + args += [ "c++,mojolpm" ] + } else { + args += [ "c++" ] + } + + if (defined(bindings_configuration.variant)) { + args += [ + "--variant", + bindings_configuration.variant, + ] + } + + args += [ + "--typemap", + rebase_path(type_mappings_path, root_build_dir), + ] + + if (defined(bindings_configuration.for_blink) && + bindings_configuration.for_blink) { + args += [ "--for_blink" ] + } + + if (defined(invoker.support_lazy_serialization) && + invoker.support_lazy_serialization) { + args += [ "--support_lazy_serialization" ] + } + + if (enable_kythe_annotations) { + args += [ "--enable_kythe_annotations" ] + } + + if (!defined(invoker.scramble_message_ids) || + invoker.scramble_message_ids) { + inputs += message_scrambling_inputs + args += message_scrambling_args + } + + if (defined(invoker.extra_cpp_template_paths)) { + foreach(extra_cpp_template, invoker.extra_cpp_template_paths) { + args += [ + "--extra_cpp_template_paths", + rebase_path(extra_cpp_template, root_build_dir), + ] + inputs += [ extra_cpp_template ] + + assert( + get_path_info(extra_cpp_template, "extension") == "tmpl", + "--extra_cpp_template_paths only accepts template files ending in extension .tmpl") + foreach(base_path, output_file_base_paths) { + template_file_name = get_path_info("$extra_cpp_template", "name") + outputs += [ "$root_gen_dir/${base_path}${variant_dash_suffix}-${template_file_name}" ] + } + } + } + } + } + + # Write the typemapping configuration for this target out to a file to be + # validated by a Python script. This helps catch mistakes that can't + # be caught by logic in GN. + _typemap_config_filename = + "$target_gen_dir/${target_name}${variant_suffix}.typemap_config" + _typemap_stamp_filename = "${_typemap_config_filename}.validated" + _typemap_validator_target_name = "${type_mappings_target_name}__validator" + _rebased_typemap_configs = [] + foreach(config, cpp_typemap_configs) { + _rebased_config = { + } + _rebased_config = config + if (defined(config.traits_headers)) { + _rebased_config.traits_headers = [] + _rebased_config.traits_headers = + rebase_path(config.traits_headers, "//") + } + if (defined(config.traits_private_headers)) { + _rebased_config.traits_private_headers = [] + _rebased_config.traits_private_headers = + rebase_path(config.traits_private_headers, "//") + } + _rebased_typemap_configs += [ _rebased_config ] + } + write_file(_typemap_config_filename, _rebased_typemap_configs, "json") + _mojom_target_name = target_name + + action(_typemap_validator_target_name) { + allow_remote = true + script = "$mojom_generator_root/validate_typemap_config.py" + inputs = [ _typemap_config_filename ] + outputs = [ _typemap_stamp_filename ] + args = [ + get_label_info(_mojom_target_name, "label_no_toolchain"), + rebase_path(_typemap_config_filename, root_build_dir), + rebase_path(_typemap_stamp_filename, root_build_dir), + ] + } + + action(type_mappings_target_name) { + allow_remote = true + inputs = + mojom_generator_sources + jinja2_sources + [ _typemap_stamp_filename ] + outputs = [ type_mappings_path ] + script = "$mojom_generator_root/generate_type_mappings.py" + deps = [ ":$_typemap_validator_target_name" ] + args = [ + "--output", + rebase_path(type_mappings_path, root_build_dir), + ] + + sources = [] + foreach(d, all_deps) { + name = get_label_info(d, "label_no_toolchain") + toolchain = get_label_info(d, "toolchain") + dependency_output = "${name}${variant_suffix}__type_mappings" + dependency_target = "${dependency_output}(${toolchain})" + deps += [ dependency_target ] + dependency_output_dir = + get_label_info(dependency_output, "target_gen_dir") + dependency_name = get_label_info(dependency_output, "name") + dependency_path = "$dependency_output_dir/${dependency_name}" + sources += [ dependency_path ] + args += [ + "--dependency", + rebase_path(dependency_path, root_build_dir), + ] + } + + # Newer GN-based typemaps are aggregated into a single config. + inputs += [ _typemap_config_filename ] + args += [ + "--cpp-typemap-config", + rebase_path(_typemap_config_filename, root_build_dir), + ] + } + + group("${target_name}${variant_suffix}_headers") { + public_deps = [] + if (sources_list != []) { + public_deps += [ + ":$generator_cpp_message_ids_target_name", + ":$generator_shared_target_name", + ":$generator_target_name", + ] + } + foreach(d, all_deps) { + full_name = get_label_info("$d", "label_no_toolchain") + public_deps += [ "${full_name}${variant_suffix}_headers" ] + } + if (defined(bindings_configuration.for_blink) && + bindings_configuration.for_blink) { + public_deps += [ "//mojo/public/cpp/bindings:wtf_support" ] + } + } + + js_data_deps_target_name = target_name + "_js_data_deps" + not_needed([ "js_data_deps_target_name" ]) + + if (!force_source_set && defined(invoker.component_macro_prefix)) { + sources_target_type = "component" + } else { + sources_target_type = "source_set" + } + + output_target_name = "${target_name}${variant_suffix}" + if (proxy_target != "") { + group(output_target_name) { + public_deps = [ proxy_target ] + visibility = output_visibility + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + } + sources_target_name = "${output_target_name}_cpp_sources" + } else { + sources_target_name = output_target_name + } + + target(sources_target_type, sources_target_name) { + if (defined(output_name_override)) { + output_name = output_name_override + } + visibility = output_visibility + [ + ":$output_target_name", + ":${target_name}_mojolpm", + ] + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + defines = export_defines + configs += [ "//build/config/compiler:wexit_time_destructors" ] + configs += extra_configs + if (output_file_base_paths != []) { + sources = [] + foreach(base_path, output_file_base_paths) { + foreach(suffix, generator_cpp_output_suffixes) { + sources += [ "$root_gen_dir/${base_path}$suffix" ] + } + } + } + deps = [ + ":$generator_cpp_message_ids_target_name", + "//mojo/public/cpp/bindings:struct_traits", + "//mojo/public/interfaces/bindings:bindings_headers", + ] + public_deps = [ + ":$shared_cpp_library_target_name", + "//base", + ] + if (require_full_cpp_deps) { + public_deps += [ "//mojo/public/cpp/bindings" ] + } else { + public_deps += [ "//mojo/public/cpp/bindings:bindings_base" ] + } + + if (sources_list != []) { + public_deps += [ ":$generator_target_name" ] + } + foreach(d, mojom_cpp_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append variant_suffix to + # get the cpp dependency name. + full_name = get_label_info(d, "label_no_toolchain") + public_deps += [ "${full_name}${variant_suffix}" ] + } + foreach(d, cpp_source_deps) { + full_name = get_label_info(d, "label_no_toolchain") + public_deps += [ + "${full_name}${variant_suffix}__has_cpp_proxy", + "${full_name}${variant_suffix}_cpp_sources", + ] + } + if (defined(bindings_configuration.for_blink) && + bindings_configuration.for_blink) { + if (defined(invoker.overridden_deps_blink)) { + foreach(d, invoker.overridden_deps_blink) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append variant_suffix + # to get the cpp dependency name. + full_name = get_label_info("$d", "label_no_toolchain") + public_deps -= [ "${full_name}${variant_suffix}" ] + } + public_deps += invoker.component_deps_blink + } + if (defined(invoker.check_includes_blink)) { + check_includes = invoker.check_includes_blink + } + } else { + if (defined(invoker.check_includes_blink)) { + not_needed(invoker, [ "check_includes_blink" ]) + } + if (defined(invoker.overridden_deps)) { + foreach(d, invoker.overridden_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append variant_suffix + # to get the cpp dependency name. + full_name = get_label_info("$d", "label_no_toolchain") + public_deps -= [ "${full_name}${variant_suffix}" ] + } + public_deps += invoker.component_deps + } + } + foreach(config, cpp_typemap_configs) { + if (defined(config.traits_sources)) { + sources += config.traits_sources + } + if (defined(config.traits_deps)) { + deps += config.traits_deps + } + if (defined(config.traits_public_deps)) { + public_deps += config.traits_public_deps + } + } + if (defined(bindings_configuration.for_blink) && + bindings_configuration.for_blink) { + public_deps += [ "//mojo/public/cpp/bindings:wtf_support" ] + } + } + + if (generate_mojolpm_fuzzing && !defined(variant)) { + # This block contains the C++ targets for the MojoLPM fuzzer, we need to + # do this here so that we can use the typemap configuration for the + # empty-variant Mojo target. + + mojolpm_target_name = "${target_name}_mojolpm" + mojolpm_generator_target_name = "${target_name}__generator" + source_set(mojolpm_target_name) { + # There are still a few missing header dependencies between mojo targets + # with typemaps and the dependencies of their typemap headers. It would + # be good to enable include checking for these in the future though. + check_includes = false + testonly = true + if (defined(invoker.sources)) { + # Split the input into generated and non-generated source files. They + # need to be processed separately. + gen_dir_path_wildcard = get_path_info("//", "gen_dir") + "/*" + non_gen_sources = + filter_exclude(invoker.sources, [ gen_dir_path_wildcard ]) + gen_sources = + filter_include(invoker.sources, [ gen_dir_path_wildcard ]) + sources = process_file_template( + non_gen_sources, + [ + "{{source_gen_dir}}/{{source_file_part}}-mojolpm.cc", + "{{source_gen_dir}}/{{source_file_part}}-mojolpm.h", + ]) + sources += process_file_template( + gen_sources, + [ + "{{source_dir}}/{{source_file_part}}-mojolpm.cc", + "{{source_dir}}/{{source_file_part}}-mojolpm.h", + ]) + deps = [ ":$output_target_name" ] + } else { + sources = [] + deps = [] + } + + public_deps = [ + ":$generator_shared_target_name", + + # NB: hardcoded dependency on the no-variant variant generator, since + # mojolpm only uses the no-variant type. + ":$mojolpm_generator_target_name", + ":$mojolpm_proto_target_name", + "//base", + "//mojo/public/tools/fuzzers:mojolpm", + ] + + foreach(d, all_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append variant_suffix to + # get the cpp dependency name. + full_name = get_label_info("$d", "label_no_toolchain") + public_deps += [ "${full_name}_mojolpm" ] + } + + foreach(config, cpp_typemap_configs) { + if (defined(config.traits_deps)) { + deps += config.traits_deps + } + if (defined(config.traits_public_deps)) { + public_deps += config.traits_public_deps + } + } + } + } + + if (generate_java && is_android) { + import("//build/config/android/rules.gni") + + java_generator_target_name = target_name + "_java__generator" + if (sources_list != []) { + action(java_generator_target_name) { + script = mojom_generator_script + inputs = mojom_generator_sources + jinja2_sources + sources = sources_list + deps = [ + ":$parser_target_name", + ":$type_mappings_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + outputs = [] + args = common_generator_args + filelist = [] + foreach(source, sources_list) { + filelist += [ rebase_path(source, root_build_dir) ] + } + foreach(base_path, output_file_base_paths) { + outputs += [ "$root_gen_dir/$base_path.srcjar" ] + } + + response_file_contents = filelist + + args += [ + "--filelist={{response_file_name}}", + "-g", + "java", + ] + + if (!defined(invoker.scramble_message_ids) || + invoker.scramble_message_ids) { + inputs += message_scrambling_inputs + args += message_scrambling_args + } + } + } else { + group(java_generator_target_name) { + } + } + + java_srcjar_target_name = target_name + "_java_sources" + + action(java_srcjar_target_name) { + script = "//build/android/gyp/zip.py" + inputs = [] + if (output_file_base_paths != []) { + foreach(base_path, output_file_base_paths) { + inputs += [ "$root_gen_dir/${base_path}.srcjar" ] + } + } + output = "$target_gen_dir/$target_name.srcjar" + outputs = [ output ] + rebase_inputs = rebase_path(inputs, root_build_dir) + rebase_output = rebase_path(output, root_build_dir) + args = [ + "--input-zips=$rebase_inputs", + "--output=$rebase_output", + ] + deps = [] + if (sources_list != []) { + deps = [ ":$java_generator_target_name" ] + } + } + + java_target_name = target_name + "_java" + android_library(java_target_name) { + forward_variables_from(invoker, [ "enable_bytecode_checks" ]) + deps = [ + "//mojo/public/java:bindings_java", + "//mojo/public/java:system_java", + "//third_party/androidx:androidx_annotation_annotation_java", + ] + + # Disable warnings/checks on these generated files. + chromium_code = false + + foreach(d, all_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append "_java" to get the java + # dependency name. + full_name = get_label_info(d, "label_no_toolchain") + deps += [ "${full_name}_java" ] + } + + srcjar_deps = [ ":$java_srcjar_target_name" ] + } + } + } + + if (defined(invoker.generate_webui_js_bindings)) { + assert(is_chromeos_ash, + "generate_webui_js_bindings can only be used on ChromeOS Ash") + assert(invoker.generate_webui_js_bindings, + "generate_webui_js_bindings should be set to true or removed") + } + + use_typescript_for_target = defined(invoker.webui_module_path) && + !defined(invoker.generate_webui_js_bindings) + + generate_legacy_js = !use_typescript_for_target || + (defined(invoker.generate_legacy_js_bindings) && + invoker.generate_legacy_js_bindings) + + if (!use_typescript_for_target && + defined(invoker.generate_legacy_js_bindings)) { + not_needed(invoker, [ "generate_legacy_js_bindings" ]) + } + + # Targets needed by both TS and JS bindings targets. These are needed + # unconditionally for JS bindings targets, and are needed for TS bindings + # targets when generate_legacy_js_bindings is true. This option is provided + # since the legacy bindings are needed by Blink tests and non-Chromium users, + # which are not expected to migrate to modules or TypeScript. + if (generate_legacy_js && (generate_js_fuzzing || + !defined(invoker.cpp_only) || !invoker.cpp_only)) { + if (sources_list != []) { + generator_js_target_name = "${target_name}_js__generator" + + action(generator_js_target_name) { + script = mojom_generator_script + inputs = mojom_generator_sources + jinja2_sources + sources = sources_list + deps = [ + ":$parser_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + if (defined(invoker.parser_deps)) { + deps += invoker.parser_deps + } + outputs = [] + args = common_generator_args + filelist = [] + foreach(source, sources_list) { + filelist += [ rebase_path(source, root_build_dir) ] + } + foreach(base_path, output_file_base_paths) { + outputs += [ + "$root_gen_dir/$base_path.js", + "$root_gen_dir/$base_path.m.js", + "$root_gen_dir/$base_path-lite.js", + "$root_gen_dir/$base_path-lite-for-compile.js", + ] + + if (defined(invoker.webui_module_path) && + !use_typescript_for_target) { + outputs += [ "$root_gen_dir/mojom-webui/$base_path-webui.js" ] + } + } + + response_file_contents = filelist + + args += [ + "--filelist={{response_file_name}}", + "-g", + "javascript", + ] + + if (defined(invoker.js_generate_struct_deserializers) && + invoker.js_generate_struct_deserializers) { + args += [ "--js_generate_struct_deserializers" ] + } + + if (!defined(invoker.scramble_message_ids) || + invoker.scramble_message_ids) { + inputs += message_scrambling_inputs + args += message_scrambling_args + } + + if (generate_js_fuzzing) { + args += [ "--generate_fuzzing" ] + } + } + } + + js_target_name = target_name + "_js" + group(js_target_name) { + public_deps = [] + if (sources_list != []) { + public_deps += [ ":$generator_js_target_name" ] + } + + foreach(d, all_deps) { + full_name = get_label_info(d, "label_no_toolchain") + public_deps += [ "${full_name}_js" ] + } + } + + group(js_data_deps_target_name) { + deps = [] + if (sources_list != []) { + data = [] + foreach(base_path, output_file_base_paths) { + data += [ + "$root_gen_dir/${base_path}.js", + "$root_gen_dir/${base_path}.m.js", + "$root_gen_dir/${base_path}-lite.js", + ] + } + deps += [ ":$generator_js_target_name" ] + } + + if (defined(invoker.disallow_native_types) && + invoker.disallow_native_types) { + data_deps = [] + } else { + data_deps = [ "//mojo/public/js:bindings_module" ] + } + foreach(d, all_deps) { + full_name = get_label_info(d, "label_no_toolchain") + data_deps += [ "${full_name}_js_data_deps" ] + } + } + } + + # js_library() closure compiler targets, primarily used on ChromeOS. Only + # generate these targets if the mojom target is not C++ only and is not using + # TypeScript. + if (generate_mojom_closure_libraries && + (!defined(invoker.cpp_only) || !invoker.cpp_only) && generate_legacy_js) { + js_library_for_compile_target_name = "${target_name}_js_library_for_compile" + if (sources_list != []) { + js_library(js_library_for_compile_target_name) { + extra_public_deps = [ ":$generator_js_target_name" ] + sources = [] + foreach(base_path, output_file_base_paths) { + sources += [ "$root_gen_dir/${base_path}-lite-for-compile.js" ] + } + externs_list = [ + "${externs_path}/mojo_core.js", + "${externs_path}/pending.js", + ] + deps = [] + if (!defined(invoker.disallow_native_types)) { + deps += [ "//mojo/public/js:bindings_lite_sources" ] + } + foreach(d, all_deps) { + full_name = get_label_info(d, "label_no_toolchain") + deps += [ "${full_name}_js_library_for_compile" ] + } + } + } else { + group(js_library_for_compile_target_name) { + } + } + + # WebUI specific closure targets, not needed by targets that are generating + # TypeScript WebUI bindings or by legacy-only targets. + if (defined(invoker.webui_module_path) && !use_typescript_for_target) { + webui_js_target_name = "${target_name}_webui_js" + if (sources_list != []) { + js_library(webui_js_target_name) { + extra_public_deps = [ ":$generator_js_target_name" ] + sources = [] + foreach(base_path, output_file_base_paths) { + sources += [ "$root_gen_dir/mojom-webui/${base_path}-webui.js" ] + } + externs_list = [ + "${externs_path}/mojo_core.js", + "${externs_path}/pending.js", + ] + if (defined(invoker.disallow_native_types) && + invoker.disallow_native_types) { + deps = [] + } else { + deps = [ "//mojo/public/js:bindings_uncompiled" ] + } + foreach(d, all_deps) { + full_name = get_label_info(d, "label_no_toolchain") + deps += [ "${full_name}_webui_js" ] + } + } + } else { + group(webui_js_target_name) { + } + } + + webui_grdp_target_name = "${target_name}_webui_grdp" + out_grd = "$target_gen_dir/${target_name}_webui_resources.grdp" + grd_prefix = "${target_name}_webui" + generate_grd(webui_grdp_target_name) { + grd_prefix = grd_prefix + out_grd = out_grd + + deps = [ ":$webui_js_target_name" ] + + input_files = [] + foreach(base_path, output_file_base_paths) { + input_files += [ "${base_path}-webui.js" ] + } + + input_files_base_dir = + rebase_path("$root_gen_dir/mojom-webui", "$root_build_dir") + } + } + } + if ((generate_js_fuzzing || !defined(invoker.cpp_only) || + !invoker.cpp_only) && use_typescript_for_target) { + if (sources_list != []) { + source_filelist = [] + foreach(source, sources_list) { + source_filelist += [ rebase_path(source, root_build_dir) ] + } + + # Generate Typescript bindings. + generator_ts_target_name = "${target_name}_ts__generator" + + action(generator_ts_target_name) { + script = mojom_generator_script + inputs = mojom_generator_sources + jinja2_sources + sources = sources_list + deps = [ + ":$parser_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + + outputs = [] + foreach(base_path, output_file_base_paths) { + outputs += [ "$root_gen_dir/$base_path-webui.ts" ] + } + args = common_generator_args + response_file_contents = source_filelist + + args += [ + "--filelist={{response_file_name}}", + "-g", + "typescript", + ] + + if (!defined(invoker.scramble_message_ids) || + invoker.scramble_message_ids) { + inputs += message_scrambling_inputs + args += message_scrambling_args + } + + if (defined(invoker.js_generate_struct_deserializers) && + invoker.js_generate_struct_deserializers) { + args += [ "--js_generate_struct_deserializers" ] + } + + # TODO(crbug.com/1007587): Support scramble_message_ids if above is + # insufficient. + # TODO(crbug.com/1007591): Support generate_fuzzing. + } + } + } +} + +# A helper for the mojom() template above when component libraries are desired +# for generated C++ bindings units. Supports all the same arguments as mojom() +# except for the optional |component_output_prefix| and |component_macro_prefix| +# arguments. These are instead shortened to |output_prefix| and |macro_prefix| +# and are *required*. +template("mojom_component") { + assert(defined(invoker.output_prefix) && defined(invoker.macro_prefix)) + + mojom(target_name) { + forward_variables_from(invoker, + "*", + [ + "output_prefix", + "macro_prefix", + ]) + component_output_prefix = invoker.output_prefix + component_macro_prefix = invoker.macro_prefix + } +} |