@@ -102,26 +102,41 @@ def get_compilation_mode_opts(ctx, toolchain):
102
102
103
103
return toolchain .compilation_mode_opts [comp_mode ]
104
104
105
- def collect_deps (label , deps , proc_macro_deps , aliases , make_rust_providers_target_independent = False ):
105
+ def _are_linkstamps_supported (feature_configuration , has_grep_includes ):
106
+ # Are linkstamps supported by the C++ toolchain?
107
+ return (cc_common .is_enabled (feature_configuration = feature_configuration , feature_name = "linkstamps" ) and
108
+ # Is Bazel recent enough to support Starlark linkstamps?
109
+ hasattr (cc_common , "register_linkstamp_compile_action" ) and
110
+ # The current rule doesn't define _grep_includes attribute; this
111
+ # attribute is required for compiling linkstamps.
112
+ has_grep_includes )
113
+
114
+ def collect_deps (label , deps , proc_macro_deps , aliases , are_linkstamps_supported = False , make_rust_providers_target_independent = False ):
106
115
"""Walks through dependencies and collects the transitive dependencies.
107
116
108
117
Args:
109
118
label (str): Label of the current target.
110
119
deps (list): The deps from ctx.attr.deps.
111
120
proc_macro_deps (list): The proc_macro deps from ctx.attr.proc_macro_deps.
112
121
aliases (dict): A dict mapping aliased targets to their actual Crate information.
122
+ are_linkstamps_supported (bool): Whether the current rule and the toolchain support building linkstamps.
113
123
make_rust_providers_target_independent (bool): Whether
114
124
--incompatible_make_rust_providers_target_independent has been flipped.
115
125
116
126
Returns:
117
- tuple: Returns a tuple (DepInfo, BuildInfo) of providers.
127
+ tuple: Returns a tuple of:
128
+ DepInfo,
129
+ BuildInfo,
130
+ linkstamps (depset[CcLinkstamp]): A depset of CcLinkstamps that need to be compiled and linked into all linked binaries.
131
+
118
132
"""
119
133
direct_crates = []
120
134
transitive_crates = []
121
135
transitive_noncrates = []
122
136
transitive_noncrate_libs = []
123
137
transitive_build_infos = []
124
138
build_info = None
139
+ linkstamps = []
125
140
126
141
aliases = {k .label : v for k , v in aliases .items ()}
127
142
for dep in depset (transitive = [deps , proc_macro_deps ]).to_list ():
@@ -159,6 +174,8 @@ def collect_deps(label, deps, proc_macro_deps, aliases, make_rust_providers_targ
159
174
libs = [get_preferred_artifact (lib ) for li in linker_inputs for lib in li .libraries ]
160
175
transitive_noncrate_libs .append (depset (libs ))
161
176
transitive_noncrates .append (cc_info .linking_context .linker_inputs )
177
+ if are_linkstamps_supported :
178
+ linkstamps .append (cc_info .linking_context .linkstamps ())
162
179
elif dep_build_info :
163
180
if build_info :
164
181
fail ("Several deps are providing build information, " +
@@ -188,6 +205,7 @@ def collect_deps(label, deps, proc_macro_deps, aliases, make_rust_providers_targ
188
205
dep_env = build_info .dep_env if build_info else None ,
189
206
),
190
207
build_info ,
208
+ depset (transitive = linkstamps ),
191
209
)
192
210
193
211
def _get_crate_and_dep_info (dep ):
@@ -305,6 +323,7 @@ def collect_inputs(
305
323
ctx ,
306
324
file ,
307
325
files ,
326
+ linkstamps ,
308
327
toolchain ,
309
328
cc_toolchain ,
310
329
feature_configuration ,
@@ -317,6 +336,7 @@ def collect_inputs(
317
336
ctx (ctx): The rule's context object.
318
337
file (struct): A struct containing files defined in label type attributes marked as `allow_single_file`.
319
338
files (list): A list of all inputs (`ctx.files`).
339
+ linkstamps (depset): A depset of CcLinkstamps that need to be compiled and linked into all linked binaries.
320
340
toolchain (rust_toolchain): The current `rust_toolchain`.
321
341
cc_toolchain (CcToolchainInfo): The current `cc_toolchain`.
322
342
feature_configuration (FeatureConfiguration): Feature configuration to be queried.
@@ -371,38 +391,33 @@ def collect_inputs(
371
391
],
372
392
)
373
393
374
- if (crate_info .type in ("bin" , "cdylib" ) and
375
- # Are linkstamps supported by the C++ toolchain?
376
- cc_common .is_enabled (feature_configuration = feature_configuration , feature_name = "linkstamps" ) and
377
- # Is Bazel recent enough to support Starlark linkstamps?
378
- hasattr (cc_common , "register_linkstamp_compile_action" ) and
379
- # The current rule doesn't define _grep_includes attribute; this
380
- # attribute is required for compiling linkstamps.
381
- hasattr (ctx .attr , "_grep_includes" )):
382
- for dep in ctx .attr .deps :
383
- if CcInfo in dep and dep [CcInfo ].linking_context :
384
- linking_context = dep [CcInfo ].linking_context
385
- for linkstamp in linking_context .linkstamps ().to_list ():
386
- # The linkstamp output path is based on the binary crate
387
- # name and the input linkstamp path. This is to disambiguate
388
- # the linkstamp outputs produced by multiple binary crates
389
- # that depend on the same linkstamp. We use the same pattern
390
- # for the output name as the one used by native cc rules.
391
- out_name = "_objs/" + crate_info .output .basename + "/" + linkstamp .file ().path [:- len (linkstamp .file ().extension )] + "o"
392
- linkstamp_out = ctx .actions .declare_file (out_name )
393
- linkstamp_outs .append (linkstamp_out )
394
- cc_common .register_linkstamp_compile_action (
395
- actions = ctx .actions ,
396
- cc_toolchain = cc_toolchain ,
397
- feature_configuration = feature_configuration ,
398
- grep_includes = ctx .file ._grep_includes ,
399
- source_file = linkstamp .file (),
400
- output_file = linkstamp_out ,
401
- compilation_inputs = linkstamp .hdrs (),
402
- inputs_for_validation = nolinkstamp_compile_inputs ,
403
- label_replacement = str (ctx .label ),
404
- output_replacement = crate_info .output .path ,
405
- )
394
+ if crate_info .type in ("bin" , "cdylib" ):
395
+ # There is no other way to register an action for each member of a depset than
396
+ # flattening the depset as of 2021-10-12. Luckily, usually there is only one linkstamp
397
+ # in a build, and we only flatten the list on binary targets that perform transitive linking,
398
+ # so it's extremely unlikely that this call to `to_list()` will ever be a performance
399
+ # problem.
400
+ for linkstamp in linkstamps .to_list ():
401
+ # The linkstamp output path is based on the binary crate
402
+ # name and the input linkstamp path. This is to disambiguate
403
+ # the linkstamp outputs produced by multiple binary crates
404
+ # that depend on the same linkstamp. We use the same pattern
405
+ # for the output name as the one used by native cc rules.
406
+ out_name = "_objs/" + crate_info .output .basename + "/" + linkstamp .file ().path [:- len (linkstamp .file ().extension )] + "o"
407
+ linkstamp_out = ctx .actions .declare_file (out_name )
408
+ linkstamp_outs .append (linkstamp_out )
409
+ cc_common .register_linkstamp_compile_action (
410
+ actions = ctx .actions ,
411
+ cc_toolchain = cc_toolchain ,
412
+ feature_configuration = feature_configuration ,
413
+ grep_includes = ctx .file ._grep_includes ,
414
+ source_file = linkstamp .file (),
415
+ output_file = linkstamp_out ,
416
+ compilation_inputs = linkstamp .hdrs (),
417
+ inputs_for_validation = nolinkstamp_compile_inputs ,
418
+ label_replacement = str (ctx .label ),
419
+ output_replacement = crate_info .output .path ,
420
+ )
406
421
407
422
compile_inputs = depset (
408
423
linkstamp_outs ,
@@ -654,18 +669,23 @@ def rustc_compile_action(
654
669
655
670
make_rust_providers_target_independent = toolchain ._incompatible_make_rust_providers_target_independent
656
671
657
- dep_info , build_info = collect_deps (
672
+ dep_info , build_info , linkstamps = collect_deps (
658
673
label = ctx .label ,
659
674
deps = crate_info .deps ,
660
675
proc_macro_deps = crate_info .proc_macro_deps ,
661
676
aliases = crate_info .aliases ,
677
+ are_linkstamps_supported = _are_linkstamps_supported (
678
+ feature_configuration = feature_configuration ,
679
+ has_grep_includes = hasattr (ctx .attr , "_grep_includes" ),
680
+ ),
662
681
make_rust_providers_target_independent = make_rust_providers_target_independent ,
663
682
)
664
683
665
684
compile_inputs , out_dir , build_env_files , build_flags_files , linkstamp_outs = collect_inputs (
666
685
ctx = ctx ,
667
686
file = ctx .file ,
668
687
files = ctx .files ,
688
+ linkstamps = linkstamps ,
669
689
toolchain = toolchain ,
670
690
cc_toolchain = cc_toolchain ,
671
691
feature_configuration = feature_configuration ,
0 commit comments