Skip to content

Add a build setting to announce crate scope #3408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions rust/private/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@bazel_skylib//rules:common_settings.bzl", "string_setting")
load("//rust/private:rust_analyzer.bzl", "rust_analyzer_detect_sysroot")
load("//rust/private:rustc.bzl", "is_proc_macro_dep", "is_proc_macro_dep_enabled")
load("//rust/private:stamp.bzl", "stamp_build_setting")
Expand Down Expand Up @@ -52,6 +53,24 @@ is_proc_macro_dep_enabled(
visibility = ["//visibility:public"],
)

# The scope of the crate being built.
#
# This setting is not used internally. It announces to the dependencies of rust crates
# (including toolchains) how their outputs are being used, to allow e.g. passing different
# copts to a cc_library when it is part of a crate or a procedure macro.
#
# We specialize proc macro, because it must be ABI compatible with rustc itself.
string_setting(
name = "crate_scope",
build_setting_default = "none",
values = [
"none", # Not building a rust crate or a dep of rust crate
"proc_macro", # Building a proc macro or a dep of proc macro
"regular", # Building a regular crate or a (non-proc-macro) dep of such
],
visibility = ["//rust/settings:__pkg__"],
)

rust_analyzer_detect_sysroot(
name = "rust_analyzer_detect_sysroot",
visibility = ["//visibility:public"],
Expand Down
86 changes: 55 additions & 31 deletions rust/private/rust.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,34 @@ def _stamp_attribute(default_value):
values = [1, 0, -1],
)

def _crate_scope_transition_impl(settings, attr):
if hasattr(attr, "_change_crate_scope"):
return {"//rust/private:crate_scope": attr._change_crate_scope}
if settings["//rust/private:crate_scope"] == "proc_macro":
# the whole transitive closure of a proc_macro should be the proc_macro scope,
# except that it is reset by either the _change_crate_scope attr above or the
# _crate_scope_reset_transition below.
return {"//rust/private:crate_scope": "proc_macro"}
return {"//rust/private:crate_scope": "regular"}

_crate_scope_transition_inputs = ["//rust/private:crate_scope"]
_crate_scope_transition_outputs = ["//rust/private:crate_scope"]

_crate_scope_transition = transition(
implementation = _crate_scope_transition_impl,
inputs = _crate_scope_transition_inputs,
outputs = _crate_scope_transition_outputs,
)

def _crate_scope_reset_transition_impl(_settings, _attr):
return {"//rust/private:crate_scope": "none"}

_crate_scope_reset_transition = transition(
implementation = _crate_scope_reset_transition_impl,
inputs = [],
outputs = _crate_scope_transition_outputs,
)

