| # 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. |
| |
| # TODO(vardhan): Currently, the compiler generates type info and calls the |
| # generators. Sever this, and have generators consume compiled output from an |
| # intermediate file. |
| |
| import("//build/config/fuchsia/sdk.gni") |
| import("//packages/gn/packages.gni") |
| |
| declare_args() { |
| # Generate Dart code from fidl bindings. |
| generate_fidl_for_dart = packages_have_dart |
| |
| # Generate Go code from fidl bindings. |
| generate_fidl_for_go = packages_have_go |
| |
| # Generate Rust code from fidl bindings. |
| generate_fidl_for_rust = packages_have_rust |
| } |
| |
| if (generate_fidl_for_dart) { |
| import("//build/dart/dart_package.gni") |
| } |
| if (generate_fidl_for_rust) { |
| import("//build/rust/rust_library.gni") |
| } |
| |
| # Generate C++/JavaScript/Java/Python/Dart/Go source files from fidl files. The |
| # output files will go under the generated file directory tree with the same |
| # path as each input file. |
| # |
| # Parameters: |
| # |
| # sources (optional if one of the deps sets listed below is present) |
| # List of source .fidl files to compile. |
| # |
| # deps (optional) |
| # Note: this can contain only other fidl targets. |
| # |
| # public_deps (optional) |
| # Note: this can contain only other fidl targets. |
| # |
| # import_dirs (optional) |
| # List of import directories that will get added when processing sources. |
| # |
| # testonly (optional) |
| # |
| # visibility (optional) |
| template("fidl") { |
| assert( |
| defined(invoker.sources) || defined(invoker.deps) || |
| defined(invoker.public_deps), |
| "\"sources\" or \"deps\" must be defined for the $target_name template.") |
| |
| cpp_sources_suffix = "cpp_sources" |
| cpp_sources_target_name = "${target_name}_${cpp_sources_suffix}" |
| |
| if (defined(invoker.sources)) { |
| legacy_gen_path = rebase_path( |
| "${root_build_dir}/host_x64/legacy_generators/run_code_generators.py") |
| fidl_tool = rebase_path("${root_build_dir}/host_x64/fidl") |
| |
| generator_cpp_outputs = [ |
| "{{source_gen_dir}}/{{source_file_part}}-common.cc", |
| "{{source_gen_dir}}/{{source_file_part}}-common.h", |
| "{{source_gen_dir}}/{{source_file_part}}-internal.h", |
| "{{source_gen_dir}}/{{source_file_part}}-sync.cc", |
| "{{source_gen_dir}}/{{source_file_part}}-sync.h", |
| "{{source_gen_dir}}/{{source_file_part}}.h", |
| "{{source_gen_dir}}/{{source_file_part}}.cc", |
| ] |
| if (generate_fidl_for_dart) { |
| generator_dart_outputs = |
| [ "{{source_gen_dir}}/{{source_file_part}}.dart" ] |
| } |
| if (generate_fidl_for_go) { |
| go_gen_path = rebase_path("${root_build_dir}/host_x64/fidl-go") |
| generator_go_outputs = [ "${root_gen_dir}/go/src/{{source_dir}}/{{source_name_part}}/{{source_name_part}}.core.go" ] |
| } |
| |
| # TODO(vardhan): We can't have both .mojom and .fidl coexist because of |
| # this hardcoded '_fidl' suffix. Has to do with python imports not handling |
| # '.fidl/.mojom' in names. Investigate putting in a package instead. |
| generator_python_outputs = |
| [ "{{source_gen_dir}}/{{source_name_part}}_fidl.py" ] |
| if (generate_fidl_for_rust) { |
| rust_gen_path = rebase_path("${root_build_dir}/host_x64/fidl-rust") |
| generator_rust_outputs = |
| # "{{source_gen_dir}}/${target_name}/src/{{source_name_part}}.rs" would be |
| # a cleaner directory structure for the generated crate, but would require |
| # changes to the generator |
| [ "{{source_gen_dir}}/{{source_name_part}}.rs" ] |
| } |
| } |
| generator_python_zip_output = "$target_out_dir/${target_name}_python.pyzip" |
| if (generate_fidl_for_rust) { |
| generator_rust_crate_output = "$target_gen_dir/${target_name}" |
| map_target = "${target_name}_map" |
| } |
| |
| if (defined(invoker.sources)) { |
| generator_target_name = target_name + "__generator" |
| action_foreach(generator_target_name) { |
| script = "/usr/bin/env" |
| public_deps = [ |
| "//garnet/public/lib/fidl/compiler:fidl(//build/toolchain:host_x64)", |
| ] |
| deps = [ |
| "//garnet/public/lib/fidl/compiler/legacy_generators(//build/toolchain:host_x64)", |
| ] |
| if (generate_fidl_for_rust) { |
| deps += [ |
| ":$map_target", |
| "//garnet/public/lib/fidl/compiler:fidl-rust(//build/toolchain:host_x64)", |
| ] |
| } |
| if (generate_fidl_for_go) { |
| deps += [ "//garnet/public/lib/fidl/compiler:fidl-go(//build/toolchain:host_x64)" ] |
| } |
| if (defined(invoker.generate_type_info) && invoker.generate_type_info) { |
| deps += [ "//garnet/public/lib/fidl/compiler/interfaces:interfaces" ] |
| } |
| sources = invoker.sources |
| |
| # In case one of our |sources| depends/imports another one of our |sources|: |
| inputs = invoker.sources |
| outputs = generator_cpp_outputs + generator_python_outputs |
| |
| if (generate_fidl_for_dart) { |
| outputs += generator_dart_outputs |
| } |
| if (generate_fidl_for_rust) { |
| outputs += generator_rust_outputs |
| } |
| if (generate_fidl_for_go) { |
| outputs += generator_go_outputs |
| } |
| generators = legacy_gen_path |
| if (generate_fidl_for_go) { |
| generators += "," + go_gen_path |
| } |
| if (generate_fidl_for_rust) { |
| generators += "," + rust_gen_path |
| } |
| args = [ |
| fidl_tool, |
| "gen", |
| "--src-root-path", |
| rebase_path("//", root_build_dir), |
| "-I", |
| rebase_path("//", root_build_dir), |
| "--output-dir", |
| rebase_path(root_gen_dir), |
| "--no-gen-imports", |
| "--generators", |
| generators, |
| ] |
| |
| if (generate_fidl_for_rust) { |
| # Plumb map to generator (for Rust) |
| args += [ |
| "--gen-arg", |
| "map-file=" + rebase_path("${generator_rust_crate_output}_map.txt", |
| root_build_dir), |
| ] |
| } |
| |
| if (defined(invoker.generate_type_info) && invoker.generate_type_info) { |
| args += [ |
| "--gen-arg", |
| "generate-type-info", |
| ] |
| } |
| |
| if (generate_fidl_for_dart) { |
| if (defined(ignore_dart_package_annotations) && |
| ignore_dart_package_annotations) { |
| args += [ |
| "--gen-arg", |
| "dart_ignore-package-annotations", |
| ] |
| } |
| } |
| |
| foreach(import_dir, sdk_dirs) { |
| args += [ |
| "-I", |
| rebase_path(import_dir, root_build_dir), |
| ] |
| } |
| |
| if (defined(invoker.import_dirs)) { |
| foreach(import_dir, invoker.import_dirs) { |
| args += [ |
| "-I", |
| rebase_path(import_dir, root_build_dir), |
| ] |
| } |
| } |
| |
| args += [ "{{source}}" ] |
| } |
| } |
| |
| # Some re-usable variables for the C++ source sets: |
| cpp_public_deps = [] |
| if (defined(invoker.public_deps)) { |
| cpp_public_deps += invoker.public_deps |
| } |
| if (defined(invoker.sources)) { |
| cpp_public_deps += [ ":$generator_target_name" ] |
| } |
| cpp_deps = [] |
| if (defined(invoker.deps)) { |
| cpp_deps += invoker.deps |
| } |
| |
| source_set(target_name) { |
| if (defined(invoker.visibility)) { |
| visibility = invoker.visibility |
| } |
| |
| if (defined(invoker.testonly)) { |
| testonly = invoker.testonly |
| } |
| |
| public_configs = [ "//garnet/public:config" ] |
| |
| public_deps = [ |
| "//garnet/public/lib/fidl/cpp/bindings", |
| ] |
| |
| public_deps += cpp_public_deps |
| |
| if (defined(invoker.sources)) { |
| public_deps += [ ":${cpp_sources_target_name}" ] |
| } |
| |
| deps = cpp_deps |
| } |
| |
| # This target provides C++ support for serialization without requiring any |
| # support from the OS. (The other C++ bindings assume message pipes, etc.) |
| source_set("${target_name}_data_only") { |
| if (defined(invoker.visibility)) { |
| visibility = invoker.visibility |
| } |
| |
| if (defined(invoker.testonly)) { |
| testonly = invoker.testonly |
| } |
| |
| public_configs = [ "//garnet/public:config" ] |
| |
| public_deps = [ |
| "//garnet/public/lib/fidl/cpp/bindings:serialization", |
| ] |
| |
| public_deps += cpp_public_deps |
| if (defined(invoker.sources)) { |
| public_deps += [ ":${cpp_sources_target_name}" ] |
| } |
| deps = cpp_deps |
| } |
| |
| all_deps = [] |
| if (defined(invoker.deps)) { |
| all_deps += invoker.deps |
| } |
| if (defined(invoker.public_deps)) { |
| all_deps += invoker.public_deps |
| } |
| |
| group("${target_name}__is_fidl") { |
| } |
| |
| # Explicitly ensure that all dependencies (invoker.deps and |
| # invoker.public_deps) are fidl targets themselves. |
| group("${target_name}__check_deps_are_all_fidl") { |
| deps = [] |
| foreach(d, all_deps) { |
| name = get_label_info(d, "label_no_toolchain") |
| toolchain = get_label_info(d, "toolchain") |
| deps += [ "${name}__is_fidl(${toolchain})" ] |
| } |
| } |
| |
| action("${target_name}_python") { |
| script = "//garnet/public/lib/fidl/build/zip.py" |
| |
| deps = [] |
| zip_inputs = [] |
| |
| if (defined(invoker.sources)) { |
| inputs = process_file_template(invoker.sources, generator_python_outputs) |
| deps += [ ":$generator_target_name" ] |
| } |
| |
| foreach(d, all_deps) { |
| # Resolve the name, so that a target //mojo/something becomes |
| # //mojo/something:something and we can append "_python" to get the python |
| # dependency name. |
| full_name = get_label_info(d, "label_no_toolchain") |
| dep_name = get_label_info(d, "name") |
| dep_target_out_dir = get_label_info(d, "target_out_dir") |
| deps += [ "${full_name}_python" ] |
| zip_inputs += [ "$dep_target_out_dir/${dep_name}_python.pyzip" ] |
| } |
| |
| output = generator_python_zip_output |
| outputs = [ |
| output, |
| ] |
| |
| rebase_base_dir = rebase_path(target_gen_dir, root_build_dir) |
| if (defined(invoker.sources)) { |
| rebase_inputs = rebase_path(inputs, root_build_dir) |
| } |
| rebase_zip_inputs = rebase_path(zip_inputs, root_build_dir) |
| rebase_output = rebase_path(output, root_build_dir) |
| args = [ |
| "--base-dir=$rebase_base_dir", |
| "--zip-inputs=$rebase_zip_inputs", |
| "--output=$rebase_output", |
| ] |
| if (defined(invoker.sources)) { |
| args += [ "--inputs=$rebase_inputs" ] |
| } |
| } |
| |
| if (generate_fidl_for_rust) { |
| rust_crate_target_name = "${target_name}_rust" |
| |
| action(rust_crate_target_name) { |
| script = "//garnet/public/lib/fidl/build/make_crate.py" |
| |
| deps = [] |
| dep_inputs = [] |
| |
| if (defined(invoker.sources)) { |
| inputs = process_file_template(invoker.sources, generator_rust_outputs) |
| deps += [ ":$generator_target_name" ] |
| } |
| |
| foreach(d, all_deps) { |
| # Resolve the name, so that a target //fidl/something becomes |
| # //fidl/something:something and we can append "_rust" to get the rust |
| # dependency name. |
| full_name = get_label_info(d, "label_no_toolchain") |
| dep_name = get_label_info(d, "name") |
| dep_target_gen_dir = get_label_info(d, "target_gen_dir") |
| deps += [ "${full_name}_rust" ] |
| dep_inputs += [ "$dep_target_gen_dir/${dep_name}" ] |
| } |
| |
| output_base = generator_rust_crate_output |
| outputs = [ |
| "$output_base/Cargo.toml", |
| "$output_base/src/lib.rs", |
| ] |
| |
| rebase_gen_dir = rebase_path(root_gen_dir) |
| if (defined(invoker.sources)) { |
| rebase_inputs = rebase_path(inputs, root_build_dir) |
| } |
| rebase_dep_inputs = rebase_path(dep_inputs, root_gen_dir) |
| rebase_output = rebase_path(output_base, root_gen_dir) |
| rebase_srcroot = rebase_path("//", root_build_dir) |
| args = [ |
| "--gen-dir=$rebase_gen_dir", |
| "--dep-inputs=$rebase_dep_inputs", |
| "--output=$rebase_output", |
| "--srcroot=$rebase_srcroot", |
| ] |
| if (defined(invoker.sources)) { |
| args += [ "--inputs=$rebase_inputs" ] |
| } |
| } |
| |
| rust_library("${target_name}_rust_library") { |
| name = exec_script("//garnet/public/lib/fidl/build/label_to_crate.py", |
| [ rebase_path(generator_rust_crate_output, |
| root_gen_dir) ], |
| "trim string") |
| |
| source_dir = generator_rust_crate_output |
| |
| deps = [] |
| foreach(d, all_deps) { |
| # Resolve the name, so that a target //fidl/something becomes |
| # //fidl/something:something and we can append "_rust_library" to get the |
| # rust dependency name. |
| full_name = get_label_info(d, "label_no_toolchain") |
| deps += [ "${full_name}_rust_library" ] |
| } |
| |
| deps += [ |
| "//garnet/public/lib/fidl/rust/fidl", |
| "//garnet/public/rust/crates/tokio-fuchsia", |
| "//garnet/public/rust/crates/fuchsia-zircon", |
| "//third_party/rust-crates:futures-0.1.16", |
| ] |
| |
| non_rust_deps = [ ":${rust_crate_target_name}" ] |
| } |
| |
| # Creates a map from fidl file to GN build target which supplies it. Used primarily |
| # for resolving dependencies in the Rust binding generation. |
| save_target = target_name |
| action(map_target) { |
| script = "//garnet/public/lib/fidl/build/make_map.py" |
| |
| deps = [] |
| |
| foreach(d, all_deps) { |
| # Resolve the name, so that a target //fidl/something becomes |
| # //fidl/something:something and we can append "_map" to get the map |
| # dependency name. |
| full_name = get_label_info(d, "label_no_toolchain") |
| deps += [ "${full_name}_map" ] |
| } |
| |
| if (defined(invoker.deps)) { |
| map_deps = [] |
| foreach(d, invoker.deps) { |
| dep_name = get_label_info(d, "name") |
| dep_target_gen_dir = get_label_info(d, "target_gen_dir") |
| map_deps += [ "$dep_target_gen_dir/${dep_name}_map.txt" ] |
| } |
| rebase_map_deps = rebase_path(map_deps, root_build_dir) |
| } |
| |
| if (defined(invoker.public_deps)) { |
| map_public_deps = [] |
| foreach(d, invoker.public_deps) { |
| dep_name = get_label_info(d, "name") |
| dep_target_gen_dir = get_label_info(d, "target_gen_dir") |
| map_public_deps += [ "$dep_target_gen_dir/${dep_name}_map.txt" ] |
| } |
| rebase_map_public_deps = rebase_path(map_public_deps, root_build_dir) |
| } |
| |
| output_fn = "${generator_rust_crate_output}_map.txt" |
| outputs = [ |
| output_fn, |
| ] |
| |
| if (defined(invoker.sources)) { |
| arg_sources = invoker.sources |
| } |
| rebase_output = rebase_path(output_fn, root_build_dir) |
| target_dir = get_label_info("${save_target}", "label_no_toolchain") |
| args = [ |
| "--target=$target_dir", |
| "--output=$rebase_output", |
| ] |
| if (defined(invoker.sources)) { |
| args += [ "--sources=$arg_sources" ] |
| } |
| if (defined(invoker.deps)) { |
| args += [ "--map-deps=$rebase_map_deps" ] |
| } |
| if (defined(invoker.public_deps)) { |
| args += [ "--map-public-deps=$rebase_map_public_deps" ] |
| } |
| } |
| } |
| |
| if (defined(invoker.sources)) { |
| # The generated C++ source files. The main reason to introduce this target |
| # is so that lib/fidl/cpp/bindings can depend on fidl interfaces without |
| # circular dependencies. It means that the target is missing the dependency |
| # on lib/fidl/cpp/bindings. No external targets should depend directly on |
| # this target *except* lib/fidl/cpp/bindings and other *_cpp_sources |
| # targets. |
| source_set(cpp_sources_target_name + "__common") { |
| if (defined(invoker.testonly)) { |
| testonly = invoker.testonly |
| } |
| sources = process_file_template( |
| invoker.sources, |
| [ |
| "{{source_gen_dir}}/{{source_file_part}}-common.cc", |
| "{{source_gen_dir}}/{{source_file_part}}-common.h", |
| "{{source_gen_dir}}/{{source_file_part}}-internal.h", |
| ]) |
| public_configs = [ "//garnet/public:config" ] |
| deps = [ |
| ":$generator_target_name", |
| "//garnet/public/lib/fidl/compiler/interfaces:interfaces__generator", |
| "//garnet/public/lib/fidl/cpp/bindings", |
| ] |
| foreach(d, all_deps) { |
| # Resolve the name, so that a target //mojo/something becomes |
| # //mojo/something:something and we can append cpp_sources_suffix to |
| # get the cpp dependency name. |
| full_name = get_label_info(d, "label_no_toolchain") |
| deps += [ "${full_name}_${cpp_sources_suffix}" ] |
| } |
| } |
| |
| source_set(cpp_sources_target_name) { |
| if (defined(invoker.testonly)) { |
| testonly = invoker.testonly |
| } |
| sources = process_file_template( |
| invoker.sources, |
| [ |
| "{{source_gen_dir}}/{{source_file_part}}.h", |
| "{{source_gen_dir}}/{{source_file_part}}.cc", |
| "{{source_gen_dir}}/{{source_file_part}}-sync.cc", |
| "{{source_gen_dir}}/{{source_file_part}}-sync.h", |
| ]) |
| public_configs = |
| [ "//garnet/public/lib/fidl/cpp/bindings:bindings_config" ] |
| deps = [ |
| ":$generator_target_name", |
| ":${cpp_sources_target_name}__common", |
| "//garnet/public/lib/fidl/compiler/interfaces:interfaces__generator", |
| "//garnet/public/lib/fidl/cpp/bindings", |
| ] |
| foreach(d, all_deps) { |
| # Resolve the name, so that a target //mojo/something becomes |
| # //mojo/something:something and we can append cpp_sources_suffix to |
| # get the cpp dependency name. |
| full_name = get_label_info(d, "label_no_toolchain") |
| deps += [ "${full_name}_${cpp_sources_suffix}" ] |
| } |
| } |
| } |
| |
| if (generate_fidl_for_dart) { |
| # Compute the Dart package name in advance to ensure it does not contain the |
| # "_dart" suffix. |
| # See //build/dart/dart_package.gni for more details. |
| target_label = get_label_info(":$target_name", "label_no_toolchain") |
| |
| # This target is used to generate Dart package information |
| dart_package("${target_name}_dart") { |
| generator_label = ":$generator_target_name($target_toolchain)" |
| |
| package_label = target_label |
| source_dir = get_label_info(generator_label, "target_gen_dir") |
| |
| # Disable analysis. FIDL targets in a same build file will share a gen (and |
| # therefore source) directory which confuses the analyzer trying to process |
| # every single file in the directory but not having the right packages set |
| # up. |
| disable_analysis = true |
| |
| generated_code = true |
| |
| deps = [ |
| "//topaz/public/lib/fidl/dart", |
| ] |
| fidl_deps = [] |
| if (defined(invoker.deps)) { |
| fidl_deps += invoker.deps |
| } |
| if (defined(invoker.public_deps)) { |
| fidl_deps += invoker.public_deps |
| } |
| |
| # Depend on the generated Dart package for all of our fidl dependencies. |
| foreach(d, fidl_deps) { |
| dep_label = get_label_info(d, "label_no_toolchain") |
| deps += [ "${dep_label}_dart" ] |
| } |
| |
| non_dart_deps = [] |
| if (defined(invoker.sources)) { |
| non_dart_deps += [ generator_label ] |
| } |
| } |
| } |
| } |