Skip to content

Commit 8798aca

Browse files
rust_toolchain: expand Make variables in flags (#3640)
This allows a user to say: ```bzl rust_register_toolchains( # or rust_toolchain( extra_rustc_flags = { "aarch64-unknown-linux-gnu": [ "--codegen=link-arg=-B$(RUST_SYSROOT)/lib/rustlib/aarch64-unknown-linux-gnu/bin/gcc-ld", "--codegen=link-arg=-fuse-ld=lld", ], "x86_64-unknown-linux-gnu": [ "--codegen=link-arg=-B$(RUST_SYSROOT)/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld", "--codegen=link-arg=-fuse-ld=lld", ], }, ) ``` bringing us one step closer to #3602. This is **technically** an incompatible change: if a user currently sets a `extra_rustc_flags` containing `$`, they now need to escape `$` to `$$` pursuant to how [Make variable expansion](https://bazel.build/reference/be/make-variables) works in Bazel. However, I would assume this is rare. Inspired by #3540 – cc @krasimirgg
1 parent 5900faa commit 8798aca

File tree

3 files changed

+54
-30
lines changed

3 files changed

+54
-30
lines changed

rust/repositories.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,11 @@ def rust_toolchain_repository(
652652
dev_components (bool, optional): Whether to download the rustc-dev components.
653653
Requires version to be "nightly". Defaults to False.
654654
extra_rustc_flags (list, optional): Extra flags to pass to rustc in non-exec configuration.
655+
Subject to Make variable expansion with respect to RUST_SYSROOT,
656+
RUST_SYSROOT_SHORT, RUSTC, etc.
655657
extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration.
658+
Subject to Make variable expansion with respect to RUST_SYSROOT,
659+
RUST_SYSROOT_SHORT, RUSTC, etc.
656660
opt_level (dict, optional): Optimization level config for this toolchain.
657661
strip_level (dict, optional): Strip level config for this toolchain.
658662
sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See

rust/toolchain.bzl

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -533,11 +533,20 @@ def _generate_sysroot(
533533
def _experimental_use_cc_common_link(ctx):
534534
return ctx.attr.experimental_use_cc_common_link[BuildSettingInfo].value
535535

536-
def _expand_flags(ctx, flags, targets):
536+
def _expand_flags(ctx, attr_name, targets, make_variables):
537537
targets = deduplicate(targets)
538538
expanded_flags = []
539+
flags = getattr(ctx.attr, attr_name)
539540
for flag in flags:
540-
expanded_flags.append(ctx.expand_location(flag, targets))
541+
# Fast-path - both location expansions and make vars have a `$` so we
542+
# can short-circuit if $ doesn't exist.
543+
if "$" in flag:
544+
# The ordering here matters. If we expand Make variables first, then
545+
# "$(location //foo)" would have to be written as "$$(location //foo)",
546+
# which is inconsistent with how Bazel builtin rules work.
547+
flag = ctx.expand_location(flag, targets)
548+
flag = ctx.expand_make_variables(attr_name, flag, make_variables)
549+
expanded_flags.append(flag)
541550
return expanded_flags
542551

543552
def _rust_toolchain_impl(ctx):
@@ -594,29 +603,6 @@ def _rust_toolchain_impl(ctx):
594603
llvm_tools = ctx.attr.llvm_tools,
595604
)
596605

597-
expanded_stdlib_linkflags = _expand_flags(ctx, ctx.attr.stdlib_linkflags, rust_std[rust_common.stdlib_info].srcs)
598-
expanded_extra_rustc_flags = _expand_flags(ctx, ctx.attr.extra_rustc_flags, rust_std[rust_common.stdlib_info].srcs)
599-
expanded_extra_exec_rustc_flags = _expand_flags(ctx, ctx.attr.extra_exec_rustc_flags, rust_std[rust_common.stdlib_info].srcs)
600-
601-
linking_context = cc_common.create_linking_context(
602-
linker_inputs = depset([
603-
cc_common.create_linker_input(
604-
owner = ctx.label,
605-
user_link_flags = depset(expanded_stdlib_linkflags),
606-
),
607-
]),
608-
)
609-
610-
# Contains linker flags needed to link Rust standard library.
611-
# These need to be added to linker command lines when the linker is not rustc
612-
# (rustc does this automatically). Linker flags wrapped in an otherwise empty
613-
# `CcInfo` to provide the flags in a way that doesn't duplicate them per target
614-
# providing a `CcInfo`.
615-
stdlib_linkflags_cc_info = CcInfo(
616-
compilation_context = cc_common.create_compilation_context(),
617-
linking_context = linking_context,
618-
)
619-
620606
# Determine the path and short_path of the sysroot
621607
sysroot_path = sysroot.sysroot_anchor.dirname
622608
sysroot_short_path, _, _ = sysroot.sysroot_anchor.short_path.rpartition("/")
@@ -642,6 +628,29 @@ def _rust_toolchain_impl(ctx):
642628

643629
make_variable_info = platform_common.TemplateVariableInfo(make_variables)
644630

631+
expanded_stdlib_linkflags = _expand_flags(ctx, "stdlib_linkflags", rust_std[rust_common.stdlib_info].srcs, make_variables)
632+
expanded_extra_rustc_flags = _expand_flags(ctx, "extra_rustc_flags", rust_std[rust_common.stdlib_info].srcs, make_variables)
633+
expanded_extra_exec_rustc_flags = _expand_flags(ctx, "extra_exec_rustc_flags", rust_std[rust_common.stdlib_info].srcs, make_variables)
634+
635+
linking_context = cc_common.create_linking_context(
636+
linker_inputs = depset([
637+
cc_common.create_linker_input(
638+
owner = ctx.label,
639+
user_link_flags = depset(expanded_stdlib_linkflags),
640+
),
641+
]),
642+
)
643+
644+
# Contains linker flags needed to link Rust standard library.
645+
# These need to be added to linker command lines when the linker is not rustc
646+
# (rustc does this automatically). Linker flags wrapped in an otherwise empty
647+
# `CcInfo` to provide the flags in a way that doesn't duplicate them per target
648+
# providing a `CcInfo`.
649+
stdlib_linkflags_cc_info = CcInfo(
650+
compilation_context = cc_common.create_compilation_context(),
651+
linking_context = linking_context,
652+
)
653+
645654
exec_triple = triple(ctx.attr.exec_triple)
646655

647656
if not exec_triple.system:
@@ -843,10 +852,10 @@ rust_toolchain = rule(
843852
doc = "Label to a boolean build setting that controls whether cc_common.link is used to link rust binaries.",
844853
),
845854
"extra_exec_rustc_flags": attr.string_list(
846-
doc = "Extra flags to pass to rustc in exec configuration. Subject to location expansion with respect to the srcs of the `rust_std` attribute.",
855+
doc = "Extra flags to pass to rustc in exec configuration. Subject to location expansion with respect to the srcs of the `rust_std` attribute. Subject to Make variable expansion with respect to RUST_SYSROOT, RUST_SYSROOT_SHORT, RUSTC, etc.",
847856
),
848857
"extra_rustc_flags": attr.string_list(
849-
doc = "Extra flags to pass to rustc in non-exec configuration. Subject to location expansion with respect to the srcs of the `rust_std` attribute.",
858+
doc = "Extra flags to pass to rustc in non-exec configuration. Subject to location expansion with respect to the srcs of the `rust_std` attribute. Subject to Make variable expansion with respect to RUST_SYSROOT, RUST_SYSROOT_SHORT, RUSTC, etc.",
850859
),
851860
"extra_rustc_flags_for_crate_types": attr.string_list_dict(
852861
doc = "Extra flags to pass to rustc based on crate type",
@@ -923,7 +932,8 @@ rust_toolchain = rule(
923932
doc = (
924933
"Additional linker flags to use when Rust standard library is linked by a C++ linker " +
925934
"(rustc will deal with these automatically). Subject to location expansion with respect " +
926-
"to the srcs of the `rust_std` attribute."
935+
"to the srcs of the `rust_std` attribute. Subject to Make variable expansion with respect " +
936+
"to RUST_SYSROOT, RUST_SYSROOT_SHORT, RUSTC, etc."
927937
),
928938
mandatory = True,
929939
),

test/unit/toolchain/toolchain_test.bzl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ def _toolchain_location_expands_linkflags_impl(ctx):
4444
"test:test/unit/toolchain/config.txt",
4545
toolchain_info.stdlib_linkflags.linking_context.linker_inputs.to_list()[0].user_link_flags[0],
4646
)
47+
asserts.equals(
48+
env,
49+
"test:sysroot=" + toolchain_info.sysroot,
50+
toolchain_info.stdlib_linkflags.linking_context.linker_inputs.to_list()[0].user_link_flags[1],
51+
)
4752

4853
return analysistest.end(env)
4954

@@ -56,6 +61,11 @@ def _toolchain_location_expands_extra_rustc_flags_impl(ctx):
5661
"extra_rustc_flags:test/unit/toolchain/config.txt",
5762
toolchain_info.extra_rustc_flags[0],
5863
)
64+
asserts.equals(
65+
env,
66+
"extra_rustc_flags:sysroot=" + toolchain_info.sysroot,
67+
toolchain_info.extra_rustc_flags[1],
68+
)
5969

6070
return analysistest.end(env)
6171

@@ -173,8 +183,8 @@ def _define_test_targets():
173183
rust_std = ":std_libs",
174184
rustc = ":mock_rustc",
175185
staticlib_ext = ".a",
176-
stdlib_linkflags = ["test:$(location :stdlib_srcs)"],
177-
extra_rustc_flags = ["extra_rustc_flags:$(location :stdlib_srcs)"],
186+
stdlib_linkflags = ["test:$(location :stdlib_srcs)", "test:sysroot=$(RUST_SYSROOT)"],
187+
extra_rustc_flags = ["extra_rustc_flags:$(location :stdlib_srcs)", "extra_rustc_flags:sysroot=$(RUST_SYSROOT)"],
178188
target_json = encoded_target_json,
179189
)
180190

0 commit comments

Comments
 (0)