blob: 815020cdb884ef8097848aefdd482d13ee74ae2a [file] [log] [blame]
# Copyright 2018 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("//build/compiled_action.gni")
import("//build/fidl/toolchain.gni")
import("//build/sdk/sdk_atom_alias.gni")
template("_fidl_cpp_codegen_impl") {
generation_target_name = "${target_name}_generate"
fidl_target_name = invoker.fidl_target_name
fidl_target_gen_dir =
get_label_info(":${fidl_target_name}($fidl_toolchain)", "target_gen_dir")
library_name = invoker.library_name
include_stem =
string_replace(library_name, ".", "/") + "/" + invoker.output_stem
file_stem = "$fidl_target_gen_dir/$fidl_target_name/$include_stem"
json_representation = "$fidl_target_gen_dir/$fidl_target_name.fidl.json"
generation_visibility = [
":$target_name",
"${invoker.fidlgen_tool}:*",
]
if (defined(invoker.fuzzers)) {
foreach(fuzzer, invoker.fuzzers) {
assert(
defined(fuzzer.protocol),
"FIDL protocol fuzzers must set protocol: the fully-qualified name of the protocol to be fuzzed.")
protocol_suffix = "_" + string_replace(fuzzer.protocol, ".", "_")
if (defined(fuzzer.methods)) {
foreach(method, fuzzer.methods) {
protocol_suffix = "${protocol_suffix}_${method}"
}
}
generation_visibility += [ ":${target_name}${protocol_suffix}" ]
}
}
compiled_action(generation_target_name) {
forward_variables_from(invoker, [ "testonly" ])
visibility = generation_visibility
tool = invoker.fidlgen_tool
inputs = [ json_representation ]
outputs = [
"$file_stem.h",
"$file_stem.cc",
]
args = [
"--json",
rebase_path(json_representation, root_build_dir),
"--output-base",
rebase_path(file_stem, root_build_dir),
"--include-base",
rebase_path("$fidl_target_gen_dir/$fidl_target_name", root_build_dir),
"--include-stem",
invoker.output_stem,
"--clang-format-path",
rebase_path(
"//prebuilt/third_party/clang/$host_platform/bin/clang-format"),
]
if (defined(invoker.additional_fidlgen_arguments)) {
args += invoker.additional_fidlgen_arguments
}
deps = [ ":$fidl_target_name($fidl_toolchain)" ]
metadata = {
generated_sources = rebase_path(outputs, root_build_dir)
}
}
}
# Generates some C++ bindings for a FIDL library.
#
# The parameters for this template are defined in //build/fidl/fidl.gni. The
# relevant parameters in this template are:
# - name;
# - sources;
template("fidl_cpp_codegen") {
if (current_toolchain == fidl_toolchain) {
_fidl_cpp_codegen_impl(target_name) {
forward_variables_from(invoker, "*")
}
} else {
# Code generation only happens under the FIDL toolchain.
not_needed([ "target_name" ])
not_needed(invoker, "*")
}
}
template("_fidl_llcpp_codegen_impl") {
generation_target_name = "${target_name}_generate"
generation_visibility = [
":$target_name",
"//tools/fidl/fidlgen_llcpp:*",
]
library_name = invoker.library_name
fidl_target_name = invoker.fidl_target_name
fidl_target_gen_dir =
get_label_info(":$target_name($fidl_toolchain)", "target_gen_dir")
json_representation = "$fidl_target_gen_dir/$fidl_target_name.fidl.json"
include_stem =
string_replace(library_name, ".", "/") + "/" + invoker.output_stem
file_stem = "$fidl_target_gen_dir/$fidl_target_name/$include_stem"
compiled_action(generation_target_name) {
forward_variables_from(invoker, [ "testonly" ])
visibility = generation_visibility
tool = "//tools/fidl/fidlgen_llcpp"
inputs = [ json_representation ]
outputs = [
"$file_stem.h",
"$file_stem.cc",
]
args = [
"--json",
rebase_path(json_representation, root_build_dir),
"--header",
rebase_path("$file_stem.h", root_build_dir),
"--source",
rebase_path("$file_stem.cc", root_build_dir),
"--include-base",
rebase_path("$fidl_target_gen_dir/$fidl_target_name", root_build_dir),
"--include-stem",
invoker.output_stem,
"--clang-format-path",
rebase_path(
"//prebuilt/third_party/clang/$host_platform/bin/clang-format"),
]
deps = [ ":$fidl_target_name($fidl_toolchain)" ]
metadata = {
generated_sources = rebase_path(outputs, root_build_dir)
}
}
}
# Generates low-level C++ bindings for a library.
template("fidl_llcpp_codegen") {
if (current_toolchain == fidl_toolchain) {
_fidl_llcpp_codegen_impl(target_name) {
forward_variables_from(invoker, "*")
}
} else {
# Code generation only happens under the FIDL toolchain.
not_needed([ "target_name" ])
not_needed(invoker, "*")
}
}
template("_fidl_cpp_library_impl") {
config_target_name = "${target_name}__config"
generation_target_name =
"${invoker.fidl_target_name}${invoker.target_suffix}_generate"
library_name = invoker.library_name
fidl_target_name = invoker.fidl_target_name
fidl_target_gen_dir =
get_label_info(":$target_name($fidl_toolchain)", "target_gen_dir")
include_stem =
string_replace(library_name, ".", "/") + "/" + invoker.output_stem
file_stem = "$fidl_target_gen_dir/$fidl_target_name/$include_stem"
config(config_target_name) {
include_dirs = [ "$fidl_target_gen_dir/$fidl_target_name" ]
}
source_set(target_name) {
forward_variables_from(invoker,
[
"defines",
"testonly",
"visibility",
])
if (defined(invoker.header_only) && invoker.header_only) {
sources = [ "$file_stem.h" ]
} else if (defined(invoker.source_only) && invoker.source_only) {
sources = [ "$file_stem.cc" ]
} else {
sources = [
"$file_stem.cc",
"$file_stem.h",
]
}
# Let dependencies use `#include "$file_stem.h"`.
public_configs = [ ":$config_target_name" ]
public_deps = [
":$generation_target_name($fidl_toolchain)",
":${invoker.fidl_target_name}($fidl_toolchain)",
":${invoker.fidl_target_name}_tables",
]
# Map FIDL library dependencies to generated library dependencies
# of the same type (identified by target_suffix).
not_needed(invoker, [ "target_suffix" ])
if (defined(invoker.public_deps)) {
foreach(dep, invoker.public_deps) {
label = get_label_info(dep, "label_no_toolchain")
public_deps += [ "${label}${invoker.target_suffix}" ]
}
}
public_deps += invoker.additional_public_deps
if (defined(invoker.deps)) {
public_deps += invoker.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
#
# library_name (required)
# Name of the FIDL library.
#
# fidl_target_name (required)
# Name of the GN target corresponding to the FIDL library.
#
# target_suffix (required)
# Must begin with an underscore. Identifies which kind of library
# (_hlcpp, _llcpp, ...).
#
# header_only (optional)
# If true, the generated library only has a header.
#
# source_only (optional)
# If true, the generated library only has a source file.
template("fidl_cpp_library") {
if (current_toolchain != fidl_toolchain) {
_fidl_cpp_library_impl(target_name) {
forward_variables_from(invoker, "*")
}
} else {
# No-op under FIDL toolchain
not_needed([ "target_name" ])
not_needed(invoker, "*")
}
}
template("_fidl_cpp_fuzzer") {
fuzzer = invoker.fuzzer
assert(
defined(fuzzer.protocol),
"FIDL protocol fuzzers must set protocol: the fully-qualified name of the protocol to be fuzzed.")
protocol_suffix = "_" + string_replace(fuzzer.protocol, ".", "_")
library_defines = [ "PROTOCOL${protocol_suffix}" ]
if (defined(invoker.defines)) {
library_defines += invoker.defines
}
if (defined(fuzzer.methods)) {
foreach(method, fuzzer.methods) {
library_defines += [ "METHOD_${method}" ]
}
} else {
library_defines += [ "ALL_METHODS" ]
}
target_suffix = "_libfuzzer"
fuzzer_lib_name = "${target_name}${target_suffix}${protocol_suffix}"
fidl_cpp_library(fuzzer_lib_name) {
library_name = invoker.library_name
forward_variables_from(invoker,
[
"testonly",
"visibility",
"public_deps",
"fidl_target_name",
])
output_stem = "cpp/libfuzzer"
target_suffix = target_suffix
additional_public_deps = [ ":${invoker.fidl_target_name}_libfuzzer" ]
defines = library_defines
source_only = true
}
}
# Generates various C++ FIDL bindings: HLCPP, LLCPP, and fuzzers.
#
# Note:
# - Under the FIDL toolchain, we would create targets that generate
# the HLCPP/LLCPP bindings.
# - Under other toolchains, we would create library targets that
# reference the generated code.
template("fidl_cpp_family") {
# Allow users to override the library name by specifying a
# "name" variable in the `fidl("my_lib")` template invocation.
# Otherwise, default to the `target_name` of the FIDL library.
#
# Note that library names will have implication on the generated
# include paths, hence should be separate from `target_name`.
library_name = target_name
if (defined(invoker.name)) {
library_name = invoker.name
}
# `target_name` becomes clobbered in template invocation scopes;
# back it up here.
fidl_target_name = target_name
# `sources` is only required to invoke `fidlc`;
# the bindings code generation consumes the JSON IR instead.
not_needed(invoker, [ "sources" ])
# Determine the C++ bindings dependencies based on Fuchsia/host.
# Additionally, an empty llcpp_public_deps indicates that the LLCPP
# bindings for this library is not needed.
llcpp_public_deps = []
if (is_fuchsia) {
not_needed(invoker, [ "host_llcpp" ])
hlcpp_public_deps = [ "//sdk/lib/fidl/cpp" ]
llcpp_public_deps = [
"//zircon/public/lib/fidl",
"//zircon/public/lib/fidl-llcpp",
"//zircon/public/lib/fit",
]
} else {
# On host.
hlcpp_public_deps = [ "//sdk/lib/fidl/cpp:cpp_base" ]
if (defined(invoker.host_llcpp) && invoker.host_llcpp) {
llcpp_public_deps = [
"//zircon/public/lib/fidl-llcpp",
"//zircon/public/lib/fit",
]
} else {
# Do not generate LLCPP if not requested.
llcpp_public_deps = []
}
}
common_options = {
fidl_target_name = fidl_target_name
library_name = library_name
forward_variables_from(invoker, [ "testonly" ])
}
natural_types_public_deps = [ "//sdk/lib/fidl/cpp:cpp_base" ]
#
# HLCPP Bindings
#
# Define C++ natural types target.
# They are generated using the HLCPP backend.
fidl_cpp_codegen("${target_name}_cpp_natural_types") {
forward_variables_from(common_options, "*")
output_stem = "cpp/natural_types"
fidlgen_tool = "//tools/fidl/fidlgen_hlcpp"
additional_fidlgen_arguments =
[ "--experimental-split-generation-domain-objects" ]
}
fidl_cpp_library("${target_name}_cpp_natural_types") {
forward_variables_from(invoker,
[
"public_deps",
"visibility",
])
forward_variables_from(common_options, "*")
output_stem = "cpp/natural_types"
target_suffix = "_cpp_natural_types"
additional_public_deps = natural_types_public_deps
}
# Define HLCPP target.
fidl_cpp_codegen("${target_name}_hlcpp") {
forward_variables_from(common_options, "*")
output_stem = "cpp/fidl"
fidlgen_tool = "//tools/fidl/fidlgen_hlcpp"
}
fidl_cpp_library("${target_name}_hlcpp") {
forward_variables_from(invoker,
[
"public_deps",
"visibility",
])
forward_variables_from(common_options, "*")
output_stem = "cpp/fidl"
target_suffix = "_hlcpp"
additional_public_deps = hlcpp_public_deps
}
if (current_toolchain != fidl_toolchain) {
# Set up an alias from ":my_lib_hlcpp" to ":my_lib"
group(target_name) {
forward_variables_from(invoker, [ "testonly" ])
public_deps = [ ":${target_name}_hlcpp" ]
}
# Set up an SDK item for this library
if (defined(invoker.sdk_category) && invoker.sdk_category != "excluded") {
# Instead of depending on the generated bindings, set up a dependency on
# the original library.
sdk_target_name = "${target_name}_sdk"
sdk_atom_alias(sdk_target_name) {
atom = ":$sdk_target_name($fidl_toolchain)"
}
}
}
#
# LLCPP Bindings
#
# Define LLCPP target, if requested.
if (llcpp_public_deps != []) {
fidl_llcpp_codegen("${target_name}_llcpp") {
forward_variables_from(common_options, "*")
output_stem = "llcpp/fidl"
}
fidl_cpp_library("${target_name}_llcpp") {
forward_variables_from(invoker,
[
"public_deps",
"visibility",
])
forward_variables_from(common_options, "*")
output_stem = "llcpp/fidl"
target_suffix = "_llcpp"
additional_public_deps = llcpp_public_deps
}
}
#
# Fuzzers (also dependent on HLCPP)
#
# Define fuzzer targets.
fidl_cpp_codegen("${target_name}_libfuzzer") {
forward_variables_from(invoker, [ "fuzzers" ])
forward_variables_from(common_options, "*")
output_stem = "cpp/libfuzzer"
fidlgen_tool = "//tools/fidl/fidlgen_libfuzzer"
}
# Define fuzzer header library.
fidl_cpp_library("${target_name}_libfuzzer") {
forward_variables_from(invoker,
[
"public_deps",
"visibility",
])
forward_variables_from(common_options, "*")
output_stem = "cpp/libfuzzer"
target_suffix = "_libfuzzer"
additional_public_deps = [
"//zircon/system/ulib/async-default",
"//zircon/system/ulib/async-loop:async-loop-cpp",
"//zircon/system/ulib/async-loop:async-loop-default",
# The generated headers `#include` the hlcpp bindings headers
# generated by the clause above, so the generated target needs
# that bindings library target in its public_deps.
":${fidl_target_name}_hlcpp",
]
header_only = true
}
# Define fuzzer implementation libraries (one per fuzzed protocol).
# The source file is the same - different macro definitions
# are used to customize the fuzzing configuration.
if (defined(invoker.fuzzers)) {
foreach(fuzzer, invoker.fuzzers) {
_fidl_cpp_fuzzer(target_name) {
forward_variables_from(invoker, "*")
fidl_target_name = fidl_target_name
}
}
}
}