# Internal attributes core to Rustc actions.
RUSTC_ATTRS = {
"_error_format": attr.label(
Expand Down Expand Up @@ -591,6 +619,7 @@ _common_attrs = {
macro.
"""),
allow_files = True,
cfg = _crate_scope_reset_transition,
),
"crate_features": attr.string_list(
doc = dedent("""\
Expand All @@ -617,6 +646,7 @@ _common_attrs = {
or the single file in `srcs` if `srcs` contains only one file.
"""),
allow_single_file = [".rs"],
cfg = _crate_scope_reset_transition,
),
"data": attr.label_list(
doc = dedent("""\
Expand All @@ -627,6 +657,7 @@ _common_attrs = {
in the runfiles.
"""),
allow_files = True,
cfg = _crate_scope_reset_transition,
),
"deps": attr.label_list(
doc = dedent("""\
Expand Down Expand Up @@ -719,6 +750,9 @@ _common_attrs = {
doc = "A version to inject in the cargo environment variable.",
default = "0.0.0",
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
"_stamp_flag": attr.label(
doc = "A setting used to determine whether or not the `--stamp` flag is enabled",
default = Label("//rust/private:stamp"),
Expand Down Expand Up @@ -828,6 +862,7 @@ rust_library = rule(
),
},
fragments = ["cpp"],
cfg = _crate_scope_transition,
toolchains = [
str(Label("//rust:toolchain_type")),
"@bazel_tools//tools/cpp:toolchain_type",
Expand Down Expand Up @@ -901,16 +936,16 @@ rust_library = rule(
def _rust_static_library_transition_impl(settings, attr):
return {
"//command_line_option:platforms": str(attr.platform) if attr.platform else settings["//command_line_option:platforms"],
}
} | _crate_scope_transition_impl(settings, attr)

_rust_static_library_transition = transition(
implementation = _rust_static_library_transition_impl,
inputs = [
"//command_line_option:platforms",
],
] + _crate_scope_transition_inputs,
outputs = [
"//command_line_option:platforms",
],
] + _crate_scope_transition_outputs,
)

rust_static_library = rule(
Expand All @@ -920,9 +955,6 @@ rust_static_library = rule(
doc = "Optional platform to transition the static library to.",
default = None,
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
fragments = ["cpp"],
cfg = _rust_static_library_transition,
Expand Down Expand Up @@ -950,16 +982,16 @@ rust_static_library = rule(
def _rust_shared_library_transition_impl(settings, attr):
return {
"//command_line_option:platforms": str(attr.platform) if attr.platform else settings["//command_line_option:platforms"],
}
} | _crate_scope_transition_impl(settings, attr)

_rust_shared_library_transition = transition(
implementation = _rust_shared_library_transition_impl,
inputs = [
"//command_line_option:platforms",
],
] + _crate_scope_transition_inputs,
outputs = [
"//command_line_option:platforms",
],
] + _crate_scope_transition_outputs,
)

rust_shared_library = rule(
Expand All @@ -969,9 +1001,6 @@ rust_shared_library = rule(
doc = "Optional platform to transition the shared library to.",
default = None,
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
"_use_grep_includes": attr.bool(default = True),
},
fragments = ["cpp"],
Expand Down Expand Up @@ -1018,9 +1047,7 @@ rust_proc_macro = rule(
# https://docs.bazel.build/versions/main/skylark/config.html#user-defined-transitions.
attrs = dict(
_common_attrs.items(),
_allowlist_function_transition = attr.label(
default = Label("//tools/allowlists/function_transition_allowlist"),
),
_change_crate_scope = attr.string(default = "proc_macro"),
deps = attr.label_list(
doc = dedent("""\
List of other libraries to be linked to this library target.
Expand All @@ -1032,6 +1059,7 @@ rust_proc_macro = rule(
),
),
fragments = ["cpp"],
cfg = _crate_scope_transition,
toolchains = [
str(Label("//rust:toolchain_type")),
"@bazel_tools//tools/cpp:toolchain_type",
Expand Down Expand Up @@ -1074,6 +1102,7 @@ _rust_binary_attrs = {
Link script to forward into linker via rustc options.
"""),
allow_single_file = True,
cfg = _crate_scope_reset_transition,
),
"out_binary": attr.bool(
doc = (
Expand All @@ -1090,16 +1119,16 @@ _rust_binary_attrs = {
def _rust_binary_transition_impl(settings, attr):
return {
"//command_line_option:platforms": str(attr.platform) if attr.platform else settings["//command_line_option:platforms"],
}
} | _crate_scope_transition_impl(settings, attr)

_rust_binary_transition = transition(
implementation = _rust_binary_transition_impl,
inputs = [
"//command_line_option:platforms",
],
] + _crate_scope_transition_inputs,
outputs = [
"//command_line_option:platforms",
],
] + _crate_scope_transition_outputs,
)

rust_binary = rule(
Expand All @@ -1110,9 +1139,6 @@ rust_binary = rule(
doc = "Optional platform to transition the binary to.",
default = None,
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
executable = True,
fragments = ["cpp"],
Expand Down Expand Up @@ -1252,9 +1278,7 @@ rust_binary_without_process_wrapper = rule(
doc = "Optional platform to transition the binary to.",
default = None,
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
"_change_crate_scope": attr.string(default = "regular"),
}),
executable = True,
fragments = ["cpp"],
Expand All @@ -1268,8 +1292,11 @@ rust_binary_without_process_wrapper = rule(
rust_library_without_process_wrapper = rule(
implementation = _rust_library_impl,
provides = COMMON_PROVIDERS,
attrs = dict(_common_attrs_for_binary_without_process_wrapper(_common_attrs).items()),
attrs = _common_attrs_for_binary_without_process_wrapper(_common_attrs | {
"_change_crate_scope": attr.string(default = "regular"),
}),
fragments = ["cpp"],
cfg = _crate_scope_transition,
toolchains = [
str(Label("//rust:toolchain_type")),
"@bazel_tools//tools/cpp:toolchain_type",
Expand All @@ -1279,16 +1306,16 @@ rust_library_without_process_wrapper = rule(
def _rust_test_transition_impl(settings, attr):
return {
"//command_line_option:platforms": str(attr.platform) if attr.platform else settings["//command_line_option:platforms"],
}
} | _crate_scope_transition_impl(settings, attr)

_rust_test_transition = transition(
implementation = _rust_test_transition_impl,
inputs = [
"//command_line_option:platforms",
],
] + _crate_scope_transition_inputs,
outputs = [
"//command_line_option:platforms",
],
] + _crate_scope_transition_outputs,
)

rust_test = rule(
Expand All @@ -1299,9 +1326,6 @@ rust_test = rule(
doc = "Optional platform to transition the test to.",
default = None,
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
executable = True,
fragments = ["cpp"],
Expand Down
21 changes: 21 additions & 0 deletions rust/settings/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,27 @@ bzl_library(
],
)

config_setting(
name = "non_rust_scope",
flag_values = {
"//rust/private:crate_scope": "none",
},
)

config_setting(
name = "proc_macro_scope",
flag_values = {
"//rust/private:crate_scope": "proc_macro",
},
)

config_setting(
name = "regular_crate_scope",
flag_values = {
"//rust/private:crate_scope": "regular",
},
)

capture_clippy_output()

clippy_flag()
Expand Down
69 changes: 69 additions & 0 deletions test/crate_scope/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
load("//rust:defs.bzl", "rust_library", "rust_proc_macro", "rust_test")

rust_test(
name = "proc_macro_data_test",
srcs = select({
"//rust/settings:regular_crate_scope": ["rust_test.rs"],
# Analysis fails if rust_test doesn't set the condition above.
}),
edition = "2021",
proc_macro_deps = [
":rust_proc_macro",
],
deps = [
":nonmacro_library",
],
)

rust_library(
name = "nonmacro_library",
srcs = select({
"//rust/settings:regular_crate_scope": ["nonmacro_library.rs"],
# Analysis fails if rust_library doesn't set the condition above.
}),
edition = "2021",
proc_macro_deps = [
":rust_proc_macro",
],
)

rust_proc_macro(
name = "rust_proc_macro",
srcs = ["rust_proc_macro.rs"],
data = select({
"//rust/settings:proc_macro_scope": [":proc_macro_data"],
# Analysis fails if rust_proc_macro doesn't set the condition above.
}),
edition = "2021",
rustc_env = {"CARGO_MANIFEST_DIR": package_name()},
deps = [
":proc_macro_helper",
],
)

rust_library(
name = "proc_macro_helper",
srcs = ["proc_macro_helper.rs"],
data = select({
"//rust/settings:proc_macro_scope": [":helper_data"],
"//rust/settings:regular_crate_scope": [],
}),
edition = "2021",
rustc_env = {"CARGO_MANIFEST_DIR": package_name()},
)

filegroup(
name = "proc_macro_data",
srcs = select({
"//rust/settings:non_rust_scope": ["proc_macro_data.txt"],
# Analysis fails if the data attribute doesn't reset the condition above.
}),
)

filegroup(
name = "helper_data",
srcs = select({
"//rust/settings:non_rust_scope": ["helper_data.txt"],
# Analysis fails if the data attribute doesn't reset the condition above.
}),
)
Empty file.
3 changes: 3 additions & 0 deletions test/crate_scope/nonmacro_library.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
rust_proc_macro::ensure_proc_macro_data_exists!();

pub use rust_proc_macro::ensure_proc_macro_data_exists;
Empty file.
6 changes: 6 additions & 0 deletions test/crate_scope/proc_macro_helper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std::path::Path;

pub fn ensure_helper_data_exists() {
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("helper_data.txt");
assert!(path.exists(), "not found: {}", path.display());
}
Loading