Skip to content

Commit 31d8c8a

Browse files
authored
Fix NoneType exception for interface dependencies. (#3563)
Before this change any dependency with `CcInfo` which did not contain static or dynamic libraries (e.g. an interface library which has it's own fields for storing the underlying files) would result in the following error: ``` ERROR: /Users/user/Code/rules_rust/test/unit/cc_info/BUILD.bazel:4:19: in rust_shared_library rule //test/unit/cc_info:rust_dylib_with_interface_lib_dep: Traceback (most recent call last): File "/Users/user/Code/rules_rust/rust/private/rust.bzl", line 126, column 32, in _rust_shared_library_impl return _rust_library_common(ctx, "cdylib") File "/Users/user/Code/rules_rust/rust/private/rust.bzl", line 190, column 32, in _rust_library_common return rustc_compile_action( File "/Users/user/Code/rules_rust/rust/private/rustc.bzl", line 1541, column 41, in rustc_compile_action dynamic_libraries = ctx.runfiles(files = [ Error in runfiles: at index 0 of files, got element of type NoneType, want File ``` This pull request fixes this exception.
1 parent 526b33d commit 31d8c8a

File tree

2 files changed

+131
-2
lines changed

2 files changed

+131
-2
lines changed

rust/private/rustc.bzl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1552,7 +1552,7 @@ def rustc_compile_action(
15521552
if CcInfo in dep
15531553
for linker_input in dep[CcInfo].linking_context.linker_inputs.to_list()
15541554
for library_to_link in linker_input.libraries
1555-
if _is_dylib(library_to_link)
1555+
if _is_dylib(library_to_link) and library_to_link.dynamic_library
15561556
])
15571557
transitive_runfiles.append(dynamic_libraries)
15581558
runfiles = runfiles.merge_all(transitive_runfiles)
@@ -1688,6 +1688,14 @@ def _get_std_and_alloc_info(ctx, toolchain, crate_info):
16881688
return toolchain.libstd_and_allocator_ccinfo
16891689

16901690
def _is_dylib(dep):
1691+
"""Determine if the dependency represents a dynamic library.
1692+
1693+
Args:
1694+
dep (LibraryToLink): The `LibraryToLink` component of a target (e.g. from `CcInfo`)
1695+
1696+
Returns:
1697+
bool: True if the dependency should be thought of as a dynamic library.
1698+
"""
16911699
return not bool(dep.static_library or dep.pic_static_library)
16921700

16931701
def _collect_nonstatic_linker_inputs(cc_info):

test/unit/cc_info/cc_info_test.bzl

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Unittests for rust rules."""
22

33
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
4-
load("@rules_cc//cc:defs.bzl", "cc_library")
4+
load("@rules_cc//cc:defs.bzl", "cc_import", "cc_library")
55
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
66
load("//rust:defs.bzl", "rust_binary", "rust_common", "rust_library", "rust_proc_macro", "rust_shared_library", "rust_static_library")
77

@@ -115,6 +115,68 @@ proc_macro_does_not_provide_cc_info_test = analysistest.make(_proc_macro_does_no
115115

116116
crate_group_info_provides_cc_info_test = analysistest.make(_crate_group_info_provides_cc_info_test_impl)
117117

118+
def _is_cc_interface_library_test_impl(ctx):
119+
env = analysistest.begin(ctx)
120+
tut = analysistest.target_under_test(env)
121+
122+
cc_info = tut[CcInfo]
123+
124+
linker_inputs = cc_info.linking_context.linker_inputs.to_list()
125+
asserts.true(
126+
env,
127+
len(linker_inputs) > 0,
128+
"No linker inputs provided by {}".format(tut.label),
129+
)
130+
131+
for linker_input in linker_inputs:
132+
asserts.true(
133+
env,
134+
len(linker_input.libraries) > 0,
135+
"No linker input libraries provided by {}".format(tut.label),
136+
)
137+
138+
for library_to_link in linker_input.libraries:
139+
asserts.true(
140+
env,
141+
library_to_link.dynamic_library == None,
142+
"dynamic_library unexpectedly provided by {}".format(tut.label),
143+
)
144+
asserts.true(
145+
env,
146+
library_to_link.static_library == None,
147+
"static_library unexpectedly provided by {}".format(tut.label),
148+
)
149+
asserts.true(
150+
env,
151+
library_to_link.pic_static_library == None,
152+
"pic_static_library unexpectedly provided by {}".format(tut.label),
153+
)
154+
asserts.true(
155+
env,
156+
library_to_link.interface_library != None,
157+
"No interface libraries provided by {}".format(tut.label),
158+
)
159+
return analysistest.end(env)
160+
161+
is_cc_interface_library_test = analysistest.make(_is_cc_interface_library_test_impl)
162+
163+
def _build_test(ctx):
164+
env = analysistest.begin(ctx)
165+
tut = analysistest.target_under_test(env)
166+
if rust_common.crate_info in tut:
167+
crate_info = tut[rust_common.crate_info]
168+
else:
169+
crate_info = tut[rust_common.test_crate_info].crate
170+
asserts.true(
171+
env,
172+
bool(crate_info.output),
173+
"No output created by {}".format(tut.label),
174+
)
175+
176+
return analysistest.end(env)
177+
178+
build_test = analysistest.make(_build_test)
179+
118180
def _rust_cc_injection_impl(ctx):
119181
dep_variant_info = rust_common.dep_variant_info(
120182
cc_info = ctx.attr.cc_dep[CcInfo],
@@ -136,6 +198,22 @@ rust_cc_injection = rule(
136198
implementation = _rust_cc_injection_impl,
137199
)
138200

201+
def _rust_output_extractor_impl(ctx):
202+
dep = ctx.attr.dep
203+
crate_info = dep[rust_common.test_crate_info].crate
204+
output = crate_info.output
205+
206+
return [DefaultInfo(
207+
files = depset([output]),
208+
)]
209+
210+
rust_output_extractor = rule(
211+
implementation = _rust_output_extractor_impl,
212+
attrs = {
213+
"dep": attr.label(),
214+
},
215+
)
216+
139217
def _cc_info_test():
140218
rust_library(
141219
name = "rlib",
@@ -185,13 +263,41 @@ def _cc_info_test():
185263
cc_dep = ":cc_lib",
186264
)
187265

266+
rust_output_extractor(
267+
name = "rust_output_extractor",
268+
dep = select({
269+
"@platforms//os:windows": ":staticlib",
270+
"//conditions:default": ":cdylib",
271+
}),
272+
)
273+
274+
cc_import(
275+
name = "cc_import",
276+
interface_library = ":rust_output_extractor",
277+
system_provided = True,
278+
)
279+
188280
rust_library(
189281
name = "rust_lib_with_cc_lib_injected",
190282
srcs = ["foo.rs"],
191283
deps = [":cc_lib_injected"],
192284
edition = "2018",
193285
)
194286

287+
rust_library(
288+
name = "rust_lib_with_interface_lib_dep",
289+
srcs = ["foo.rs"],
290+
deps = [":cc_import"],
291+
edition = "2018",
292+
)
293+
294+
rust_shared_library(
295+
name = "rust_dylib_with_interface_lib_dep",
296+
srcs = ["foo.rs"],
297+
deps = [":cc_import"],
298+
edition = "2018",
299+
)
300+
195301
rlib_provides_cc_info_test(
196302
name = "rlib_provides_cc_info_test",
197303
target_under_test = ":rlib",
@@ -220,6 +326,18 @@ def _cc_info_test():
220326
name = "crate_group_info_provides_cc_info_test",
221327
target_under_test = ":rust_lib_with_cc_lib_injected",
222328
)
329+
is_cc_interface_library_test(
330+
name = "is_cc_interface_library_test",
331+
target_under_test = ":cc_import",
332+
)
333+
build_test(
334+
name = "rust_lib_with_interface_lib_dep_test",
335+
target_under_test = ":rust_lib_with_interface_lib_dep",
336+
)
337+
build_test(
338+
name = "rust_dylib_with_interface_lib_dep_test",
339+
target_under_test = ":rust_dylib_with_interface_lib_dep",
340+
)
223341

224342
def cc_info_test_suite(name):
225343
"""Entry-point macro called from the BUILD file.
@@ -239,5 +357,8 @@ def cc_info_test_suite(name):
239357
":proc_macro_does_not_provide_cc_info_test",
240358
":bin_does_not_provide_cc_info_test",
241359
":crate_group_info_provides_cc_info_test",
360+
":is_cc_interface_library_test",
361+
":rust_lib_with_interface_lib_dep_test",
362+
":rust_dylib_with_interface_lib_dep_test",
242363
],
243364
)

0 commit comments

Comments
 (0)