@@ -10,8 +10,9 @@ load(":libc_configure_options.bzl", "LIBC_CONFIGURE_OPTIONS")
1010load (":libc_namespace.bzl" , "LIBC_NAMESPACE" )
1111load (":platforms.bzl" , "PLATFORM_CPU_X86_64" )
1212
13+ # TODO: Remove this helper function once all donwstream users are migrated.
1314def libc_internal_target (name ):
14- return name + ".__internal__"
15+ return name
1516
1617def libc_common_copts ():
1718 root_label = Label (":libc" )
@@ -44,84 +45,134 @@ def libc_release_copts():
4445 })
4546 return copts + platform_copts
4647
47- def _libc_library (name , copts = [], deps = [], local_defines = [], ** kwargs ):
48+ def _libc_library (name , ** kwargs ):
4849 """Internal macro to serve as a base for all other libc library rules.
4950
5051 Args:
5152 name: Target name.
52- copts: The special compiler options for the target.
53- deps: The list of target dependencies if any.
54- local_defines: The list of target local_defines if any.
5553 **kwargs: All other attributes relevant for the cc_library rule.
5654 """
5755
56+ for attr in ["copts" , "local_defines" ]:
57+ if attr in kwargs :
58+ fail ("disallowed attribute: '{}' in rule: '{}'" .format (attr , name ))
5859 native .cc_library (
5960 name = name ,
60- copts = copts + libc_common_copts (),
61- local_defines = local_defines + LIBC_CONFIGURE_OPTIONS ,
62- deps = deps ,
61+ copts = libc_common_copts (),
62+ local_defines = LIBC_CONFIGURE_OPTIONS ,
6363 linkstatic = 1 ,
6464 ** kwargs
6565 )
6666
67- def _libc_library_filegroups (
68- name ,
69- is_function ,
70- srcs = [],
71- hdrs = [],
72- textual_hdrs = [],
73- deps = [],
74- # We're not using kwargs, but instead explicitly list all possible
75- # arguments that can be passed to libc_support_library or
76- # libc_function macros. This is done to limit the configurability
77- # and ensure the consistent and tightly controlled set of flags
78- # (see libc_common_copts and libc_release_copts above) is used to build
79- # libc code both for tests and for release configuration.
80- target_compatible_with = None ): # @unused
81- """Internal macro to collect sources and headers required to build a library.
82- """
83-
84- # filegroups created from "libc_function" macro has an extra "_fn" in their
85- # name to ensure that no other libc target can depend on libc_function.
86- prefix = name + ("_fn" if is_function else "" )
87- native .filegroup (
88- name = prefix + "_srcs" ,
89- srcs = srcs + hdrs + [dep + "_srcs" for dep in deps ],
90- )
91- native .filegroup (
92- name = prefix + "_textual_hdrs" ,
93- srcs = textual_hdrs + [dep + "_textual_hdrs" for dep in deps ],
94- )
95-
9667# A convenience function which should be used to list all libc support libraries.
9768# Any library which does not define a public function should be listed with
9869# libc_support_library.
9970def libc_support_library (name , ** kwargs ):
10071 _libc_library (name = name , ** kwargs )
101- _libc_library_filegroups (name = name , is_function = False , ** kwargs )
10272
10373def libc_function (name , ** kwargs ):
10474 """Add target for a libc function.
10575
10676 This macro creates an internal cc_library that can be used to test this
107- function, and creates filegroups required to include this function into
108- a release build of libc.
77+ function.
10978
11079 Args:
111- name: Target name. It is normally the name of the function this target is
112- for.
80+ name: Target name. Typically the name of the function this target is for.
11381 **kwargs: Other attributes relevant for a cc_library. For example, deps.
11482 """
11583
116- # Build "internal" library with a function, the target has ".__internal__" suffix and contains
117- # C++ functions in the "LIBC_NAMESPACE" namespace. This allows us to test the function in the
84+ # Builds "internal" library with a function, exposed as a C++ function in
85+ # the "LIBC_NAMESPACE" namespace. This allows us to test the function in the
11886 # presence of another libc.
11987 _libc_library (
12088 name = libc_internal_target (name ),
12189 ** kwargs
12290 )
12391
124- _libc_library_filegroups (name = name , is_function = True , ** kwargs )
92+ # LibcLibraryInfo is used to collect all sources and textual headers required
93+ # to build a particular libc_function or libc_support_library.
94+ LibcLibraryInfo = provider (
95+ fields = ["srcs" , "textual_hdrs" ],
96+ )
97+
98+ def _get_libc_info_aspect_impl (target , ctx ):
99+ maybe_srcs = getattr (ctx .rule .attr , "srcs" , [])
100+ maybe_hdrs = getattr (ctx .rule .attr , "hdrs" , [])
101+ maybe_textual_hdrs = getattr (ctx .rule .attr , "textual_hdrs" , [])
102+ maybe_deps = getattr (ctx .rule .attr , "deps" , [])
103+ return LibcLibraryInfo (
104+ srcs = depset (
105+ [
106+ f
107+ for src in maybe_srcs + maybe_hdrs
108+ for f in src .files .to_list ()
109+ if f .is_source
110+ ],
111+ transitive = [
112+ dep [LibcLibraryInfo ].srcs
113+ for dep in maybe_deps
114+ if LibcLibraryInfo in dep
115+ ],
116+ ),
117+ textual_hdrs = depset (
118+ [
119+ f
120+ for hdr in maybe_textual_hdrs
121+ for f in hdr .files .to_list ()
122+ if f .is_source
123+ ],
124+ transitive = [
125+ dep [LibcLibraryInfo ].textual_hdrs
126+ for dep in maybe_deps
127+ if LibcLibraryInfo in dep
128+ ],
129+ ),
130+ )
131+
132+ _get_libc_info_aspect = aspect (
133+ implementation = _get_libc_info_aspect_impl ,
134+ attr_aspects = ["deps" ],
135+ )
136+
137+ def _get_libc_srcs_impl (ctx ):
138+ return DefaultInfo (
139+ files = depset (transitive = [
140+ fn [LibcLibraryInfo ].srcs
141+ for fn in ctx .attr .libs
142+ ]),
143+ )
144+
145+ # get_libc_srcs returns the list of sources required to build all
146+ # specified libraries.
147+ get_libc_srcs = rule (
148+ implementation = _get_libc_srcs_impl ,
149+ attrs = {
150+ "libs" : attr .label_list (
151+ mandatory = True ,
152+ aspects = [_get_libc_info_aspect ],
153+ ),
154+ },
155+ )
156+
157+ def _get_libc_textual_hdrs_impl (ctx ):
158+ return DefaultInfo (
159+ files = depset (transitive = [
160+ fn [LibcLibraryInfo ].textual_hdrs
161+ for fn in ctx .attr .libs
162+ ]),
163+ )
164+
165+ # get_libc_textual_hdrs returns the list of textual headers required to compile
166+ # all specified libraries.
167+ get_libc_textual_hdrs = rule (
168+ implementation = _get_libc_textual_hdrs_impl ,
169+ attrs = {
170+ "libs" : attr .label_list (
171+ mandatory = True ,
172+ aspects = [_get_libc_info_aspect ],
173+ ),
174+ },
175+ )
125176
126177def libc_release_library (
127178 name ,
@@ -138,15 +189,18 @@ def libc_release_library(
138189 **kwargs: Other arguments relevant to cc_library.
139190 """
140191
141- # Combine all sources into a single filegroup to avoid repeated sources error.
142- native .filegroup (
192+ get_libc_srcs (
143193 name = name + "_srcs" ,
144- srcs = [ function + "_fn_srcs" for function in libc_functions ] ,
194+ libs = libc_functions ,
145195 )
146196
197+ get_libc_textual_hdrs (
198+ name = name + "_textual_hdrs" ,
199+ libs = libc_functions ,
200+ )
147201 native .cc_library (
148202 name = name + "_textual_hdr_library" ,
149- textual_hdrs = [function + "_fn_textual_hdrs" for function in libc_functions ],
203+ textual_hdrs = [":" + name + "_textual_hdrs" ],
150204 )
151205
152206 weak_attributes = [
@@ -175,15 +229,20 @@ def libc_header_library(name, hdrs, deps = [], **kwargs):
175229 **kwargs: All other attributes relevant for the cc_library rule.
176230 """
177231
178- # Combine sources from dependencies to create a single cc_library target.
179- native .filegroup (
232+ get_libc_srcs (
180233 name = name + "_hdr_deps" ,
181- srcs = [dep + "_srcs" for dep in deps ],
234+ libs = deps ,
235+ )
236+
237+ get_libc_textual_hdrs (
238+ name = name + "_textual_hdrs" ,
239+ libs = deps ,
182240 )
183241 native .cc_library (
184242 name = name + "_textual_hdr_library" ,
185- textual_hdrs = [dep + "_textual_hdrs" for dep in deps ],
243+ textual_hdrs = [":" + name + "_textual_hdrs" ],
186244 )
245+
187246 native .cc_library (
188247 name = name ,
189248 # Technically speaking, we should put _hdr_deps in srcs, as they are
0 commit comments