diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index a08e71c25e..f4f0902e51 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -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: diff --git a/cargo/cargo_build_script_runner/lib.rs b/cargo/cargo_build_script_runner/lib.rs index 3739a1778d..201e90144e 100644 --- a/cargo/cargo_build_script_runner/lib.rs +++ b/cargo/cargo_build_script_runner/lib.rs @@ -124,7 +124,9 @@ impl BuildScriptOutput { pub fn outputs_from_command( cmd: &mut Command, ) -> Result<(Vec, 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); diff --git a/cargo/private/BUILD.bazel b/cargo/private/BUILD.bazel index 6a1aab653c..2b7e6de7dd 100644 --- a/cargo/private/BUILD.bazel +++ b/cargo/private/BUILD.bazel @@ -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"], +) diff --git a/cargo/private/cargo_build_script.bzl b/cargo/private/cargo_build_script.bzl index 56f64994af..8d08395c85 100644 --- a/cargo/private/cargo_build_script.bzl +++ b/cargo/private/cargo_build_script.bzl @@ -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")), diff --git a/cargo/private/runfiles_enabled.bzl b/cargo/private/runfiles_enabled.bzl new file mode 100644 index 0000000000..27138cf2eb --- /dev/null +++ b/cargo/private/runfiles_enabled.bzl @@ -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 diff --git a/cargo/private/runfiles_maker/BUILD.bazel b/cargo/private/runfiles_maker/BUILD.bazel new file mode 100644 index 0000000000..3b3df766c2 --- /dev/null +++ b/cargo/private/runfiles_maker/BUILD.bazel @@ -0,0 +1,8 @@ +load("//rust:defs.bzl", "rust_binary") + +rust_binary( + name = "runfiles_maker", + srcs = ["runfiles_maker.rs"], + edition = "2021", + visibility = ["//visibility:public"], +) diff --git a/cargo/private/runfiles_maker/runfiles_maker.rs b/cargo/private/runfiles_maker/runfiles_maker.rs new file mode 100644 index 0000000000..9dea797c69 --- /dev/null +++ b/cargo/private/runfiles_maker/runfiles_maker.rs @@ -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, +} + +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::>(); + + 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 + ) + }); + } +} diff --git a/docs/src/index.md b/docs/src/index.md index 1045dca333..53ee5cbd71 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -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", ], ) ``` diff --git a/examples/crate_universe/cargo_aliases/.bazelrc b/examples/crate_universe/cargo_aliases/.bazelrc deleted file mode 100644 index a67f1baf7f..0000000000 --- a/examples/crate_universe/cargo_aliases/.bazelrc +++ /dev/null @@ -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 diff --git a/examples/crate_universe/cargo_remote/.bazelrc b/examples/crate_universe/cargo_remote/.bazelrc deleted file mode 100644 index a67f1baf7f..0000000000 --- a/examples/crate_universe/cargo_remote/.bazelrc +++ /dev/null @@ -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 diff --git a/examples/crate_universe/cargo_workspace/.bazelrc b/examples/crate_universe/cargo_workspace/.bazelrc deleted file mode 100644 index a67f1baf7f..0000000000 --- a/examples/crate_universe/cargo_workspace/.bazelrc +++ /dev/null @@ -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 diff --git a/examples/crate_universe/multi_package/.bazelrc b/examples/crate_universe/multi_package/.bazelrc deleted file mode 100644 index a67f1baf7f..0000000000 --- a/examples/crate_universe/multi_package/.bazelrc +++ /dev/null @@ -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 diff --git a/examples/crate_universe/no_cargo_manifests/.bazelrc b/examples/crate_universe/no_cargo_manifests/.bazelrc deleted file mode 100644 index a67f1baf7f..0000000000 --- a/examples/crate_universe/no_cargo_manifests/.bazelrc +++ /dev/null @@ -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 diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index 5836040334..c82c236bb2 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -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]), diff --git a/test/dep_env/BUILD.bazel b/test/dep_env/BUILD.bazel index 82acfbb7cb..994731efa5 100644 --- a/test/dep_env/BUILD.bazel +++ b/test/dep_env/BUILD.bazel @@ -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) > $@", ) diff --git a/test/dep_env/dep_env.bzl b/test/dep_env/dep_env.bzl index f571fa6266..84f96a3735 100644 --- a/test/dep_env/dep_env.bzl +++ b/test/dep_env/dep_env.bzl @@ -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( +_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 = [out.path], - command = 'echo contents > "$@/a_file"', + 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 + ) diff --git a/test/dep_env/read_b.rs b/test/dep_env/read_b.rs index b63db42a03..ad89fdce3d 100644 --- a/test/dep_env/read_b.rs +++ b/test/dep_env/read_b.rs @@ -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"); } diff --git a/test/dep_env/read_dep_dir.rs b/test/dep_env/read_dep_dir.rs index c9a82edef1..a9484bad37 100644 --- a/test/dep_env/read_dep_dir.rs +++ b/test/dep_env/read_dep_dir.rs @@ -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::>>() .expect("Failed to read DEP_DIR directory entries"); let entries = entries diff --git a/test/toolchain/BUILD.bazel b/test/toolchain/BUILD.bazel index 6400af931e..bc8e0112ee 100644 --- a/test/toolchain/BUILD.bazel +++ b/test/toolchain/BUILD.bazel @@ -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"], ) diff --git a/test/unit/location_expansion/location_expansion_test.bzl b/test/unit/location_expansion/location_expansion_test.bzl index a58d974980..96b6bf89e8 100644 --- a/test/unit/location_expansion/location_expansion_test.bzl +++ b/test/unit/location_expansion/location_expansion_test.bzl @@ -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( diff --git a/test/unit/pipelined_compilation/wrap.bzl b/test/unit/pipelined_compilation/wrap.bzl index 09c2a6c737..fb4c6db067 100644 --- a/test/unit/pipelined_compilation/wrap.bzl +++ b/test/unit/pipelined_compilation/wrap.bzl @@ -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 < {} +_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")] diff --git a/test/unit/toolchain/subpackage/BUILD.bazel b/test/unit/toolchain/subpackage/BUILD.bazel index 0c8ace8c97..e8f3d676f1 100644 --- a/test/unit/toolchain/subpackage/BUILD.bazel +++ b/test/unit/toolchain/subpackage/BUILD.bazel @@ -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(