blob: 73f959c0667b4a5c64cbd4c542f7b0bf949c653b [file] [log] [blame]
# Copyright 2022 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.
"""A cc_library backed by a FIDL library."""
load(":providers.bzl", "FuchsiaFidlLibraryInfo")
_CodegenInfo = provider("Carries generated information across FIDL bindings code generation ", fields = ["files"])
# ALL CODE BELOW IS DEPRECATED - TODO: REMOVE IT when soft transition is over
def _codegen_impl(context):
sdk = context.toolchains["@rules_fuchsia//fuchsia:toolchain"]
fidlgen = sdk.fidlgen_cpp if context.attr.binding_level == "llcpp" else sdk.fidlgen_hlcpp
ir = context.attr.library[FuchsiaFidlLibraryInfo].ir
name = context.attr.library[FuchsiaFidlLibraryInfo].name
base_path = context.attr.name + "." + context.attr.binding_level
# This declaration is needed in order to get access to the full path.
root = context.actions.declare_directory(base_path)
headers = []
sources = []
if context.attr.binding_level == "llcpp":
dir = base_path + "/fidl/" + name + "/cpp"
header_files = []
source_files = []
# common:
header_files.extend(["common_types.h", "markers.h"])
source_files.extend(["common_types.cc"])
# wire types:
header_files.extend(["wire_types.h"])
source_files.extend(["wire_types.cc"])
# wire zircon:
header_files.extend(["wire.h", "wire_messaging.h"])
source_files.extend(["wire_messaging.cc"])
# wire channel testing:
header_files.extend(["wire_test_base.h"])
# natural types:
header_files.extend(["natural_types.h"])
source_files.extend(["natural_types.cc"])
# wire/natural type conversions:
header_files.extend(["type_conversions.h"])
source_files.extend(["type_conversions.cc"])
# unified zircon channel messaging:
header_files.extend(["fidl.h", "natural_messaging.h"])
source_files.extend(["natural_messaging.cc"])
# TODO(fxbug.dev/108680): Better workaround for skipping codegen for zx.
if name == "zx":
source_files = ["markers.h"]
for header in header_files:
headers.append(context.actions.declare_file(dir + "/" + header))
for source in source_files:
sources.append(context.actions.declare_file(dir + "/" + source))
else: # context.attr.binding_level == "hlcpp"
dir = base_path + "/" + name.replace(".", "/") + "/cpp"
headers.append(context.actions.declare_file(dir + "/fidl.h"))
headers.append(context.actions.declare_file(dir + "/fidl_test_base.h"))
sources.append(context.actions.declare_file(dir + "/fidl.cc"))
outputs = [root] + headers + sources
context.actions.run(
executable = fidlgen,
arguments = [
"--json",
ir.path,
"--root",
root.path,
],
inputs = [
ir,
],
outputs = outputs,
mnemonic = "FidlGenCc",
)
return [
_CodegenInfo(files = depset(sources)),
DefaultInfo(files = depset(headers)),
]
def _impl_wrapper_impl(context):
files = context.attr.codegen[_CodegenInfo].files
return [DefaultInfo(files = files)]
# Runs fidlgen to produce both the header file and the implementation file.
# Only exposes the header as a source, as the two files need to be consumed by
# the cc_library as two separate rules.
_codegen = rule(
implementation = _codegen_impl,
toolchains = ["@rules_fuchsia//fuchsia:toolchain"],
# Files must be generated in genfiles in order for the header to be included
# anywhere.
output_to_genfiles = True,
attrs = {
"library": attr.label(
doc = "The FIDL library to generate code for",
mandatory = True,
allow_files = False,
providers = [FuchsiaFidlLibraryInfo],
),
"binding_level": attr.string(
doc = "Controls whether to generate high- (hlcpp) or low-level (llcpp) C++ bindings.",
mandatory = True,
),
},
)
# Simply declares the implementation file generated by the codegen target as an
# output.
# This allows the implementation file to be exposed as a source in its own rule.
_impl_wrapper = rule(
implementation = _impl_wrapper_impl,
output_to_genfiles = True,
attrs = {
"codegen": attr.label(
doc = "The codegen rules generating the implementation file",
mandatory = True,
allow_files = False,
providers = [_CodegenInfo],
),
},
)
def _fidl_cc_library(name, library, binding_level, deps = [], tags = [], **kwargs):
"""Generates cc_library() for the given fidl_library.
Args:
name: Target name. Required.
library: fidl_library() target to generate the language bindings for. Required.
binding_level: Controls whether to generate high- (hlcpp) or low-level (llcpp) C++ bindings.
deps: Additional dependencies.
tags: Optional tags.
**kwargs: Remaining args.
"""
gen_name = "%s_codegen" % name
impl_name = "%s_impl" % name
_codegen(
name = gen_name,
library = library,
binding_level = binding_level,
)
_impl_wrapper(
name = impl_name,
codegen = ":%s" % gen_name,
)
native.cc_library(
name = name,
hdrs = [
":%s" % gen_name,
],
srcs = [
":%s" % impl_name,
# For the coding tables.
library,
],
# This is necessary in order to locate generated headers.
strip_include_prefix = gen_name + "." + binding_level,
deps = deps,
tags = tags,
**kwargs
)
def fuchsia_fidl_hlcpp_library(name, library, deps = [], tags = [], **kwargs):
"""Generates HLCPP cc_library() for the given fidl_library.
DEPRECATED: use fuchsia_fidl_library instead.
Args:
name: Target name. Required.
library: fidl_library() target to generate the language bindings for. Required.
deps: Additional dependencies.
tags: Optional tags.
**kwargs: Remaining args.
"""
_fidl_cc_library(
tags = tags,
name = name,
library = library,
binding_level = "hlcpp",
deps = deps,
**kwargs
)
def fuchsia_fidl_llcpp_library(name, library, deps = [], tags = [], **kwargs):
"""Generates LLCPP cc_library() for the given fidl_library.
DEPRECATED: use fuchsia_fidl_library instead.
Args:
name: Target name. Required.
library: fidl_library() target to generate the language bindings for. Required.
deps: Additional dependencies.
tags: Optional tags.
**kwargs: Remaining args.
"""
_fidl_cc_library(
tags = tags,
name = name,
library = library,
binding_level = "llcpp",
deps = deps,
**kwargs
)