Update `cargo_build_script` to work without runfiles support. (#2871)

Partially addresses https://github.com/bazelbuild/rules_rust/issues/1156
This commit is contained in:
UebelAndre 2024-09-18 19:44:23 -07:00 committed by GitHub
parent d9ee6172d1
commit c520417e26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 471 additions and 181 deletions

View File

@ -36,6 +36,21 @@ default_windows_targets: &default_windows_targets
- "//..."
- "-//test/proto/..."
- "-//test/unit/pipelined_compilation/..."
default_windows_no_runfiles_targets: &default_windows_no_runfiles_targets
- "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245
- "//..."
# TODO: https://github.com/bazelbuild/rules_rust/issues/1156
- "-//crate_universe/..."
- "-//test/chained_direct_deps:mod3_doc_test"
- "-//test/out_dir_in_tests:demo_lib_doc_test"
- "-//test/proto/..."
- "-//test/rustc_env_files:output_test"
- "-//test/test_env_launcher:test"
- "-//test/test_env:test_manifest_dir"
- "-//test/test_env:test_run"
- "-//test/unit/pipelined_compilation/..."
- "-//test/unit/rustdoc/..."
- "-//tools/runfiles/..."
crate_universe_vendor_example_targets: &crate_universe_vendor_example_targets
- "//vendor_external:crates_vendor"
- "//vendor_local_manifests:crates_vendor"
@ -58,6 +73,7 @@ split_coverage_postprocessing_shell_commands: &split_coverage_postprocessing_she
- echo "build --//rust/settings:experimental_use_coverage_metadata_files" >> user.bazelrc
tasks:
ubuntu2004:
platform: ubuntu2004
build_targets: *default_linux_targets
test_targets: *default_linux_targets
coverage_targets: *default_linux_targets
@ -65,19 +81,31 @@ tasks:
run_targets:
- //test:query_test_binary
rbe_ubuntu2004:
platform: rbe_ubuntu2004
shell_commands:
- sed -i 's/^# load("@bazel_ci_rules/load("@bazel_ci_rules/' WORKSPACE.bazel
- sed -i 's/^# rbe_preconfig/rbe_preconfig/' WORKSPACE.bazel
build_targets: *default_linux_targets
test_targets: *default_linux_targets
macos:
platform: macos
build_targets: *default_macos_targets
test_targets: *default_macos_targets
coverage_targets: *default_macos_targets
post_shell_commands: *coverage_validation_post_shell_commands
windows:
platform: windows
build_targets: *default_windows_targets
test_targets: *default_windows_targets
windows_no_runfiles:
name: No Runfiles
platform: windows
build_flags:
- "--noenable_runfiles"
test_flags:
- "--noenable_runfiles"
build_targets: *default_windows_no_runfiles_targets
test_targets: *default_windows_no_runfiles_targets
ubuntu2004_split_coverage_postprocessing:
name: Split Coverage Postprocessing
platform: ubuntu2004
@ -171,6 +199,19 @@ tasks:
- "--config=clippy"
build_targets: *default_windows_targets
test_targets: *default_windows_targets
windows_no_runfiles_with_aspects:
name: No Runfiles With Aspects
platform: windows
build_flags:
- "--noenable_runfiles"
- "--config=rustfmt"
- "--config=clippy"
test_flags:
- "--noenable_runfiles"
- "--config=rustfmt"
- "--config=clippy"
build_targets: *default_windows_no_runfiles_targets
test_targets: *default_windows_no_runfiles_targets
windows_rolling_with_aspects:
name: "Windows Rolling Bazel Version With Aspects"
platform: windows
@ -610,7 +651,7 @@ tasks:
environment:
# This ndk version matches with rules_android_ndk repo's CI
# https://github.com/bazelbuild/rules_android_ndk/blob/877c68ef34c9f3353028bf490d269230c1990483/.bazelci/presubmit.yml#L37
# The ndk is installed by this script
# The ndk is installed by this script
# https://github.com/bazelbuild/continuous-integration/blob/ba56013373821feadd9f2eaa6b81eb19528795f0/macos/mac-android.sh
ANDROID_NDK_HOME: /opt/android-ndk-r25b
android_examples_macos:
@ -625,7 +666,7 @@ tasks:
environment:
# This ndk version matches with rules_android_ndk repo's CI
# https://github.com/bazelbuild/rules_android_ndk/blob/877c68ef34c9f3353028bf490d269230c1990483/.bazelci/presubmit.yml#L42
# The ndk is installed by this script
# The ndk is installed by this script
# https://github.com/bazelbuild/continuous-integration/blob/ba56013373821feadd9f2eaa6b81eb19528795f0/macos/mac-android.sh
ANDROID_NDK_HOME: /Users/buildkite/android-ndk-r25b
ios_examples:

View File

@ -124,7 +124,9 @@ impl BuildScriptOutput {
pub fn outputs_from_command(
cmd: &mut Command,
) -> Result<(Vec<BuildScriptOutput>, Output), Output> {
let child_output = cmd.output().expect("Unable to start binary");
let child_output = cmd
.output()
.unwrap_or_else(|e| panic!("Unable to start command:\n{:?}\n{:#?}", e, cmd));
if child_output.status.success() {
let reader = BufReader::new(child_output.stdout.as_slice());
let output = Self::outputs_from_reader(reader);

View File

@ -1,7 +1,13 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load(":runfiles_enabled.bzl", "runfiles_enabled_build_setting")
bzl_library(
name = "bzl_lib",
srcs = glob(["**/*.bzl"]),
visibility = ["//:__subpackages__"],
)
runfiles_enabled_build_setting(
name = "runfiles_enabled",
visibility = ["//visibility:public"],
)

View File

@ -23,6 +23,7 @@ load(
"find_toolchain",
_name_to_crate_name = "name_to_crate_name",
)
load(":runfiles_enabled.bzl", "is_runfiles_enabled", "runfiles_enabled_attr")
# Reexport for cargo_build_script_wrapper.bzl
name_to_crate_name = _name_to_crate_name
@ -198,6 +199,39 @@ def _feature_enabled(ctx, feature_name, default = False):
return default
def _rlocationpath(file, workspace_name):
if file.short_path.startswith("../"):
return file.short_path[len("../"):]
return "{}/{}".format(workspace_name, file.short_path)
def _create_runfiles_dir(ctx, script):
runfiles_dir = ctx.actions.declare_directory("{}.cargo_runfiles".format(ctx.label.name))
workspace_name = ctx.label.workspace_name
if not workspace_name:
workspace_name = ctx.workspace_name
def _runfiles_map(file):
return "{}={}".format(file.path, _rlocationpath(file, workspace_name))
runfiles = script[DefaultInfo].default_runfiles
args = ctx.actions.args()
args.use_param_file("@%s", use_always = True)
args.add(runfiles_dir.path)
args.add_all(runfiles.files, map_each = _runfiles_map, allow_closure = True)
ctx.actions.run(
mnemonic = "CargoBuildScriptRunfilesDir",
executable = ctx.executable._runfiles_maker,
arguments = [args],
inputs = runfiles.files,
outputs = [runfiles_dir],
)
return runfiles_dir
def _cargo_build_script_impl(ctx):
"""The implementation for the `cargo_build_script` rule.
@ -208,6 +242,7 @@ def _cargo_build_script_impl(ctx):
list: A list containing a BuildInfo provider
"""
script = ctx.executable.script
script_info = ctx.attr.script[CargoBuildScriptRunfilesInfo]
toolchain = find_toolchain(ctx)
out_dir = ctx.actions.declare_directory(ctx.label.name + ".out_dir")
env_out = ctx.actions.declare_file(ctx.label.name + ".env")
@ -215,9 +250,27 @@ def _cargo_build_script_impl(ctx):
flags_out = ctx.actions.declare_file(ctx.label.name + ".flags")
link_flags = ctx.actions.declare_file(ctx.label.name + ".linkflags")
link_search_paths = ctx.actions.declare_file(ctx.label.name + ".linksearchpaths") # rustc-link-search, propagated from transitive dependencies
manifest_dir = "%s.runfiles/%s/%s" % (script.path, ctx.label.workspace_name or ctx.workspace_name, ctx.label.package)
compilation_mode_opt_level = get_compilation_mode_opts(ctx, toolchain).opt_level
script_tools = []
script_data = []
for target in script_info.data:
script_data.append(target[DefaultInfo].files)
script_data.append(target[DefaultInfo].default_runfiles.files)
for target in script_info.tools:
script_tools.append(target[DefaultInfo].files)
script_tools.append(target[DefaultInfo].default_runfiles.files)
workspace_name = ctx.label.workspace_name
if not workspace_name:
workspace_name = ctx.workspace_name
manifest_dir = "{}.runfiles/{}/{}".format(script.path, workspace_name, ctx.label.package)
if not is_runfiles_enabled(ctx.attr):
runfiles_dir = _create_runfiles_dir(ctx, ctx.attr.script)
script_data.append(depset([runfiles_dir]))
manifest_dir = "{}/{}/{}".format(runfiles_dir.path, workspace_name, ctx.label.package)
streams = struct(
stdout = ctx.actions.declare_file(ctx.label.name + ".stdout.log"),
stderr = ctx.actions.declare_file(ctx.label.name + ".stderr.log"),
@ -331,8 +384,6 @@ def _cargo_build_script_impl(ctx):
variables = getattr(target[platform_common.TemplateVariableInfo], "variables", depset([]))
env.update(variables)
script_info = ctx.attr.script[CargoBuildScriptRunfilesInfo]
_merge_env_dict(env, expand_dict_value_locations(
ctx,
ctx.attr.build_script_env,
@ -343,15 +394,6 @@ def _cargo_build_script_impl(ctx):
script_info.tools,
))
script_tools = []
script_data = []
for target in script_info.data:
script_data.append(target[DefaultInfo].files)
script_data.append(target[DefaultInfo].default_runfiles.files)
for target in script_info.tools:
script_tools.append(target[DefaultInfo].files)
script_tools.append(target[DefaultInfo].default_runfiles.files)
tools = depset(
direct = [
script,
@ -379,6 +421,7 @@ def _cargo_build_script_impl(ctx):
args.add(ctx.attr.rundir)
build_script_inputs = []
for dep in ctx.attr.link_deps:
if rust_common.dep_info in dep and dep[rust_common.dep_info].dep_env:
dep_env_file = dep[rust_common.dep_info].dep_env
@ -520,7 +563,12 @@ cargo_build_script = rule(
"_experimental_symlink_execroot": attr.label(
default = Label("//cargo/settings:experimental_symlink_execroot"),
),
},
"_runfiles_maker": attr.label(
cfg = "exec",
executable = True,
default = Label("//cargo/private/runfiles_maker"),
),
} | runfiles_enabled_attr(),
fragments = ["cpp"],
toolchains = [
str(Label("//rust:toolchain_type")),

View File

@ -0,0 +1,167 @@
"""A small utility module dedicated to detecting whether or not the `--enable_runfiles` and `--windows_enable_symlinks` flag are enabled
"""
load("@bazel_skylib//lib:selects.bzl", "selects")
load("@bazel_skylib//rules:common_settings.bzl", "bool_setting")
RunfilesEnabledInfo = provider(
doc = "A singleton provider that contains the raw value of a build setting",
fields = {
"value": "The value of the build setting in the current configuration. " +
"This value may come from the command line or an upstream transition, " +
"or else it will be the build setting's default.",
},
)
def _runfiles_enabled_setting_impl(ctx):
return RunfilesEnabledInfo(value = ctx.attr.value)
runfiles_enabled_setting = rule(
implementation = _runfiles_enabled_setting_impl,
doc = "A bool-typed build setting that cannot be set on the command line",
attrs = {
"value": attr.bool(
doc = "A boolean value",
mandatory = True,
),
},
)
_RUNFILES_ENABLED_ATTR_NAME = "_runfiles_enabled"
def runfiles_enabled_attr(default = Label("//cargo/private:runfiles_enabled")):
return {
_RUNFILES_ENABLED_ATTR_NAME: attr.label(
doc = "A flag representing whether or not runfiles are enabled.",
providers = [RunfilesEnabledInfo],
default = default,
cfg = "exec",
),
}
def runfiles_enabled_build_setting(name, **kwargs):
"""Define a build setting identifying if runfiles are enabled.
Args:
name (str): The name of the build setting
**kwargs: Additional keyword arguments for the target.
"""
native.config_setting(
name = "{}__enable_runfiles".format(name),
values = {"enable_runfiles": "true"},
)
native.config_setting(
name = "{}__disable_runfiles".format(name),
values = {"enable_runfiles": "false"},
)
bool_setting(
name = "{}__always_true".format(name),
build_setting_default = True,
)
native.config_setting(
name = "{}__always_true_setting".format(name),
flag_values = {":{}__always_true".format(name): "True"},
)
native.config_setting(
name = "{}__always_false_setting".format(name),
flag_values = {":{}__always_true".format(name): "False"},
)
# There is no way to query a setting that is unset. By utilizing constant
# settings, we can filter to a fallback setting where no known value is
# defined.
native.alias(
name = "{}__unset_runfiles".format(name),
actual = select({
":{}__disable_runfiles".format(name): ":{}__always_false_setting".format(name),
":{}__enable_runfiles".format(name): ":{}__always_false_setting".format(name),
"//conditions:default": ":{}__always_true_setting".format(name),
}),
)
selects.config_setting_group(
name = "{}__windows_enable_runfiles".format(name),
match_all = [
":{}__enable_runfiles".format(name),
"@platforms//os:windows",
],
)
selects.config_setting_group(
name = "{}__windows_disable_runfiles".format(name),
match_all = [
":{}__disable_runfiles".format(name),
"@platforms//os:windows",
],
)
selects.config_setting_group(
name = "{}__windows_unset_runfiles".format(name),
match_all = [
":{}__unset_runfiles".format(name),
"@platforms//os:windows",
],
)
native.alias(
name = "{}__unix".format(name),
actual = select({
"@platforms//os:windows": ":{}__always_false_setting".format(name),
"//conditions:default": ":{}__always_true_setting".format(name),
}),
)
selects.config_setting_group(
name = "{}__unix_enable_runfiles".format(name),
match_all = [
":{}__enable_runfiles".format(name),
":{}__unix".format(name),
],
)
selects.config_setting_group(
name = "{}__unix_disable_runfiles".format(name),
match_all = [
":{}__disable_runfiles".format(name),
":{}__unix".format(name),
],
)
selects.config_setting_group(
name = "{}__unix_unset_runfiles".format(name),
match_all = [
":{}__unset_runfiles".format(name),
":{}__unix".format(name),
],
)
runfiles_enabled_setting(
name = name,
value = select({
":{}__windows_enable_runfiles".format(name): True,
":{}__windows_disable_runfiles".format(name): False,
":{}__windows_unset_runfiles".format(name): False,
":{}__unix_enable_runfiles".format(name): True,
":{}__unix_disable_runfiles".format(name): False,
":{}__unix_unset_runfiles".format(name): True,
"//conditions:default": True,
}),
**kwargs
)
def is_runfiles_enabled(attr):
"""Determine whether or not runfiles are enabled.
Args:
attr (struct): A rule's struct of attributes (`ctx.attr`)
Returns:
bool: The enable_runfiles value.
"""
runfiles_enabled = getattr(attr, _RUNFILES_ENABLED_ATTR_NAME, None)
return runfiles_enabled[RunfilesEnabledInfo].value if runfiles_enabled else True

View File

@ -0,0 +1,8 @@
load("//rust:defs.bzl", "rust_binary")
rust_binary(
name = "runfiles_maker",
srcs = ["runfiles_maker.rs"],
edition = "2021",
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,71 @@
//! A tool for building runfiles directories for Bazel environments that don't
//! support runfiles or have runfiles enabled.
use std::collections::BTreeMap;
use std::path::PathBuf;
struct Args {
pub output_dir: PathBuf,
pub runfiles: BTreeMap<PathBuf, PathBuf>,
}
impl Args {
fn parse() -> Self {
let args_file = std::env::args().nth(1).expect("No args file was passed.");
let content = std::fs::read_to_string(
args_file
.strip_prefix('@')
.expect("Param files should start with @"),
)
.unwrap();
let mut args = content.lines();
let output_dir = PathBuf::from(
args.next()
.unwrap_or_else(|| panic!("Not enough arguments provided.")),
);
let runfiles = args
.map(|s| {
let s = if s.starts_with('\'') && s.ends_with('\'') {
s.trim_matches('\'')
} else {
s
};
let (src, dest) = s
.split_once('=')
.unwrap_or_else(|| panic!("Unexpected runfiles argument: {}", s));
(PathBuf::from(src), PathBuf::from(dest))
})
.collect::<BTreeMap<_, _>>();
assert!(!runfiles.is_empty(), "No runfiles found");
Args {
output_dir,
runfiles,
}
}
}
fn main() {
let args = Args::parse();
for (src, dest) in args.runfiles.iter() {
let out_dest = args.output_dir.join(dest);
std::fs::create_dir_all(
out_dest
.parent()
.expect("The output location should have a valid parent."),
)
.expect("Failed to create output directory");
std::fs::copy(src, &out_dest).unwrap_or_else(|e| {
panic!(
"Failed to copy file {} -> {}\n{:?}",
src.display(),
out_dest.display(),
e
)
});
}
}

View File

@ -20,7 +20,7 @@ Note that rules_rust bzlmod support is still a work in progress. Most features s
To use `rules_rust` in a project using bzlmod, add the following to your `MODULE.bazel` file:
```python
bazel_dep(name = "rules_rust", version = "0.48.0")
bazel_dep(name = "rules_rust", version = "0.50.1")
```
Don't forget to substitute in your desired release's version number.
@ -36,8 +36,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# https://github.com/bazelbuild/rules_rust/releases
http_archive(
name = "rules_rust",
integrity = "sha256-Weev1uz2QztBlDA88JX6A1N72SucD1V8lBsaliM0TTg=",
urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.48.0/rules_rust-v0.48.0.tar.gz"],
integrity = "sha256-Log/YgrGjboS4tCqQPBA58VPyFcnCn/IZm+xxKTZrn0=",
urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.50.1/rules_rust-v0.50.1.tar.gz"],
)
load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains")
@ -57,7 +57,7 @@ To build with a particular version of the Rust compiler, pass that version to [`
rust_register_toolchains(
edition = "2021",
versions = [
"1.79.0"
"1.79.0",
],
)
```

View File

@ -1,25 +0,0 @@
# A config file containing Bazel settings
# Required on windows
common --enable_platform_specific_config
startup --windows_enable_symlinks
build:windows --enable_runfiles
# Enable rustfmt
build:strict --aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect
build:strict --output_groups=+rustfmt_checks
# Enable clippy
build:strict --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect
build:strict --output_groups=+clippy_checks
# TODO: migrate all dependencies from WORKSPACE to MODULE.bazel
# https://github.com/bazelbuild/rules_rust/issues/2181
common --noenable_bzlmod
# This isn't currently the defaut in Bazel, but we enable it to test we'll be ready if/when it flips.
build --incompatible_disallow_empty_glob
# This import should always be last to allow users to override
# settings for local development.
try-import %workspace%/user.bazelrc

View File

@ -1,25 +0,0 @@
# A config file containing Bazel settings
# Required on windows
common --enable_platform_specific_config
startup --windows_enable_symlinks
build:windows --enable_runfiles
# Enable rustfmt
build:strict --aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect
build:strict --output_groups=+rustfmt_checks
# Enable clippy
build:strict --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect
build:strict --output_groups=+clippy_checks
# TODO: migrate all dependencies from WORKSPACE to MODULE.bazel
# https://github.com/bazelbuild/rules_rust/issues/2181
common --noenable_bzlmod
# This isn't currently the defaut in Bazel, but we enable it to test we'll be ready if/when it flips.
build --incompatible_disallow_empty_glob
# This import should always be last to allow users to override
# settings for local development.
try-import %workspace%/user.bazelrc

View File

@ -1,25 +0,0 @@
# A config file containing Bazel settings
# Required on windows
common --enable_platform_specific_config
startup --windows_enable_symlinks
build:windows --enable_runfiles
# Enable rustfmt
build:strict --aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect
build:strict --output_groups=+rustfmt_checks
# Enable clippy
build:strict --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect
build:strict --output_groups=+clippy_checks
# TODO: migrate all dependencies from WORKSPACE to MODULE.bazel
# https://github.com/bazelbuild/rules_rust/issues/2181
common --noenable_bzlmod
# This isn't currently the defaut in Bazel, but we enable it to test we'll be ready if/when it flips.
build --incompatible_disallow_empty_glob
# This import should always be last to allow users to override
# settings for local development.
try-import %workspace%/user.bazelrc

View File

@ -1,25 +0,0 @@
# A config file containing Bazel settings
# Required on windows
common --enable_platform_specific_config
startup --windows_enable_symlinks
build:windows --enable_runfiles
# Enable rustfmt
build:strict --aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect
build:strict --output_groups=+rustfmt_checks
# Enable clippy
build:strict --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect
build:strict --output_groups=+clippy_checks
# TODO: migrate all dependencies from WORKSPACE to MODULE.bazel
# https://github.com/bazelbuild/rules_rust/issues/2181
common --noenable_bzlmod
# This isn't currently the defaut in Bazel, but we enable it to test we'll be ready if/when it flips.
build --incompatible_disallow_empty_glob
# This import should always be last to allow users to override
# settings for local development.
try-import %workspace%/user.bazelrc

View File

@ -1,25 +0,0 @@
# A config file containing Bazel settings
# Required on windows
common --enable_platform_specific_config
startup --windows_enable_symlinks
build:windows --enable_runfiles
# Enable rustfmt
build:strict --aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect
build:strict --output_groups=+rustfmt_checks
# Enable clippy
build:strict --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect
build:strict --output_groups=+clippy_checks
# TODO: migrate all dependencies from WORKSPACE to MODULE.bazel
# https://github.com/bazelbuild/rules_rust/issues/2181
common --noenable_bzlmod
# This isn't currently the defaut in Bazel, but we enable it to test we'll be ready if/when it flips.
build --incompatible_disallow_empty_glob
# This import should always be last to allow users to override
# settings for local development.
try-import %workspace%/user.bazelrc

View File

@ -329,6 +329,7 @@ def collect_deps(
transitive_build_infos.append(depset([build_info]))
if build_info.link_search_paths:
transitive_link_search_paths.append(depset([build_info.link_search_paths]))
transitive_data.append(build_info.compile_data)
else:
fail("rust targets can only depend on rust_library, rust_*_library or cc_library " +
"targets.")
@ -470,14 +471,12 @@ def get_linker_and_args(ctx, attr, crate_type, cc_toolchain, feature_configurati
def _process_build_scripts(
build_info,
dep_info,
compile_inputs,
include_link_flags = True):
"""Gathers the outputs from a target's `cargo_build_script` action.
Args:
build_info (BuildInfo): The target Build's dependency info.
dep_info (DepInfo): The Depinfo provider form the target Crate's set of inputs.
compile_inputs (depset): A set of all files that will participate in the build.
include_link_flags (bool, optional): Whether to include flags like `-l` that instruct the linker to search for a library.
Returns:
@ -488,8 +487,7 @@ def _process_build_scripts(
- (depset[File]): All direct and transitive build flags from the current build info.
"""
extra_inputs, out_dir, build_env_file, build_flags_files = _create_extra_input_args(build_info, dep_info, include_link_flags = include_link_flags)
compile_inputs = depset(transitive = [extra_inputs, compile_inputs])
return compile_inputs, out_dir, build_env_file, build_flags_files
return extra_inputs, out_dir, build_env_file, build_flags_files
def _symlink_for_ambiguous_lib(actions, toolchain, crate_info, lib):
"""Constructs a disambiguating symlink for a library dependency.
@ -780,13 +778,18 @@ def collect_inputs(
],
)
build_script_compile_inputs, out_dir, build_env_file, build_flags_files = _process_build_scripts(
build_info = build_info,
dep_info = dep_info,
include_link_flags = include_link_flags,
)
# For backwards compatibility, we also check the value of the `rustc_env_files` attribute when
# `crate_info.rustc_env_files` is not populated.
build_env_files = crate_info.rustc_env_files if crate_info.rustc_env_files else getattr(files, "rustc_env_files", [])
compile_inputs, out_dir, build_env_file, build_flags_files = _process_build_scripts(build_info, dep_info, compile_inputs, include_link_flags = include_link_flags)
if build_env_file:
build_env_files = [f for f in build_env_files] + [build_env_file]
compile_inputs = depset(build_env_files, transitive = [compile_inputs])
compile_inputs = depset(build_env_files, transitive = [build_script_compile_inputs, compile_inputs])
return compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs
def construct_arguments(
@ -1731,8 +1734,13 @@ def _create_extra_input_args(build_info, dep_info, include_link_flags = True):
input_depsets.append(build_info.compile_data)
out_dir_compile_inputs = depset(
input_files,
transitive = [dep_info.link_search_path_files, dep_info.transitive_data] + input_depsets,
)
return (
depset(input_files, transitive = [dep_info.link_search_path_files] + input_depsets),
out_dir_compile_inputs,
out_dir,
build_env_file,
depset(build_flags_files, transitive = [dep_info.link_search_path_files]),

View File

@ -113,4 +113,5 @@ genrule(
srcs = ["dep_dir"],
outs = ["set_dep_dir.env"],
cmd = "echo DEP_DIR=\\$${pwd}/$(execpath dep_dir) > $@",
cmd_bat = "echo DEP_DIR=$${pwd}/$(execpath dep_dir) > $@",
)

View File

@ -1,14 +1,59 @@
"""Tests for passing configuration to cargo_build_script rules"""
"""Tests for passing configuration to cargo_dep_env rules"""
def _create_dep_dir(ctx):
out = ctx.actions.declare_directory("dep_dir")
ctx.actions.run_shell(
outputs = [out],
arguments = [out.path],
command = 'echo contents > "$@/a_file"',
_SH_WRITER = """\
#!/usr/bin/env bash
set -euo pipefail
echo content > $@
"""
_BAT_WRITER = """\
@ECHO OFF
echo content > %*
"""
def _create_dep_dir_impl(ctx):
is_windows = ctx.attr.platform.values()[0] == "windows"
writer = ctx.actions.declare_file("{}.writer.{}".format(
ctx.label.name,
".bat" if is_windows else ".sh",
))
ctx.actions.write(
output = writer,
content = _BAT_WRITER if is_windows else _SH_WRITER,
is_executable = True,
)
out = ctx.actions.declare_directory("{}.dep_dir".format(ctx.label.name))
ctx.actions.run(
executable = writer,
outputs = [out],
arguments = [
"{}\\a_file".format(out.path) if is_windows else "{}/a_file".format(out.path),
],
)
return [DefaultInfo(files = depset(direct = [out]))]
create_dep_dir = rule(
implementation = _create_dep_dir,
_create_dep_dir = rule(
implementation = _create_dep_dir_impl,
attrs = {
"platform": attr.label_keyed_string_dict(
doc = "The name of the exec platform",
cfg = "exec",
mandatory = True,
),
},
)
def create_dep_dir(name, **kwargs):
native.filegroup(
name = "{}_".format(name),
)
_create_dep_dir(
name = name,
platform = select({
"@platforms//os:windows": {":{}_".format(name): "windows"},
"//conditions:default": {":{}_".format(name): "unix"},
}),
**kwargs
)

View File

@ -1,5 +1,5 @@
use std::env::var;
fn main() {
assert_eq!(var("DEP_Y_B").unwrap(), "b_value");
assert_eq!(var("DEP_Y_B").unwrap().trim(), "b_value");
}

View File

@ -1,9 +1,18 @@
use std::{env::var, fs, io::Result};
use std::env::var;
use std::fs;
use std::io::Result;
use std::path::PathBuf;
fn main() {
let dep_dir = &var("DEP_DIR").expect("DEP_DIR should be set");
let entries = fs::read_dir(dep_dir)
.expect("Failed to open DEP_DIR directory")
let dep_dir = PathBuf::from(var("DEP_DIR").expect("DEP_DIR should be set").trim());
let entries = fs::read_dir(&dep_dir)
.unwrap_or_else(|e| {
panic!(
"Failed to open DEP_DIR directory: {}\n{:?}",
dep_dir.display(),
e
)
})
.collect::<Result<Vec<_>>>()
.expect("Failed to read DEP_DIR directory entries");
let entries = entries

View File

@ -9,6 +9,7 @@ genrule(
# rustc assumes it can read things like librustc_driver in order to run this command.
# This is a test to ensure we supply all of the files rustc needs as part of the current_rust_toolchain.
cmd = "$(RUSTC) --print=cfg > $@",
cmd_bat = "$(RUSTC) --print=cfg > $@",
toolchains = ["@rules_rust//rust/toolchain:current_rust_toolchain"],
tools = ["@rules_rust//rust/toolchain:current_rust_toolchain"],
)

View File

@ -1,6 +1,7 @@
"""Unittest to verify location expansion in rustc flags"""
load("@bazel_skylib//lib:unittest.bzl", "analysistest")
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("//rust:defs.bzl", "rust_library")
load("//test/unit:common.bzl", "assert_action_mnemonic", "assert_argv_contains")
@ -17,10 +18,14 @@ def _location_expansion_rustc_flags_test(ctx):
location_expansion_rustc_flags_test = analysistest.make(_location_expansion_rustc_flags_test)
def _location_expansion_test():
native.genrule(
write_file(
name = "flag_generator",
outs = ["generated_flag.data"],
cmd = "echo --cfg=test_flag > $@",
out = "generated_flag.data",
content = [
"--cfg=test_flag",
"",
],
newline = "unix",
)
rust_library(

View File

@ -6,21 +6,21 @@ load("//rust/private:providers.bzl", "BuildInfo", "CrateInfo", "DepInfo", "DepVa
# buildifier: disable=bzl-visibility
load("//rust/private:rustc.bzl", "rustc_compile_action")
def _wrap_impl(ctx):
rs_file = ctx.actions.declare_file(ctx.label.name + "_wrapped.rs")
crate_name = ctx.attr.crate_name if ctx.attr.crate_name else ctx.label.name
ctx.actions.run_shell(
outputs = [rs_file],
command = """cat <<EOF > {}
_CONTENT = """\
// crate_name: {}
use to_wrap::to_wrap;
pub fn wrap() {{
to_wrap();
}}
EOF
""".format(rs_file.path, crate_name),
mnemonic = "WriteWrapperRsFile",
"""
def _wrap_impl(ctx):
rs_file = ctx.actions.declare_file(ctx.label.name + "_wrapped.rs")
crate_name = ctx.attr.crate_name if ctx.attr.crate_name else ctx.label.name
ctx.actions.write(
output = rs_file,
content = _CONTENT.format(crate_name),
)
toolchain = ctx.toolchains[Label("//rust:toolchain")]

View File

@ -1,7 +1,10 @@
genrule(
load("@bazel_skylib//rules:write_file.bzl", "write_file")
write_file(
name = "dummy_rlib",
outs = ["core.rlib"],
cmd = "touch $@",
out = "core.rlib",
content = [],
newline = "unix",
)
filegroup(