diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 9195249ab8..025f2407fd 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -68,6 +68,12 @@ default_macos_targets: &default_macos_targets - "//..." # Not sure why this doesn't work on bazelci, it does locally on macOS. - "-//test/unit/remap_path_prefix:integration_test" +default_macos_coverage_targets: &default_macos_coverage_targets + - "--" + - "//..." + # Not sure why these don't work on bazelci, it does locally on macOS. + - "-//test/unit/remap_path_prefix:integration_test" + - "-//test/linking_out_dir:test" default_windows_targets: &default_windows_targets - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245 - "//..." @@ -110,7 +116,7 @@ tasks: platform: macos_arm64 build_targets: *default_macos_targets test_targets: *default_macos_targets - coverage_targets: *default_macos_targets + coverage_targets: *default_macos_coverage_targets post_shell_commands: *coverage_validation_post_shell_commands windows: build_targets: *default_windows_targets @@ -140,7 +146,7 @@ tasks: shell_commands: *no_bzlmod_shell_commands build_targets: *default_macos_targets test_targets: *default_macos_targets - coverage_targets: *default_macos_targets + coverage_targets: *default_macos_coverage_targets post_shell_commands: *coverage_validation_post_shell_commands windows_no_bzlmod: name: No Bzlmod @@ -167,7 +173,7 @@ tasks: name: Split Coverage Postprocessing platform: macos_arm64 shell_commands: *split_coverage_postprocessing_shell_commands - coverage_targets: *default_macos_targets + coverage_targets: *default_macos_coverage_targets post_shell_commands: *coverage_validation_post_shell_commands ubuntu2204_opt: name: Opt Mode @@ -230,7 +236,7 @@ tasks: build_flags: *aspects_flags build_targets: *default_macos_targets test_targets: *default_macos_targets - coverage_targets: *default_macos_targets + coverage_targets: *default_macos_coverage_targets post_shell_commands: *coverage_validation_post_shell_commands macos_rolling_with_aspects: name: "Macos Rolling Bazel Version With Aspects" @@ -238,7 +244,7 @@ tasks: build_flags: *aspects_flags build_targets: *default_macos_targets test_targets: *default_macos_targets - coverage_targets: *default_macos_targets + coverage_targets: *default_macos_coverage_targets post_shell_commands: *coverage_validation_post_shell_commands soft_fail: yes bazel: "rolling" diff --git a/rust/private/providers.bzl b/rust/private/providers.bzl index 5c47bf14cb..44c31acfa7 100644 --- a/rust/private/providers.bzl +++ b/rust/private/providers.bzl @@ -59,6 +59,7 @@ DepInfo = provider( "transitive_data": "depset[File]: Data of all transitive non-macro dependencies.", "transitive_metadata_outputs": "depset[File]: All transitive metadata dependencies (.rmeta, for crates that provide them) and all transitive object dependencies (.rlib) for crates that don't provide metadata.", "transitive_noncrates": "depset[LinkerInput]: All transitive dependencies that aren't crates.", + "transitive_out_dirs": "depset[File]: The out directories of the build scripts of all transitive dependencies", "transitive_proc_macro_data": "depset[File]: Data of all transitive proc-macro dependencies, and non-macro dependencies of those macros.", }, ) diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index 3293cd9f12..aa7344d77c 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -226,6 +226,7 @@ def collect_deps( transitive_proc_macro_data = [] transitive_noncrates = [] transitive_build_infos = [] + transitive_out_dirs = [] transitive_link_search_paths = [] build_info = None linkstamps = [] @@ -321,6 +322,7 @@ def collect_deps( transitive_link_search_paths.append(dep_info.link_search_path_files) transitive_build_infos.append(dep_info.transitive_build_infos) + transitive_out_dirs.append(dep_info.transitive_out_dirs) elif cc_info or dep_build_info: if cc_info: # This dependency is a cc_library @@ -332,6 +334,8 @@ def collect_deps( "only one is allowed in the dependencies") build_info = dep_build_info transitive_build_infos.append(depset([build_info])) + if build_info.out_dir: + transitive_out_dirs.append(depset([build_info.out_dir])) if build_info.link_search_paths: transitive_link_search_paths.append(depset([build_info.link_search_paths])) transitive_data.append(build_info.compile_data) @@ -356,6 +360,7 @@ def collect_deps( transitive_crate_outputs = depset(transitive = transitive_crate_outputs), transitive_metadata_outputs = depset(transitive = transitive_metadata_outputs), transitive_build_infos = depset(transitive = transitive_build_infos), + transitive_out_dirs = depset(transitive = transitive_out_dirs), link_search_path_files = depset(transitive = transitive_link_search_paths), dep_env = build_info.dep_env if build_info else None, ), @@ -1872,7 +1877,7 @@ def _create_extra_input_args(build_info, dep_info, include_link_flags = True): out_dir_compile_inputs = depset( input_files, - transitive = [dep_info.link_search_path_files, dep_info.transitive_data] + input_depsets, + transitive = [dep_info.link_search_path_files, dep_info.transitive_data, dep_info.transitive_out_dirs] + input_depsets, ) return ( diff --git a/test/linking_out_dir/BUILD.bazel b/test/linking_out_dir/BUILD.bazel new file mode 100644 index 0000000000..706fccd88b --- /dev/null +++ b/test/linking_out_dir/BUILD.bazel @@ -0,0 +1,47 @@ +"""Tests that cargo build scripts can create archives in OUT_DIR and link to +them. This requires that binaries or shared libraries include the out dirs of +transitive dependencies when linking.""" + +load("@bazel_skylib//rules:native_binary.bzl", "native_test") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("//cargo:defs.bzl", "cargo_build_script") +load("//rust:defs.bzl", "rust_binary", "rust_library") + +cc_library( + name = "foo", + srcs = ["foo.c"], +) + +filegroup( + name = "foo_static", + srcs = [":foo"], + output_group = "archive", +) + +cargo_build_script( + name = "build_script", + srcs = ["build.rs"], + build_script_env = {"ARCHIVE_PATH": "$(execpath :foo_static)"}, + crate_root = "build.rs", + data = [":foo_static"], + edition = "2021", +) + +rust_library( + name = "bar", + srcs = ["bar.rs"], + edition = "2021", + deps = [":build_script"], +) + +rust_binary( + name = "main", + srcs = ["main.rs"], + edition = "2021", + deps = [":bar"], +) + +native_test( + name = "test", + src = ":main", +) diff --git a/test/linking_out_dir/bar.rs b/test/linking_out_dir/bar.rs new file mode 100644 index 0000000000..e24c542625 --- /dev/null +++ b/test/linking_out_dir/bar.rs @@ -0,0 +1,7 @@ +extern "C" { + fn foo() -> i32; +} + +pub fn bar() -> i32 { + unsafe { foo() } +} diff --git a/test/linking_out_dir/build.rs b/test/linking_out_dir/build.rs new file mode 100644 index 0000000000..0a29429a26 --- /dev/null +++ b/test/linking_out_dir/build.rs @@ -0,0 +1,17 @@ +use std::env; +use std::path::PathBuf; + +const ARCHIVE_NAME: &'static str = "test_linking_out_dir_foo"; + +fn main() { + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + let src = env::var_os("ARCHIVE_PATH").unwrap(); + + let dst = out_dir.join(format!("lib{ARCHIVE_NAME}.a")); + + std::fs::copy(&src, &dst).unwrap(); + + println!("cargo:rustc-link-lib={ARCHIVE_NAME}"); + println!("cargo:rustc-link-search=native={}", out_dir.display()); +} diff --git a/test/linking_out_dir/foo.c b/test/linking_out_dir/foo.c new file mode 100644 index 0000000000..f0ffc1c0f7 --- /dev/null +++ b/test/linking_out_dir/foo.c @@ -0,0 +1,3 @@ +#include + +int32_t foo() { return 1; } diff --git a/test/linking_out_dir/main.rs b/test/linking_out_dir/main.rs new file mode 100644 index 0000000000..d1c0bb3f3a --- /dev/null +++ b/test/linking_out_dir/main.rs @@ -0,0 +1,5 @@ +pub fn main() { + let result = bar::bar(); + + assert_eq!(result, 1); +}