[llvm] [libc][bazel] Use Bazel aspects to implement libc_release_library. (PR #134948)

Jordan Rupprecht via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 9 12:47:16 PDT 2025


================
@@ -44,84 +45,134 @@ def libc_release_copts():
     })
     return copts + platform_copts
 
-def _libc_library(name, copts = [], deps = [], local_defines = [], **kwargs):
+def _libc_library(name, **kwargs):
     """Internal macro to serve as a base for all other libc library rules.
 
     Args:
       name: Target name.
-      copts: The special compiler options for the target.
-      deps: The list of target dependencies if any.
-      local_defines: The list of target local_defines if any.
       **kwargs: All other attributes relevant for the cc_library rule.
     """
 
+    for attr in ["copts", "local_defines"]:
+        if attr in kwargs:
+            fail("disallowed attribute: '{}' in rule: '{}'".format(attr, name))
     native.cc_library(
         name = name,
-        copts = copts + libc_common_copts(),
-        local_defines = local_defines + LIBC_CONFIGURE_OPTIONS,
-        deps = deps,
+        copts = libc_common_copts(),
+        local_defines = LIBC_CONFIGURE_OPTIONS,
         linkstatic = 1,
         **kwargs
     )
 
-def _libc_library_filegroups(
-        name,
-        is_function,
-        srcs = [],
-        hdrs = [],
-        textual_hdrs = [],
-        deps = [],
-        # We're not using kwargs, but instead explicitly list all possible
-        # arguments that can be passed to libc_support_library or
-        # libc_function macros. This is done to limit the configurability
-        # and ensure the consistent and tightly controlled set of flags
-        # (see libc_common_copts and libc_release_copts above) is used to build
-        # libc code both for tests and for release configuration.
-        target_compatible_with = None):  # @unused
-    """Internal macro to collect sources and headers required to build a library.
-    """
-
-    # filegroups created from "libc_function" macro has an extra "_fn" in their
-    # name to ensure that no other libc target can depend on libc_function.
-    prefix = name + ("_fn" if is_function else "")
-    native.filegroup(
-        name = prefix + "_srcs",
-        srcs = srcs + hdrs + [dep + "_srcs" for dep in deps],
-    )
-    native.filegroup(
-        name = prefix + "_textual_hdrs",
-        srcs = textual_hdrs + [dep + "_textual_hdrs" for dep in deps],
-    )
-
 # A convenience function which should be used to list all libc support libraries.
 # Any library which does not define a public function should be listed with
 # libc_support_library.
 def libc_support_library(name, **kwargs):
     _libc_library(name = name, **kwargs)
-    _libc_library_filegroups(name = name, is_function = False, **kwargs)
 
 def libc_function(name, **kwargs):
     """Add target for a libc function.
 
     This macro creates an internal cc_library that can be used to test this
-    function, and creates filegroups required to include this function into
-    a release build of libc.
+    function.
 
     Args:
-      name: Target name. It is normally the name of the function this target is
-            for.
+      name: Target name. Typically the name of the function this target is for.
       **kwargs: Other attributes relevant for a cc_library. For example, deps.
     """
 
-    # Build "internal" library with a function, the target has ".__internal__" suffix and contains
-    # C++ functions in the "LIBC_NAMESPACE" namespace. This allows us to test the function in the
+    # Builds "internal" library with a function, exposed as a C++ function in
+    # the "LIBC_NAMESPACE" namespace. This allows us to test the function in the
     # presence of another libc.
     _libc_library(
         name = libc_internal_target(name),
         **kwargs
     )
 
-    _libc_library_filegroups(name = name, is_function = True, **kwargs)
+# LibcLibraryInfo is used to collect all sources and textual headers required
+# to build a particular libc_function or libc_support_library.
+LibcLibraryInfo = provider(
+    fields = ["srcs", "textual_hdrs"],
+)
+
+def _get_libc_info_aspect_impl(target, ctx):
+    maybe_srcs = getattr(ctx.rule.attr, "srcs", [])
+    maybe_hdrs = getattr(ctx.rule.attr, "hdrs", [])
+    maybe_textual_hdrs = getattr(ctx.rule.attr, "textual_hdrs", [])
+    maybe_deps = getattr(ctx.rule.attr, "deps", [])
+    return LibcLibraryInfo(
+        srcs = depset(
+            [
+                f
+                for src in maybe_srcs + maybe_hdrs
+                for f in src.files.to_list()
+                if f.is_source
+            ],
+            transitive = [
+                dep[LibcLibraryInfo].srcs
+                for dep in maybe_deps
+                if LibcLibraryInfo in dep
+            ],
+        ),
+        textual_hdrs = depset(
+            [
+                f
+                for hdr in maybe_textual_hdrs
+                for f in hdr.files.to_list()
+                if f.is_source
+            ],
+            transitive = [
+                dep[LibcLibraryInfo].textual_hdrs
+                for dep in maybe_deps
+                if LibcLibraryInfo in dep
+            ],
+        ),
+    )
+
+_get_libc_info_aspect = aspect(
+    implementation = _get_libc_info_aspect_impl,
+    attr_aspects = ["deps"],
+)
+
+def _get_libc_srcs_impl(ctx):
+    return DefaultInfo(
+        files = depset(transitive = [
+            fn[LibcLibraryInfo].srcs
+            for fn in ctx.attr.libs
+        ]),
+    )
+
+# get_libc_srcs returns the list of sources required to build all
+# specified libraries.
+get_libc_srcs = rule(
----------------
rupprecht wrote:

Since these are not used outside the bzl file, you should be able to name them privately, i.e. _get_libc_srcs and _get_libc_textual_hdrs

https://github.com/llvm/llvm-project/pull/134948


More information about the llvm-commits mailing list