# Copyright 2014 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import("//build/config/python.gni") 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/webui_features.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/chromecast_build.gni") import("//build/config/chromeos/ui_mode.gni") import("//build/config/nacl/config.gni") import("//build/toolchain/kythe.gni") import("//components/nacl/features.gni") import("//third_party/jinja2/jinja2.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. Set to |false| to disable message ID # scrambling on all platforms. enable_mojom_message_id_scrambling = true # 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. enable_mojom_closure_compile = enable_js_type_check && optimize_webui # Enables generating Typescript bindings and compiling them to JS bindings. enable_typescript_bindings = false # Enables generating javascript fuzzing-related code and the bindings for the # MojoLPM fuzzer targets. Off by default. enable_mojom_fuzzer = 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_chromeos_ash && !is_chromecast && !is_chromeos_lacros) || ((enable_nacl || is_nacl || is_nacl_nonsfi) && (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/generate/__init__.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/lexer.py", "$_mojom_library_root/parse/parser.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/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_mojolpm_generator.py", "$mojom_generator_root/generators/mojom_js_generator.py", "$mojom_generator_root/generators/mojom_ts_generator.py", "$mojom_generator_script", ] 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_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|. If # 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. # # 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. # # use_typescript_sources (optional) # Uses the Typescript generator to generate JavaScript bindings. # # 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 an absolute path, a WebUI page may only import these modules if # they are manually packaged and mapped independently by that page's # WebUIDataSource. The mapped path must match the path given here. # # If this is is instead a URL string starting with # "chrome://resources/mojo", the generated resources must be added to # content_resources.grd and registered with # content::SharedResourcesDataSource with a corresponding path, at which # point they will be made available to all WebUI pages at the given URL. # # 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>". # # 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. # # 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. # # 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. # # 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). # # 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. # # 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) 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") ] } write_file(build_metadata_filename, build_metadata, "json") generate_fuzzing = (!defined(invoker.enable_fuzzing) || invoker.enable_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_fuchsia) { enabled_features += [ "is_fuchsia" ] } else if (is_ios) { enabled_features += [ "is_ios" ] } else if (is_linux || is_chromeos_lacros) { enabled_features += [ "is_linux" ] if (is_chromeos_lacros) { enabled_features += [ "is_chromeos", "is_chromeos_lacros", ] } } else if (is_mac) { enabled_features += [ "is_mac" ] } else if (is_win) { enabled_features += [ "is_win" ] } # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_action(parser_target_name) { script = mojom_parser_script inputs = mojom_parser_sources + [ build_metadata_filename ] sources = sources_list 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) ] } response_file_contents = filelist args = [ # Resolve relative input mojom paths against both the root src dir and # the root gen dir. "--input-root", rebase_path("//."), "--input-root", rebase_path(root_gen_dir), "--output-root", rebase_path(root_gen_dir), "--mojom-file-list={{response_file_name}}", "--check-imports", rebase_path(build_metadata_filename), ] if (defined(invoker.input_root_override)) { args += [ "--input-root", rebase_path(invoker.input_root_override), ] } 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}", ] } } } 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" } } # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_action(generator_cpp_message_ids_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-shared-message-ids.h" ] } response_file_contents = filelist args += [ "--filelist={{response_file_name}}", "--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" # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_action(generator_shared_target_name) { visibility = [ ":*" ] 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-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", ] } response_file_contents = filelist args += [ "--filelist={{response_file_name}}", "--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 } deps = [] public_deps = [] if (output_file_base_paths != []) { sources = [] foreach(base_path, output_file_base_paths) { sources += [ "$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_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" # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_action(generator_mojolpm_proto_target_name) { script = mojom_generator_script inputs = mojom_generator_sources + jinja2_sources sources = invoker.sources deps = [ ":$parser_target_name", "//mojo/public/tools/bindings:precompile_templates", ] outputs = [] args = common_generator_args filelist = [] foreach(source, invoker.sources) { filelist += [ rebase_path("$source", root_build_dir) ] outputs += [ "$target_gen_dir/$source.mojolpm.proto" ] } response_file_contents = filelist args += [ "--filelist={{response_file_name}}", "--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 sources = process_file_template( invoker.sources, [ "{{source_gen_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) && !is_ios) { 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" ] } 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", ] } 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 != []) { 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.cc", "${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. python2_action(generator_target_name) { visibility = [ ":*" ] 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", ] 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) { 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.cc", "$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_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", ] } } response_file_contents = filelist args += [ "--filelist={{response_file_name}}", "-g", ] if (generate_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), ] 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}" ] } } } } } if (generate_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)) { sources = process_file_template( invoker.sources, [ "{{source_gen_dir}}/{{source_file_part}}-mojolpm.cc", "{{source_gen_dir}}/{{source_file_part}}-mojolpm.h", ]) deps = [] } 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 } } } } # 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 # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_action(_typemap_validator_target_name) { 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), rebase_path(_typemap_stamp_filename), ] } # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_action(type_mappings_target_name) { 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), ] 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 = rebase_path("$dependency_output_dir/${dependency_name}", root_build_dir) args += [ "--dependency", dependency_path, ] } # 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" ] if (defined(invoker.testonly)) { testonly = invoker.testonly } defines = export_defines 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_java && is_android) { import("//build/config/android/rules.gni") java_generator_target_name = target_name + "_java__generator" if (sources_list != []) { # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_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" # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_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 = [ "//base:base_java", "//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" ] } } } use_typescript_for_target = enable_typescript_bindings && defined(invoker.use_typescript_sources) && invoker.use_typescript_sources if (!use_typescript_for_target && defined(invoker.use_typescript_sources)) { not_needed(invoker, [ "use_typescript_sources" ]) } if ((generate_fuzzing || !defined(invoker.cpp_only) || !invoker.cpp_only) && !use_typescript_for_target) { if (sources_list != []) { generator_js_target_name = "${target_name}_js__generator" # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_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.externs.js", "$root_gen_dir/$base_path.m.js", "$root_gen_dir/$base_path-lite.js", "$root_gen_dir/$base_path.html", "$root_gen_dir/$base_path-lite-for-compile.js", ] if (defined(invoker.webui_module_path)) { outputs += [ "$root_gen_dir/mojom-webui/$base_path-webui.js" ] } } response_file_contents = filelist args += [ "--filelist={{response_file_name}}", "-g", "javascript", "--js_bindings_mode=new", ] 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_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_target_name = "${target_name}_js_library" if (sources_list != []) { js_library(js_library_target_name) { extra_public_deps = [ ":$generator_js_target_name" ] sources = [] foreach(base_path, output_file_base_paths) { sources += [ "$root_gen_dir/${base_path}-lite.js" ] } externs_list = [ "${externs_path}/mojo_core.js", "${externs_path}/pending.js", ] deps = [] foreach(d, all_deps) { full_name = get_label_info(d, "label_no_toolchain") deps += [ "${full_name}_js_library" ] } } } else { group(js_library_target_name) { } } 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) { } } js_modules_target_name = "${target_name}_js_modules" if (sources_list != []) { js_library(js_modules_target_name) { extra_public_deps = [ ":$generator_js_target_name" ] sources = [] foreach(base_path, output_file_base_paths) { sources += [ "$root_gen_dir/${base_path}.m.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}_js_modules" ] } } } else { group(js_modules_target_name) { } } if (defined(invoker.webui_module_path)) { 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) { } } } } if ((generate_fuzzing || !defined(invoker.cpp_only) || !invoker.cpp_only) && use_typescript_for_target) { generator_js_target_names = [] source_filelist = [] foreach(source, sources_list) { source_filelist += [ rebase_path("$source", root_build_dir) ] } dependency_types = [ { name = "regular" ts_extension = ".ts" js_extension = ".js" }, { name = "es_modules" ts_extension = ".m.ts" js_extension = ".m.js" }, ] foreach(dependency_type, dependency_types) { ts_outputs = [] js_outputs = [] foreach(base_path, output_file_base_paths) { ts_outputs += [ "$root_gen_dir/$base_path-lite${dependency_type.ts_extension}" ] js_outputs += [ "$root_gen_dir/$base_path-lite${dependency_type.js_extension}" ] } # Generate Typescript bindings. generator_ts_target_name = "${target_name}_${dependency_type.name}__ts__generator" # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_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 = ts_outputs args = common_generator_args response_file_contents = source_filelist args += [ "--filelist={{response_file_name}}", "-g", "typescript", ] if (dependency_type.name == "es_modules") { args += [ "--ts_use_es_modules" ] } # TODO(crbug.com/1007587): Support scramble_message_ids. # TODO(crbug.com/1007591): Support generate_fuzzing. } # Create tsconfig.json for the generated Typescript. tsconfig_filename = "$target_gen_dir/$target_name-${dependency_type.name}-tsconfig.json" tsconfig = { } tsconfig.compilerOptions = { composite = true target = "es6" module = "es6" lib = [ "es6", "esnext.bigint", ] strict = true } tsconfig.files = [] foreach(base_path, output_file_base_paths) { tsconfig.files += [ rebase_path( "$root_gen_dir/$base_path-lite${dependency_type.ts_extension}", target_gen_dir, root_gen_dir) ] } tsconfig.references = [] # Get tsconfigs for deps. foreach(d, all_deps) { dep_target_gen_dir = rebase_path(get_label_info(d, "target_gen_dir")) dep_name = get_label_info(d, "name") reference = { } reference.path = "$dep_target_gen_dir/$dep_name-${dependency_type.name}-tsconfig.json" tsconfig.references += [ reference ] } write_file(tsconfig_filename, tsconfig, "json") # Compile previously generated Typescript to Javascript. generator_js_target_name = "${target_name}_${dependency_type.name}__js__generator" generator_js_target_names += [ generator_js_target_name ] # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. python2_action(generator_js_target_name) { script = "$mojom_generator_root/compile_typescript.py" sources = ts_outputs outputs = js_outputs public_deps = [ ":$generator_ts_target_name" ] foreach(d, all_deps) { full_name = get_label_info(d, "label_no_toolchain") public_deps += [ "${full_name}_${dependency_type.name}__js__generator" ] } absolute_tsconfig_path = rebase_path(tsconfig_filename, "", target_gen_dir) args = [ "--tsconfig_path=$absolute_tsconfig_path" ] } } js_target_name = target_name + "_js" group(js_target_name) { public_deps = [] if (sources_list != []) { foreach(generator_js_target_name, generator_js_target_names) { 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) { data = js_outputs deps = [] foreach(generator_js_target_name, generator_js_target_names) { deps += [ ":$generator_js_target_name" ] } data_deps = [] foreach(d, all_deps) { full_name = get_label_info(d, "label_no_toolchain") data_deps += [ "${full_name}_js_data_deps" ] } } } } # 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 } }