| # Copyright 2019 The Fuchsia 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("gn_configs.gni") |
| import("gn_sdk_configs.gni") |
| |
| # Defines a base fidl library with no bindings. |
| # |
| # FIDL library dependencies under `public_deps` will manifest as corresponding |
| # library target dependencies. |
| # |
| # Parameters |
| # |
| # library_name (required) |
| # Name of the FIDL library. |
| # |
| # sources (required) |
| # List of fidl files to include in the library. |
| # |
| # json_representation (required) |
| # filename to use for the json representation of the library |
| # |
| template("fidl_base_library") { |
| forward_variables_from(invoker, |
| [ |
| "library_name", |
| "sources", |
| "json_representation", |
| ]) |
| _response_file = "${target_gen_dir}/${target_name}.rsp" |
| |
| action("${target_name}_response_file") { |
| script = gn_sdk_root + "/gen_fidl_response_file.py" |
| |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "public_deps", |
| "testonly", |
| ]) |
| |
| _libraries_file = "$target_gen_dir/${invoker.target_name}.fidl_libraries" |
| |
| outputs = [ |
| _response_file, |
| _libraries_file, |
| ] |
| |
| args = [ |
| "--out-response-file", |
| rebase_path(_response_file, root_build_dir), |
| "--out-libraries", |
| rebase_path(_libraries_file, root_build_dir), |
| "--json", |
| rebase_path(json_representation, root_build_dir), |
| "--name", |
| library_name, |
| "--sources", |
| ] + rebase_path(sources, root_build_dir) |
| |
| # Pass the target API level if it has been specified. |
| assert(fuchsia_target_api_level >= 1) |
| args += [ |
| "--target-api-level", |
| "${fuchsia_target_api_level}", |
| ] |
| |
| if (defined(invoker.experimental_flags)) { |
| foreach(flag, invoker.experimental_flags) { |
| args += [ |
| "--experimental", |
| flag, |
| ] |
| } |
| } |
| |
| deps = [] |
| |
| if (defined(invoker.deps) || defined(invoker.public_deps)) { |
| merged_deps = [] |
| |
| if (defined(invoker.deps)) { |
| merged_deps += invoker.deps |
| } |
| |
| if (defined(invoker.public_deps)) { |
| merged_deps += invoker.public_deps |
| } |
| |
| dep_libraries = [] |
| |
| foreach(dep, merged_deps) { |
| gen_dir = get_label_info(dep, "target_gen_dir") |
| dep_toolchain = get_label_info(dep, "toolchain") |
| name = get_label_info(dep, "name") |
| dep_libraries += [ "${gen_dir}/${name}.fidl_libraries" ] |
| dep_dir = |
| get_label_info(get_label_info(dep, "label_no_toolchain"), "dir") |
| deps += [ "${dep_dir}:${name}_response_file($dep_toolchain)" ] |
| } |
| |
| inputs = dep_libraries |
| |
| args += [ "--dep-libraries" ] + rebase_path(dep_libraries, root_build_dir) |
| } |
| |
| if (defined(invoker.non_fidl_deps)) { |
| deps += invoker.non_fidl_deps |
| } |
| } |
| |
| action("${target_name}_ir") { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| visibility = [ ":*" ] |
| |
| deps = [ ":${invoker.target_name}_response_file" ] |
| |
| script = gn_sdk_root + "/gn_run_binary.py" |
| |
| inputs = [ |
| # Depend on the SDK hash, to ensure rebuild if the SDK tools change. |
| fuchsia_sdk_manifest_file, |
| _response_file, |
| ] |
| |
| outputs = [ json_representation ] |
| |
| rebased_response_file = rebase_path(_response_file, root_build_dir) |
| args = [ |
| rebase_path("${fuchsia_tool_dir}/fidlc", root_build_dir), |
| "@${rebased_response_file}", |
| ] |
| } |
| } |
| |
| # Generates C++ code for a given FIDL library |
| # |
| # Parameters |
| # |
| # fidl_gen_dir (required) |
| # The directory into which bindings should be generated. |
| # |
| # bindings_flavor (required) |
| # Identifies which kind of bindings (hlcpp, cpp, ...). |
| # This should be the same flavor as the one used when instantiating |
| # the fidl_cpp_library template. |
| # |
| # generated_sources (optional) |
| # A list of source files that will be generated for this binding, relative |
| # to the target-specific generation directory. |
| # |
| # generated_headers (optional) |
| # A list of header files that will be generated for this binding, relative |
| # to the target-specific generation directory. |
| # |
| # fidlgen_tool (required) |
| # The code generation tool to use, as an absolute GN label. |
| # |
| # additional_visibility (optional) |
| # A list of labels which are allowed to depend on the generated code. |
| # |
| template("fidl_cpp_codegen") { |
| root = "${invoker.fidl_gen_dir}/${invoker.bindings_flavor}" |
| generation_target_name = "${target_name}_gen" |
| |
| generation_visibility = [ ":${target_name}" ] |
| if (defined(invoker.additional_visibility)) { |
| generation_visibility += invoker.additional_visibility |
| } |
| |
| action(generation_target_name) { |
| visibility = generation_visibility |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| deps = [ invoker.fidl_ir_target ] |
| |
| inputs = [ |
| # Depend on the SDK hash, to ensure rebuild if the SDK tools change. |
| fuchsia_sdk_manifest_file, |
| invoker.json_representation, |
| ] |
| |
| outputs = [] |
| if (defined(invoker.generated_sources)) { |
| foreach(output, invoker.generated_sources) { |
| outputs += [ "${root}/${output}" ] |
| } |
| } |
| if (defined(invoker.generated_headers)) { |
| foreach(output, invoker.generated_headers) { |
| outputs += [ "${root}/${output}" ] |
| } |
| } |
| |
| script = gn_sdk_root + "/gn_run_binary.py" |
| args = [ |
| rebase_path(invoker.fidlgen_tool, root_build_dir), |
| "--json", |
| rebase_path(invoker.json_representation, root_build_dir), |
| "--root", |
| rebase_path(root, root_build_dir), |
| ] |
| } |
| } |
| |
| template("_fidl_cpp_library_impl") { |
| root = "${invoker.fidl_gen_dir}/${invoker.bindings_flavor}" |
| generation_target_name = "${target_name}_gen" |
| if (defined(invoker.generation_target_prefix)) { |
| generation_target_name = "${invoker.generation_target_prefix}_gen" |
| } |
| |
| config_target_name = "${target_name}_config" |
| config(config_target_name) { |
| visibility = [ ":${target_name}" ] |
| include_dirs = [ root ] |
| } |
| |
| source_set(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "public_deps", |
| "testonly", |
| "visibility", |
| ]) |
| if (defined(visibility)) { |
| # Ensure that layers have visibility to each other. |
| visibility += [ ":*" ] |
| } |
| |
| sources = [] |
| public = [] |
| if (defined(invoker.generated_sources)) { |
| foreach(source, invoker.generated_sources) { |
| sources += [ "${root}/${source}" ] |
| } |
| } |
| if (defined(invoker.generated_headers)) { |
| foreach(header, invoker.generated_headers) { |
| sources += [ "${root}/${header}" ] |
| public += [ "${root}/${header}" ] |
| } |
| } |
| |
| if (defined(invoker.generated_headers)) { |
| # Let dependencies use `#include "$file_stem.h"`. |
| public_configs = [ ":$config_target_name" ] |
| } |
| |
| # Metadata to allow us to query all FIDL IR files. |
| metadata = { |
| fidl_json = [ rebase_path(invoker.json_representation, root_build_dir) ] |
| } |
| |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ |
| ":${generation_target_name}", |
| invoker.fidl_ir_target, |
| ] |
| |
| if (!defined(public_deps)) { |
| public_deps = [] |
| } |
| |
| not_needed(invoker, [ "bindings_flavor" ]) |
| not_needed(invoker, [ "bindings_layer" ]) |
| if (defined(invoker.public_deps)) { |
| if (invoker.public_deps != []) { |
| if (defined(invoker.bindings_layer)) { |
| bindings_layer = invoker.bindings_layer |
| } else { |
| bindings_layer = invoker.bindings_flavor |
| } |
| foreach(dep, invoker.public_deps) { |
| label = get_label_info(dep, "label_no_toolchain") |
| if (get_label_info(label, "name") != "zx") { |
| public_deps += [ "${label}_${bindings_layer}" ] |
| } else { |
| not_needed([ "bindings_layer" ]) |
| } |
| } |
| } |
| } |
| |
| public_deps += invoker.additional_public_deps |
| } |
| } |
| |
| # Defines a C++ library target (source_set) generated from a FIDL library. |
| # |
| # FIDL library dependencies under `public_deps` will manifest as corresponding |
| # library target dependencies. |
| # |
| # Parameters |
| # |
| # fidl_gen_dir (required) |
| # The directory where generated files will be placed. |
| # |
| # json_representation (required) |
| # The file containing the json representation. |
| # |
| # fidl_ir_target (required) |
| # The target for the base fidl library. |
| # |
| # bindings_flavor (required) |
| # Identifies which kind of bindings (hlcpp, cpp, ...). |
| # This should be the same suffix as the one used when instantiating |
| # the fidl_cpp_codegen template. |
| # |
| # bindings_layer (optional) |
| # A particular binding may be decomposed into multiple layers. In that case, |
| # this identifies the particular layer that makes up this library (e.g. |
| # domain objects layer, messaging layer, ...). When adding dependencies, |
| # a particular layer for a FIDL library depends on the corresponding |
| # layers of the dependencies of that FIDL library. |
| # |
| # Some examples of valid layers are: |
| # * cpp_wire: Wire messaging over channel transport |
| # * cpp_wire_types: Wire domain objects |
| # |
| # If missing, defaults to bindings_flavor. |
| # |
| # generated_sources (optional) |
| # A list of source files that will be generated for this binding, relative |
| # to the target-specific generation directory. |
| # |
| # generated_headers (optional) |
| # A list of header files that will be generated for this binding, relative |
| # to the target-specific generation directory. |
| # |
| # generation_target_prefix (optional) |
| # Overrides the prefix for the generation target so that it becomes |
| # `${generation_target_prefix}_gen`. |
| # |
| # additional_public_deps (optional) |
| # A list of targets to be added to public_deps. |
| # |
| template("fidl_cpp_library") { |
| if (invoker.fidl_target_name == "zx") { |
| # The zx FIDL library isn't generated with C++ fidlgens. |
| not_needed(invoker, "*") |
| group(target_name) { |
| } |
| } else { |
| _fidl_cpp_library_impl(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "public_deps", |
| "testonly", |
| "visibility", |
| "fidl_gen_dir", |
| "fidl_ir_target", |
| "json_representation", |
| "bindings_flavor", |
| "bindings_layer", |
| "generated_sources", |
| "generated_headers", |
| "generation_target_prefix", |
| "additional_public_deps", |
| ]) |
| } |
| } |
| } |
| |
| # Define a Fuchsia FIDL library target. |
| # |
| # ${namespace}.${library_name} must match the the library name specified in the FIDL |
| # files. |
| # |
| # Parameters |
| # |
| # sources |
| # Required: List of .fidl files. |
| # |
| # library_name |
| # Optional: Name of the library. target_name is used if name |
| # is not specified explicitly. |
| # |
| # namespace |
| # Optional: Namespace for the library. |
| # |
| # deps |
| # Optional: List of other fidl_library() targets that this |
| # FIDL library depends on. |
| # |
| # non_fidl_deps |
| # Optional: List of other deps that aren't fidl_library targets. |
| # |
| # experimental_flags |
| # Optional: List of experimental flags to pass to fidlc. |
| # |
| template("fidl_library") { |
| forward_variables_from(invoker, [ "namespace" ]) |
| |
| library_basename = target_name |
| if (defined(invoker.library_name)) { |
| library_basename = invoker.library_name |
| } |
| |
| if (defined(namespace)) { |
| library_name = "${namespace}.${library_basename}" |
| _namespace_path = string_replace(namespace, ".", "/") |
| _library_name_slashes = "${_namespace_path}/${library_basename}" |
| } else { |
| library_name = library_basename |
| _library_name_slashes = string_replace(library_basename, ".", "/") |
| } |
| |
| json_representation = "${target_gen_dir}/${library_name}.fidl.json" |
| fidl_gen_dir = "${target_gen_dir}/fidl" |
| fidl_target_name = target_name |
| fidl_ir_target = ":${target_name}_ir" |
| |
| fidl_base_library(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "sources", |
| "deps", |
| "public_deps", |
| "testonly", |
| ]) |
| } |
| |
| # HLCPP bindings |
| hlcpp_options = { |
| bindings_flavor = "hlcpp" |
| generated_headers = [ |
| "${_library_name_slashes}/cpp/fidl.h", |
| "${_library_name_slashes}/cpp/fidl_test_base.h", |
| ] |
| generated_sources = [ |
| "${_library_name_slashes}/cpp/fidl.cc", |
| "${_library_name_slashes}/cpp/tables.c", |
| ] |
| } |
| |
| fidl_cpp_codegen("${target_name}_hlcpp") { |
| forward_variables_from(invoker, [ "testonly" ]) |
| forward_variables_from(hlcpp_options, "*") |
| fidlgen_tool = "${fuchsia_tool_dir}/fidlgen_hlcpp" |
| } |
| |
| fidl_cpp_library("${target_name}_hlcpp") { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "public_deps", |
| "testonly", |
| "visibility", |
| ]) |
| additional_public_deps = [ |
| "${fuchsia_sdk}/pkg/fidl", |
| "${fuchsia_sdk}/pkg/fidl_cpp", |
| ] |
| forward_variables_from(hlcpp_options, "*") |
| } |
| |
| # Alias the target name to the _hlcpp target. This is for backward |
| # compatibility with the the old mechanism where the base fidl library |
| # and the hlcpp bindings were in a single target. Once all uses of |
| # hlcpp are removed, this alias should be removed and the target that |
| # is currently named ${target_name}_ir will become ${target_name} |
| group(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| public_deps = [ ":${invoker.target_name}_hlcpp" ] |
| } |
| |
| # These bindings are defined as a set of layers that build upon each other. |
| # All of the layers are generated in a single fidlgen invocation but are |
| # exposed as separate source_sets to user code so that it's easy to include |
| # just the parts of the bindings that you need. |
| llcpp_layers = [ |
| { |
| layer = "cpp_common" |
| headers = [ |
| "fidl/${library_name}/cpp/common_types.h", |
| "fidl/${library_name}/cpp/markers.h", |
| ] |
| sources = [ "fidl/${library_name}/cpp/common_types.cc" ] |
| |
| public_deps = [ |
| "${fuchsia_sdk}/pkg/fidl", |
| "${fuchsia_sdk}/pkg/fidl_cpp_wire", |
| "${fuchsia_sdk}/pkg/fit", |
| ] |
| }, |
| |
| { |
| layer = "cpp_wire_types" |
| headers = [ "fidl/${library_name}/cpp/wire_types.h" ] |
| sources = [ "fidl/${library_name}/cpp/wire_types.cc" ] |
| |
| layer_deps = [ "cpp_common" ] |
| }, |
| |
| { |
| layer = "cpp_wire" # AKA: wire_channel_messaging |
| headers = [ |
| "fidl/${library_name}/cpp/wire.h", |
| "fidl/${library_name}/cpp/wire_messaging.h", |
| ] |
| sources = [ "fidl/${library_name}/cpp/wire_messaging.cc" ] |
| layer_deps = [ "cpp_wire_types" ] |
| }, |
| |
| { |
| layer = "cpp_wire_testing" |
| headers = [ "fidl/${library_name}/cpp/wire_test_base.h" ] |
| layer_deps = [ "cpp_wire" ] |
| testonly = true |
| }, |
| |
| { |
| layer = "cpp_natural_types" |
| headers = [ "fidl/${library_name}/cpp/natural_types.h" ] |
| sources = [ "fidl/${library_name}/cpp/natural_types.cc" ] |
| public_deps = [ "${fuchsia_sdk}/pkg/fidl_cpp_base_v2" ] |
| layer_deps = [ "cpp_common" ] |
| }, |
| |
| { |
| layer = "cpp_natural_ostream" |
| headers = [ "fidl/${library_name}/cpp/natural_ostream.h" ] |
| sources = [ "fidl/${library_name}/cpp/natural_ostream.cc" ] |
| public_deps = [ "${fuchsia_sdk}/pkg/fidl_cpp_natural_ostream" ] |
| layer_deps = [ "cpp_natural_types" ] |
| }, |
| |
| { |
| layer = "cpp_type_conversions" |
| headers = [ "fidl/${library_name}/cpp/type_conversions.h" ] |
| sources = [ "fidl/${library_name}/cpp/type_conversions.cc" ] |
| |
| public_deps = [ "${fuchsia_sdk}/pkg/fidl_cpp_v2" ] |
| |
| layer_deps = [ |
| "cpp_natural_types", |
| |
| # TODO(fxbug.dev/101525): Replace with "cpp_wire_types". |
| "cpp_wire", |
| ] |
| }, |
| |
| { |
| layer = "cpp" # AKA: unified_channel_messaging |
| headers = [ |
| "fidl/${library_name}/cpp/fidl.h", |
| "fidl/${library_name}/cpp/natural_messaging.h", |
| ] |
| sources = [ "fidl/${library_name}/cpp/natural_messaging.cc" ] |
| layer_deps = [ |
| "cpp_natural_types", |
| "cpp_type_conversions", |
| "cpp_wire", |
| ] |
| public_deps = [ "${fuchsia_sdk}/pkg/fidl_cpp_v2" ] |
| }, |
| |
| { |
| layer = "cpp_testing" |
| headers = [ "fidl/${library_name}/cpp/test_base.h" ] |
| layer_deps = [ "cpp" ] |
| testonly = true |
| }, |
| |
| { |
| layer = "cpp_hlcpp_conversion" |
| headers = [ "fidl/${library_name}/cpp/hlcpp_conversion.h" ] |
| public_deps = [ |
| ":${target_name}_hlcpp", |
| "${fuchsia_sdk}/pkg/fidl_cpp_hlcpp_conversion", |
| ] |
| layer_deps = [ "cpp_natural_types" ] |
| }, |
| ] |
| |
| # Define new C++ binding targets. |
| layer_target_prefix = target_name + "_" |
| fidl_cpp_codegen("${target_name}_cpp") { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "fidl_gen_dir", |
| "fidl_ir_json", |
| "fidl_ir_target", |
| ]) |
| bindings_flavor = "cpp" |
| fidlgen_tool = "${fuchsia_tool_dir}/fidlgen_cpp" |
| generated_headers = [] |
| generated_sources = [] |
| additional_visibility = [] |
| foreach(layer, llcpp_layers) { |
| additional_visibility += [ ":${layer_target_prefix}${layer.layer}" ] |
| if (defined(layer.headers)) { |
| generated_headers += layer.headers |
| } |
| if (defined(layer.sources)) { |
| generated_sources += layer.sources |
| } |
| } |
| } |
| |
| foreach(layer, llcpp_layers) { |
| layer_target_name = layer_target_prefix + layer.layer |
| fidl_cpp_library(layer_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| "public_configs", |
| "public_deps", |
| "fidl_gen_dir", |
| ]) |
| generation_target_prefix = "${invoker.target_name}_cpp" |
| bindings_flavor = "cpp" |
| bindings_layer = layer.layer |
| if (defined(layer.headers)) { |
| generated_headers = layer.headers |
| } |
| if (defined(layer.sources)) { |
| generated_sources = layer.sources |
| } |
| if (defined(layer.testonly)) { |
| testonly = layer.testonly |
| } |
| additional_public_deps = [] |
| if (defined(layer.public_deps)) { |
| additional_public_deps += layer.public_deps |
| } |
| if (defined(layer.layer_deps)) { |
| foreach(layer_dep, layer.layer_deps) { |
| additional_public_deps += [ ":${layer_target_prefix}${layer_dep}" ] |
| } |
| } |
| } |
| } |
| } |