google / emboss

Emboss is a tool for generating code that reads and writes binary data structures.
Apache License 2.0
71 stars 21 forks source link

Bazel: support "includes" in emboss_cc_library #107

Open BenjaminLawson opened 7 months ago

BenjaminLawson commented 7 months ago

Currently emboss_cc_library is missing the "includes" parameter found in cc_library. This can be worked around by wrapping every emboss_cc_library in a cc_library, but it is noisy.

I have a hacked together solution, but I don't know enough Bazel-fu to calculate the path to the includes correctly:

diff --git a/build_defs.bzl b/build_defs.bzl
index 114b0d6..cdbf303 100644
--- a/build_defs.bzl
+++ b/build_defs.bzl
@@ -26,7 +26,7 @@ There is also a convenience macro, `emboss_cc_library()`, which creates an

 load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")

-def emboss_cc_library(name, srcs, deps = [], visibility = None):
+def emboss_cc_library(name, srcs, deps = [], visibility = None, includes = []):
     """Constructs a C++ library from an .emb file."""
     if len(srcs) != 1:
         fail(
@@ -38,6 +38,7 @@ def emboss_cc_library(name, srcs, deps = [], visibility = None):
         name = name + "_ir",
         srcs = srcs,
         deps = [dep + "_ir" for dep in deps],
+        includes = includes,
     )

     cc_emboss_library(
@@ -130,6 +131,9 @@ emboss_library = rule(
         "deps": attr.label_list(
             providers = [EmbossInfo],
         ),
+        "includes": attr.string_list(
+            mandatory = False
+        ),
         "licenses": attr.license() if hasattr(attr, "license") else attr.string_list(),
         "_emboss_compiler": attr.label(
             executable = True,
@@ -184,6 +188,20 @@ def _cc_emboss_aspect_impl(target, ctx):
                      ] +
                      [runtime_cc_info.compilation_context.headers],
     )
+    prefixed_includes = [
+        "/".join(["bazel-out/k8-fastbuild/bin", target.label.workspace_root, target.label.package, include])
+        for include in ctx.rule.attr.includes
+    ]
+    transitive_includes = depset(
+        direct = prefixed_includes,
+        transitive = [
+            dep[CcInfo].compilation_context.includes
+            for dep in ctx.rule.attr.deps
+        ]
+    )
     (cc_compilation_context, cc_compilation_outputs) = cc_common.compile(
         name = ctx.label.name,
         actions = ctx.actions,
@@ -191,6 +209,7 @@ def _cc_emboss_aspect_impl(target, ctx):
         cc_toolchain = cc_toolchain,
         public_hdrs = headers,
         private_hdrs = transitive_headers.to_list(),
+        includes = transitive_includes.to_list(),
     )
     return [
         CcInfo(compilation_context = cc_compilation_context),
BenjaminLawson commented 7 months ago

My wrapper workaround:

emboss_cc_library(
    name = "_emboss_hci_common",
    srcs = ["public/pw_bluetooth/hci_common.emb"],
)

# emboss_cc_library doesn't support includes, so we need to wrap it.
cc_library(
    name = "emboss_hci_common",
    deps = [":_emboss_hci_common"],
    includes = ["public"],
)