2020)
2121load ("@rules_cc//cc:defs.bzl" , "CcInfo" )
2222load ("//rust:defs.bzl" , "rust_library" )
23+ load ("//rust:rust_common.bzl" , "BuildInfo" )
2324
2425# buildifier: disable=bzl-visibility
2526load ("//rust/private:rustc.bzl" , "get_linker_and_args" )
@@ -64,27 +65,100 @@ def rust_bindgen_library(
6465 if "tags" in kwargs :
6566 kwargs .pop ("tags" )
6667
68+ sub_tags = tags + ([] if "manual" in tags else ["manual" ])
69+
6770 deps = kwargs .get ("deps" ) or []
6871 if "deps" in kwargs :
6972 kwargs .pop ("deps" )
7073
74+ bindgen_kwargs = {}
75+ if "leak_symbols" in kwargs :
76+ bindgen_kwargs .update ({"leak_symbols" : kwargs .pop ("leak_symbols" )})
77+
7178 rust_bindgen (
7279 name = name + "__bindgen" ,
7380 header = header ,
7481 cc_lib = cc_lib ,
7582 bindgen_flags = bindgen_flags or [],
7683 clang_flags = clang_flags or [],
77- tags = ["manual" ],
84+ tags = sub_tags ,
85+ ** bindgen_kwargs
7886 )
7987
88+ for custom_tag in ["__bindgen" , "no-clippy" , "no-rustfmt" ]:
89+ tags = tags + ([] if custom_tag in tags else [custom_tag ])
90+
8091 rust_library (
8192 name = name ,
8293 srcs = [name + "__bindgen.rs" ],
83- tags = tags + ["__bindgen" , "noclippy " ],
84- deps = deps + [ cc_lib ] ,
94+ deps = deps + [name + "__bindgen " ],
95+ tags = tags ,
8596 ** kwargs
8697 )
8798
99+ def _generate_cc_link_build_info (ctx , cc_lib ):
100+ """Produce the eqivilant cargo_build_script providers for use in linking the library.
101+
102+ Args:
103+ ctx (ctx): The rule's context object
104+ cc_lib (Target): The `rust_bindgen.cc_lib` target.
105+
106+ Returns:
107+ The `BuildInfo` provider.
108+ """
109+ compile_data = []
110+ linker_flags = []
111+ linker_search_paths = []
112+
113+ for linker_input in cc_lib [CcInfo ].linking_context .linker_inputs .to_list ():
114+ for lib in linker_input .libraries :
115+ if lib .static_library :
116+ linker_flags .append ("-lstatic={}" .format (lib .static_library .owner .name ))
117+ linker_search_paths .append (lib .static_library .dirname )
118+ compile_data .append (lib .static_library )
119+ elif lib .pic_static_library :
120+ linker_flags .append ("-lstatic={}" .format (lib .pic_static_library .owner .name ))
121+ linker_search_paths .append (lib .pic_static_library .dirname )
122+ compile_data .append (lib .pic_static_library )
123+
124+ linker_flags .extend (linker_input .user_link_flags )
125+
126+ if not compile_data :
127+ fail ("No static libraries found in {}" .format (
128+ cc_lib .label ,
129+ ))
130+
131+ empty_file = ctx .actions .declare_file ("{}.empty" .format (ctx .label .name ))
132+ ctx .actions .write (
133+ output = empty_file ,
134+ content = "" ,
135+ )
136+
137+ link_flags = ctx .actions .declare_file ("{}.link_flags" .format (ctx .label .name ))
138+ ctx .actions .write (
139+ output = link_flags ,
140+ content = "\n " .join (linker_flags ),
141+ )
142+
143+ link_search_paths = ctx .actions .declare_file ("{}.link_search_paths" .format (ctx .label .name ))
144+ ctx .actions .write (
145+ output = link_search_paths ,
146+ content = "\n " .join ([
147+ "-Lnative=${{pwd}}/{}" .format (path )
148+ for path in depset (linker_search_paths ).to_list ()
149+ ]),
150+ )
151+
152+ return BuildInfo (
153+ out_dir = None ,
154+ rustc_env = empty_file ,
155+ dep_env = empty_file ,
156+ flags = empty_file ,
157+ link_flags = link_flags ,
158+ link_search_paths = link_search_paths ,
159+ compile_data = depset (compile_data ),
160+ )
161+
88162def _rust_bindgen_impl (ctx ):
89163 # nb. We can't grab the cc_library`s direct headers, so a header must be provided.
90164 cc_lib = ctx .attr .cc_lib
@@ -200,6 +274,19 @@ def _rust_bindgen_impl(ctx):
200274 tools = tools ,
201275 )
202276
277+ if ctx .attr .leak_symbols :
278+ providers = [cc_common .merge_cc_infos (
279+ direct_cc_infos = [cc_lib [CcInfo ]],
280+ )]
281+ else :
282+ providers = [_generate_cc_link_build_info (ctx , cc_lib )]
283+
284+ return providers + [
285+ OutputGroupInfo (
286+ bindgen_bindings = depset ([output ]),
287+ ),
288+ ]
289+
203290rust_bindgen = rule (
204291 doc = "Generates a rust source file from a cc_library and a header." ,
205292 implementation = _rust_bindgen_impl ,
@@ -220,6 +307,13 @@ rust_bindgen = rule(
220307 allow_single_file = True ,
221308 mandatory = True ,
222309 ),
310+ "leak_symbols" : attr .bool (
311+ doc = (
312+ "If True, `cc_lib` will be exposed and linked into all downstream consumers of the target vs. the " +
313+ "`rust_library` directly consuming it."
314+ ),
315+ default = False ,
316+ ),
223317 "_cc_toolchain" : attr .label (
224318 default = Label ("@bazel_tools//tools/cpp:current_cc_toolchain" ),
225319 ),
0 commit comments