Squashed 'third_party/rules_rust/' changes from bf59038cac..078c6908fc
078c6908fc add cc_common.link support for rust_library and rust_test (#1490)
c07aef0287 Skip supplying rpaths on Fuchsia (#1511)
6ee7c80bdb Propagate rustc_env{,_files} from rust_test.crate (#1443)
1cd0788d2a Apply get_lib_name correctly to the C++ runtime libraries (#1508)
90808f0dc4 Minor cleanup to documentation (#1505)
735640f2df Enable rust-analyzer tests on windows. (#1506)
0f34573166 Updated rules_rust to version 0.9.0 (#1503)
9b61b49934 Promoted crate_universe to non-experimental (#1504)
76360dd354 Implement rules archive release artifact in github action. (#1501)
4e5fac5980 Do not pass `--Clink-arg=-l` for libstd and libtest (#1500)
6c38934636 pipelining: add the ability to disable pipelining for a single rule. (#1499)
867fc37c17 rules_rust: enable pipelined compilation. (#1275)
c97f255dfe Delete deprecated targets (#1496)
43b42884a7 Updated examples to use crate_universe (#1494)
0ffde973e8 Updated `//util/import` to use crate_universe (#1492)
83a03ab03e Updated proto rules to fetch dependencies using crate_universe (#1491)
67e204ff22 fix: `rust_doc_test` failure to find params file (#1418)
0fc834bdfa Updated all toolchain_type definitions to be named `toolchain_type`. (#1479)
3be056a7a3 toolchain files: ensure test depends on std (#1486)
228ebfa6eb Updated rules_rust to version `0.8.1`. (#1484)
685dfda497 Fixed use of rust-analyzer with rust_static_library and rust_shared_library (#1482)
2d7f94543f Fix rust-analyzer being unable to find rust sysroot sources. (#1483)
81a77acde2 Updated rules_rust to version `0.8.0`. (#1472)
caad908848 Give useful error on missing workspace manifest (#1475)
0e86b9dd30 Added `rust_analyzer_toolchain` and repository rules for creating one (#1455)
838e4ea828 Update docs on lockfiles (#1477)
fce1222628 Fix typo in function name (#1478)
1929bfbc3e Added Rust version 1.62.1 (#1476)
9a8e878d3d Fix `rust_binary_without_process_wrapper` build with `--stamp` (#1473)
25baabc205 Updated bindgen version (#1470)
8c9d5c7051 Updated rust-analyzer generator to use clap (#1471)
6d8009dbc8 Update `//bindgen` to use `crate_universe` (#1440)
67c97d44ff Updated `tools/rust_analyzer` to use `crate_universe`. (#1448)
6c285eb28e Updated `wasm_bindgen` rules dependencies. (#1464)
82a437cc17 Fixed crate_universe lockfile checks for crates_repository rule (#1468)
e83d5f3c77 Limit coverage to requested files (#1467)
daff327ea7 Stamp only binaries by default (#1452)
adc80a301d Cleanup crate_universe dependency macros (#1460)
824b121acc Updated header of crate_universe generated files to include a regen command (#1461)
d44e1d8363 feat: add `rustc_flags` attr to `rust_doc` rule (#1458)
6b54feb0ff add a way to distinguish proc-macro deps (#1420)
6070b3c9f4 Fixed missing items in distro artifact (#1450)
1e83e74159 do not add proc-macro deps to transitive_link_search_paths (#1424)
ced94dec1b Fix @libgit2 (#1457)
03d1d5e4ac Add extra_rustc_flag and extra_exec_rustc_flag (#1413)
711adc7985 crate_universe: shorten `crate_universe_crate_index` to `cui` (#1454)
8cb9247f18 Replaced small genrules with uses of bazel_skylib (#1451)
38e841aece Upgrade stardoc (#1444)
674762f66a Updated toolchain repository rules to represent one toolchain per repo (#1442)
b22a6e1416 Re-enable disabled windows jobs in CI (#1353)
2fb94c48fd docs: Update homepage to use latest version (#1441)
389c58fcb1 Updated rules_rust to version `0.7.0`. (#1436)
60f26d49d8 exclude `BUILD` and `WORKSPACE` files from generated crate_universe targets (#1437)
26344d4cd7 Have rust_test put its compilation outputs in a subdirectory (#1434)
8b0f644122 Updated crate_universe version to `0.4.0`. (#1435)
adf92b1534 update crate_universe `--repin` args to not require values. (#1433)
da75146d0a Do not attempt to instrument rust code for coverage if rust_toolchain.llvm-cov is None (#1432)
bde2c36821 Added Rust 1.62.0 (#1427)
7056f22bd0 Fixed crate_universe not finding target library names for "rlib"s (#1429)
3d65214d23 crate_universe support for individually updating packages. (#1426)
5a9d999db9 Updated `attr.label` attribute defaults to use `Label` constructor (#1422)
52fc70145a Added `TemplateVariableInfo` to `rust_toolchain`. (#1416)
7465c1aa29 Add test coverage support (#1324)
c5c3603da6 Bump the min supported bazel version (#1414)
937bdc9d05 Add a `cargo_dep_env` rule for setting build.rs environment variables (#1415)
91466fc0d1 Updated `rules_rust` version to `0.6.0`. (#1397)
97264b79d5 Update wasm_bindgen to use crate universe. (#1398)
d3197a65c5 Updated crate_universe version (to `0.3.0`) and dependencies (#1409)
a15e67d666 Deleted "extra workspace member" functionality from crate_universe (#1406)
5910a7585a Use a vec, not set for rustc_flags for crate_universe annotations (#1404)
3aa88ab067 Deleted deprecated `rust_analyzer` rule. (#1405)
7adf7210d0 cargo: Fix handling of relative sysroots (#1371)
57607239ec Enable rustfmt CI for Windows. (#1403)
30e68b49be Added more "ignore" tags to rustfmt and clippy rules. (#1400)
53ad14eead Added support for vendoring external manifests (#1381)
ff243c6ef0 Reorganized rustfmt source tree (#1399)
94e0044afe Refactored the Rustfmt tool to work cross-platform (#1375)
8fca438124 Ran clang-format on all C++ sources (#1396)
e765719e29 Added TemplateVariableInfo to rust_toolchain (#1377)
81590f4b6a Fixed Clippy bug with `--@rules_rust//:clippy_flags`. (#1392)
d77b9f7c6a Use `target_compatible_with` to make `macos` with `Xcode` happy (#1391)
ec27dbe310 Added comments to internal function (#1378)
a9dd2f9200 Removed deprecated file (#1380)
16175c881c Renamed toolchain files targets (#1376)
c7cb5bd7a8 Support crates that have mix of generated and nongenerated inputs (#1340)
521e649ff4 Avoid using common substrings as encodings. (#1370)
28ac6b133d Use a more compact encoding in the `import` macro. (#1365)
3a099bfa97 Fix incorrect assertion in test_env_launcher test (#1368)
4661093fb1 Use target instead of rule in rust_register_toolchains edition docs (#1366)
652f2802e3 Add `env` attribute to `rust_toolchain`. (#1363)
9520f37f1e Update rules_perl in examples (#1364)
1b451c301e Add armv7-linux-androideabi tier 2 triple (#1362)
0265c293f1 Ensure crate_features to be included correctly in rust_project.json (#1356)
121d65fe6a Updated `rules_rust` version to `0.5.0` (#1360)
aca4ec1a0f crate_universe: fix typo (#1314)
69ca2611c5 Don't leak native dependencies of proc_macro (#1359)
4c7f08b8b9 Fixed missing docs (#1358)
e48bec94de feat: build script toolchains annotations (#1344)
ffb946f4b7 Ensure memchr is linked after libobject (#1349)
edca1d8042 Add developing notes for crate_universe (#1351)
120f911d2f Updated rust_bindgen dependencies API (#1354)
42c4528a5f Added Rust 1.61.0 (#1347)
c05e0c6ab1 Fixed fetch_shas script to correctly include .gz and .xz extensions (#1355)
9770b0dd75 Update apple_support (#1346)
87eb807e67 Added support for Rust 1.61.0 to crate_universe (#1348)
84c1d42128 Temporarily disable windows job in CI. (#1352)
421d30e4ff Remove unnecessary `crate_name` usage in `rust_test_suite`. (#1345)
10185339dd Build `rust_test` targets with `crate` using the same crate name as the underlying library target. (#1332)
0049ce3884 Add support for riscv32 targets (#1323)
3aa6de3c63 remove experimental_use_whole_archive_for_native_deps (#1338)
a066bfed46 Replace slashes with underscores in default crate names. (#1336)
1b91e592d5 Revert "Replace slashes with underscores in default crate names. (#1334)" (#1335)
51f8e302e9 "sandwich" rlibs between native deps in linker order (#1333)
df354904a1 Replace slashes with underscores in default crate names. (#1334)
21eed19188 Bump version to 0.4.0 (#1329)
d3d9abac4d Support . workspace member (#1326)
fccaae3055 Error calling `all_crate_deps` without `Cargo.toml` (#1327)
d7c532cb78 Updated wasm_bindgen dependencies API (#1313)
fb4d5546ea Updated wasm_bindgen rules to only require core `rules_nodejs` rules (#1311)
1590670ae1 Prevents running of clippy on bindgen targets (#1320)
73d0164a34 Add support for aarch64-apple-ios-sim (#1304)
61eee54c73 Add bazel-* directories in cargo_manifest_dir/external_crate to gitignore (#1279)
42f78f25e1 crate_universe: Improved documentation (#1305)
bddc4bd94a Silence warnings for example/test dependencies (#1312)
b04fe3b21f Use tinyjson from crates.io instead of github.com. (#1309)
1cab691d14 Remove doc about STATIC_RUST_URL env var. (#1306)
d86e06a884 Don't propagate non-shared transitive linker inputs from `rust_static|shared_library` (#1299)
5abeb93333 Don't emit `CrateInfo` from `rust_static_library` and `rust_shared_library` (#1298)
0175a1b7aa fix for using a nightly channel after https://github.com/bazelbuild/rules_rust/commit/841fc6fb82141576d91aecb1d3f2656d58b0ab71 (#1302)
e07881fa22 Updated crate_universe docs (#1301)
c63ad973f1 rustc: fix a conditional (#1300)
a6f332fcbe Use __EXEC_ROOT__ paths for genfiles in rust_analyzer aspect (#1293)
97de47df51 Remove 'triple' field from triple struct in favor of 'str' (#1297)
58627f59eb Make get_host_triple public to get a triple from Bazel's repository_ctx (#1289)
612f4362bc Updated `rules_rust` version to `0.3.1` (#1296)
26fa5a15de Fixed build issues in release artifact (#1295)
48bb32f817 crate_universe: Added tests for serialized config files. (#1291)
841fc6fb82 Enable xz archives (#1284)
f7cb22efa6 feat(#514): pass extra flags to clippy (#1264)
e9f8b48711 Updated `rules_rust` version to `0.3.0` (#1288)
c900e1c66c Revert "Add workaround for arm vs armv7 android issue (#1259)" (#1290)
01ebef2fb9 Remove DEFAULT_RUST_EDITION (#1256)
03a70796ab Outside of examples, fill in all `edition` attrs (#1257)
207ee4fbcf feat: support extra deps in rust_doc_test (#1286)
4e7d114a8e Fix typo in render config doc (#1281)
db17f291d3 Fix crate annotation anchor (#1282)
fdb6851a92 Fix target name in `rust_test` example. (#1280)
4fb6e40147 Don't leak additive build file content across crates (#1278)
965044ae2b Remove `rust_test` example which doesn't build. (#1267)
f6e7e0a93f add a stopgap experimental_use_whole_archive_for_native_deps attribute (#1269)
34fd46756a process_wrapper: add support for terminating rustc after it emits rmeta. (#1207)
b778fca0ac crate_universe: propagate build_script_tools (#1266)
f6f27a8734 Add workaround for arm vs armv7 android issue (#1259)
c3f56c2d50 Add the BUILD.bazel file to the wasm_bindgen distro filegroup target (#1246) (#1261)
1f2e6231de Set edition for process_wrapper and cargo_build_script_runner (#1254)
55790492ac Updated Rust to 1.60.0 (#1247)
b594f90f17 Workaround for issue in linux Cargo binaries (#1252)
8f0dd9042e rust_test_suite: ensure crate names are valid (#1248)
4144ddeb9c Updating `rules_rust` version to `0.2.1` (#1243)
65cad76a52 Fixed proto package in release artifact (#1241)
4d8de6e361 Updated repository pin in the docs (#1240)
e5a3970754 Updating `rules_rust` version to `0.2.0` (#1235)
d061bf640e Updated `crate_universe` version to `0.2.0` (#1239)
c0505da0d2 Replace `rust_repositories` with `rust_register_toolchains` in docs (#1237)
145ad7609f Fixed `crates_repository` deleting `.cargo/config.toml` files. (#1227)
20066b05e2 fix: distribute `//tools/rust_analyzer` (#1234)
b58ce89603 Enabled `rust_doc_test` for `crate_universe` (#1232)
d2e2470cbf Fix some unit tests to run from another workspace (#1226)
b03aee039a Fixed `crate_universe` clippy defects (#1228)
41b39f0c99 add bots using lld (and examples with clang as a drive by) (#1221)
84e98e4d2f don't emit --codegen={metadata,extra-filename} for rust_static_library and rust_shared_library (#1222)
e48c834a40 Renamed `crate_index` repository to `crate_universe_crate_index` (#1217)
99b4b2574f fix use of stamping in rust_binary_without_process_wrapper (#1218)
8df4517d37 Add NUM_JOBS env var to cargo build scripts (#1216)
628e85e70f Restrucutred `crate_universe` dependency macros (#1208)
e3d67a0a10 Updated docs to guide users to using releases (#1213)
fd912e644c Updated crate_universe docs. (#1212)
cde4c0826c Delete deprecated `rules` targets (#1210)
26e01c8386 cache the release archive in release actions (#1201)
3205c9d846 Updated crate_universe setup guide (#1202)
c078494678 Don't leak deps from rust_proc_macro (#1206)
7c865ffeb1 Build `_import_macro_dep` in `exec` mode (#1203)
635da93206 Updating `rules_rust` version to `0.1.0`. (#1198)
6c797c9070 disable advanced features of C++ rules (#1200)
86d47a1bba Tweak import macro bootstrap to trick rust analyzer aspect (#1179)
80d197205a Added release workflow (#1195)
cd44b3670a Added support for producing distribution archives (#1194)
a665447989 Traverse custom alias-like rules in the rust analyzer aspect (#1190)
4504983fa9 Add a test showing that rust_analayzer aspect traverses aliases (#1188)
297dd18215 Updated `crate_universe` to version `0.1.0`. (#1197)
0d9c7d5e1b Specify root target for rust_analyzer test (#1189)
4a0352fecd Updated `crate_universe` dependencies (#1196)
5126479254 Fixed crate_universe release tools (#1193)
e840400eb6 Remove last remains of use_process_wrapper flag. (#1192)
eb7db68d96 Fix iOS linker arguments (#1186)
de726a10c9 Create internal rust_binary rule instead of using transitions (#1187)
5e6ad9f638 Regenerated `cargo-raze` outputs with v0.15.0 (#1184)
980b662843 add static_library to get_preferred_artifact with pic (#1183)
97fd329540 Populate CFLAGS and CXXFLAGS when invoking build script. (#1081)
git-subtree-dir: third_party/rules_rust
git-subtree-split: 078c6908fc32c168b58e72cc3884dd8e30419e3a
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: Ifc218edaa852263bd76835ee7de44de07c08aec2
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
index 596c10d..490bfa1 100644
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -27,7 +27,8 @@
"expand_dict_value_locations",
"expand_list_element_locations",
"find_cc_toolchain",
- "get_lib_name",
+ "get_lib_name_default",
+ "get_lib_name_for_windows",
"get_preferred_artifact",
"is_exec_configuration",
"make_static_lib_symlink",
@@ -61,6 +62,34 @@
fields = {"extra_exec_rustc_flags": "List[string] Extra flags to pass to rustc in exec configuration"},
)
+IsProcMacroDepInfo = provider(
+ doc = "Records if this is a transitive dependency of a proc-macro.",
+ fields = {"is_proc_macro_dep": "Boolean"},
+)
+
+def _is_proc_macro_dep_impl(ctx):
+ return IsProcMacroDepInfo(is_proc_macro_dep = ctx.build_setting_value)
+
+is_proc_macro_dep = rule(
+ doc = "Records if this is a transitive dependency of a proc-macro.",
+ implementation = _is_proc_macro_dep_impl,
+ build_setting = config.bool(flag = True),
+)
+
+IsProcMacroDepEnabledInfo = provider(
+ doc = "Enables the feature to record if a library is a transitive dependency of a proc-macro.",
+ fields = {"enabled": "Boolean"},
+)
+
+def _is_proc_macro_dep_enabled_impl(ctx):
+ return IsProcMacroDepEnabledInfo(enabled = ctx.build_setting_value)
+
+is_proc_macro_dep_enabled = rule(
+ doc = "Enables the feature to record if a library is a transitive dependency of a proc-macro.",
+ implementation = _is_proc_macro_dep_enabled_impl,
+ build_setting = config.bool(flag = True),
+)
+
def _get_rustc_env(attr, toolchain, crate_name):
"""Gathers rustc environment variables
@@ -78,7 +107,7 @@
patch, pre = patch.split("-", 1)
else:
pre = ""
- return {
+ result = {
"CARGO_CFG_TARGET_ARCH": toolchain.target_arch,
"CARGO_CFG_TARGET_OS": toolchain.os,
"CARGO_CRATE_NAME": crate_name,
@@ -92,6 +121,12 @@
"CARGO_PKG_VERSION_PATCH": patch,
"CARGO_PKG_VERSION_PRE": pre,
}
+ if hasattr(attr, "_is_proc_macro_dep_enabled") and attr._is_proc_macro_dep_enabled[IsProcMacroDepEnabledInfo].enabled:
+ is_proc_macro_dep = "0"
+ if hasattr(attr, "_is_proc_macro_dep") and attr._is_proc_macro_dep[IsProcMacroDepInfo].is_proc_macro_dep:
+ is_proc_macro_dep = "1"
+ result["BAZEL_RULES_RUST_IS_PROC_MACRO_DEP"] = is_proc_macro_dep
+ return result
def get_compilation_mode_opts(ctx, toolchain):
"""Gathers rustc flags for the current compilation mode (opt/debug)
@@ -119,10 +154,25 @@
has_grep_includes)
def _should_use_pic(cc_toolchain, feature_configuration, crate_type):
- if crate_type in ("cdylib" or "dylib"):
+ """Whether or not [PIC][pic] should be enabled
+
+ [pic]: https://en.wikipedia.org/wiki/Position-independent_code
+
+ Args:
+ cc_toolchain (CcToolchainInfo): The current `cc_toolchain`.
+ feature_configuration (FeatureConfiguration): Feature configuration to be queried.
+ crate_type (str): A Rust target's crate type.
+
+ Returns:
+ bool: Whether or not [PIC][pic] should be enabled.
+ """
+ if crate_type in ("cdylib", "dylib"):
return cc_toolchain.needs_pic_for_dynamic_libraries(feature_configuration = feature_configuration)
return False
+def _is_proc_macro(crate_info):
+ return "proc-macro" in (crate_info.type, crate_info.wrapped_crate_type)
+
def collect_deps(
deps,
proc_macro_deps,
@@ -151,6 +201,7 @@
build_info = None
linkstamps = []
transitive_crate_outputs = []
+ transitive_metadata_outputs = []
aliases = {k.label: v for k, v in aliases.items()}
for dep in depset(transitive = [deps, proc_macro_deps]).to_list():
@@ -173,16 +224,42 @@
dep = crate_info,
))
- transitive_crates.append(depset([crate_info], transitive = [dep_info.transitive_crates]))
+ transitive_crates.append(
+ depset(
+ [crate_info],
+ transitive = [] if _is_proc_macro(crate_info) else [dep_info.transitive_crates],
+ ),
+ )
+
+ # If this dependency produces metadata, add it to the metadata outputs.
+ # If it doesn't (for example a custom library that exports crate_info),
+ # we depend on crate_info.output.
+ depend_on = crate_info.metadata
+ if not crate_info.metadata:
+ depend_on = crate_info.output
+
+ # If this dependency is a proc_macro, it still can be used for lib crates
+ # that produce metadata.
+ # In that case, we don't depend on its metadata dependencies.
+ transitive_metadata_outputs.append(
+ depset(
+ [depend_on],
+ transitive = [] if _is_proc_macro(crate_info) else [dep_info.transitive_metadata_outputs],
+ ),
+ )
+
transitive_crate_outputs.append(
depset(
[crate_info.output],
- transitive = [dep_info.transitive_crate_outputs],
+ transitive = [] if _is_proc_macro(crate_info) else [dep_info.transitive_crate_outputs],
),
)
- transitive_noncrates.append(dep_info.transitive_noncrates)
+
+ if "proc-macro" not in [crate_info.type, crate_info.wrapped_crate_type]:
+ transitive_noncrates.append(dep_info.transitive_noncrates)
+ transitive_link_search_paths.append(dep_info.link_search_path_files)
+
transitive_build_infos.append(dep_info.transitive_build_infos)
- transitive_link_search_paths.append(dep_info.link_search_path_files)
elif cc_info:
# This dependency is a cc_library
@@ -209,6 +286,7 @@
order = "topological", # dylib link flag ordering matters.
),
transitive_crate_outputs = depset(transitive = transitive_crate_outputs),
+ transitive_metadata_outputs = depset(transitive = transitive_metadata_outputs),
transitive_build_infos = depset(transitive = transitive_build_infos),
link_search_path_files = depset(transitive = transitive_link_search_paths),
dep_env = build_info.dep_env if build_info else None,
@@ -348,7 +426,7 @@
# Take the absolute value of hash() since it could be negative.
path_hash = abs(hash(lib.path))
- lib_name = get_lib_name(lib)
+ lib_name = get_lib_name_for_windows(lib) if toolchain.os.startswith("windows") else get_lib_name_default(lib)
prefix = "lib"
extension = ".a"
@@ -411,7 +489,7 @@
if _is_dylib(lib):
continue
artifact = get_preferred_artifact(lib, use_pic)
- name = get_lib_name(artifact)
+ name = get_lib_name_for_windows(artifact) if toolchain.os.startswith("windows") else get_lib_name_default(artifact)
# On Linux-like platforms, normally library base names start with
# `lib`, following the pattern `lib[name].(a|lo)` and we pass
@@ -445,6 +523,28 @@
visited_libs[name] = artifact
return ambiguous_libs
+def _depend_on_metadata(crate_info, force_depend_on_objects):
+ """Determines if we can depend on metadata for this crate.
+
+ By default (when pipelining is disabled or when the crate type needs to link against
+ objects) we depend on the set of object files (.rlib).
+ When pipelining is enabled and the crate type supports depending on metadata,
+ we depend on metadata files only (.rmeta).
+ In some rare cases, even if both of those conditions are true, we still want to
+ depend on objects. This is what force_depend_on_objects is.
+
+ Args:
+ crate_info (CrateInfo): The Crate to determine this for.
+ force_depend_on_objects (bool): if set we will not depend on metadata.
+
+ Returns:
+ Whether we can depend on metadata for this crate.
+ """
+ if force_depend_on_objects:
+ return False
+
+ return crate_info.type in ("rlib", "lib")
+
def collect_inputs(
ctx,
file,
@@ -456,7 +556,9 @@
crate_info,
dep_info,
build_info,
- stamp = False):
+ stamp = False,
+ force_depend_on_objects = False,
+ experimental_use_cc_common_link = False):
"""Gather's the inputs and required input information for a rustc action
Args:
@@ -472,6 +574,10 @@
build_info (BuildInfo): The target Crate's build settings.
stamp (bool, optional): Whether or not workspace status stamping is enabled. For more details see
https://docs.bazel.build/versions/main/user-manual.html#flag--stamp
+ force_depend_on_objects (bool, optional): Forces dependencies of this rule to be objects rather than
+ metadata, even for libraries. This is used in rustdoc tests.
+ experimental_use_cc_common_link (bool, optional): Whether rules_rust uses cc_common.link to link
+ rust binaries.
Returns:
tuple: A tuple: A tuple of the following items:
@@ -512,6 +618,10 @@
# change.
linkstamp_outs = []
+ transitive_crate_outputs = dep_info.transitive_crate_outputs
+ if _depend_on_metadata(crate_info, force_depend_on_objects):
+ transitive_crate_outputs = dep_info.transitive_metadata_outputs
+
nolinkstamp_compile_inputs = depset(
getattr(files, "data", []) +
([build_info.rustc_env, build_info.flags] if build_info else []) +
@@ -520,14 +630,16 @@
transitive = [
linker_depset,
crate_info.srcs,
- dep_info.transitive_crate_outputs,
+ transitive_crate_outputs,
depset(additional_transitive_inputs),
crate_info.compile_data,
toolchain.all_files,
],
)
- if crate_info.type in ("bin", "cdylib"):
+ # Register linkstamps when linking with rustc (when linking with
+ # cc_common.link linkstamps are handled by cc_common.link itself).
+ if not experimental_use_cc_common_link and crate_info.type in ("bin", "cdylib"):
# There is no other way to register an action for each member of a depset than
# flattening the depset as of 2021-10-12. Luckily, usually there is only one linkstamp
# in a build, and we only flatten the list on binary targets that perform transitive linking,
@@ -555,8 +667,8 @@
output_replacement = crate_info.output.path,
)
- # If stamping is enabled include the volatile status info file
- stamp_info = [ctx.version_file] if stamp else []
+ # If stamping is enabled include the volatile and stable status info file
+ stamp_info = [ctx.version_file, ctx.info_file] if stamp else []
compile_inputs = depset(
linkstamp_outs + stamp_info,
@@ -565,7 +677,9 @@
],
)
- build_env_files = getattr(files, "rustc_env_files", [])
+ # 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)
if build_env_file:
build_env_files = [f for f in build_env_files] + [build_env_file]
@@ -594,7 +708,10 @@
force_all_deps_direct = False,
force_link = False,
stamp = False,
- remap_path_prefix = "."):
+ remap_path_prefix = ".",
+ use_json_output = False,
+ build_metadata = False,
+ force_depend_on_objects = False):
"""Builds an Args object containing common rustc flags
Args:
@@ -621,6 +738,9 @@
stamp (bool, optional): Whether or not workspace status stamping is enabled. For more details see
https://docs.bazel.build/versions/main/user-manual.html#flag--stamp
remap_path_prefix (str, optional): A value used to remap `${pwd}` to. If set to a falsey value, no prefix will be set.
+ use_json_output (bool): Have rustc emit json and process_wrapper parse json messages to output rendered output.
+ build_metadata (bool): Generate CLI arguments for building *only* .rmeta files. This requires use_json_output.
+ force_depend_on_objects (bool): Force using `.rlib` object files instead of metadata (`.rmeta`) files even if they are available.
Returns:
tuple: A tuple of the following items
@@ -632,6 +752,9 @@
This is to be passed to the `arguments` parameter of actions
- (dict): Common rustc environment variables
"""
+ if build_metadata and not use_json_output:
+ fail("build_metadata requires parse_json_output")
+
output_dir = getattr(crate_info.output, "dirname", None)
linker_script = getattr(file, "linker_script", None)
@@ -662,6 +785,7 @@
# If stamping is enabled, enable the functionality in the process wrapper
if stamp:
process_wrapper_flags.add("--volatile-status-file", ctx.version_file)
+ process_wrapper_flags.add("--stable-status-file", ctx.info_file)
# Both ctx.label.workspace_root and ctx.label.package are relative paths
# and either can be empty strings. Avoid trailing/double slashes in the path.
@@ -700,15 +824,50 @@
rustc_flags.add(crate_info.root)
rustc_flags.add("--crate-name=" + crate_info.name)
rustc_flags.add("--crate-type=" + crate_info.type)
- if hasattr(attr, "_error_format"):
- rustc_flags.add("--error-format=" + attr._error_format[ErrorFormatInfo].error_format)
- # Mangle symbols to disambiguate crates with the same name
- extra_filename = "-" + output_hash if output_hash else ""
- rustc_flags.add("--codegen=metadata=" + extra_filename)
+ error_format = "human"
+ if hasattr(attr, "_error_format"):
+ error_format = attr._error_format[ErrorFormatInfo].error_format
+
+ if use_json_output:
+ # If --error-format was set to json, we just pass the output through
+ # Otherwise process_wrapper uses the "rendered" field.
+ process_wrapper_flags.add("--rustc-output-format", "json" if error_format == "json" else "rendered")
+
+ # Configure rustc json output by adding artifact notifications.
+ # These will always be filtered out by process_wrapper and will be use to terminate
+ # rustc when appropriate.
+ json = ["artifacts"]
+ if error_format == "short":
+ json.append("diagnostic-short")
+ elif error_format == "human" and toolchain.os != "windows":
+ # If the os is not windows, we can get colorized output.
+ json.append("diagnostic-rendered-ansi")
+
+ rustc_flags.add("--json=" + ",".join(json))
+
+ error_format = "json"
+
+ if build_metadata:
+ # Configure process_wrapper to terminate rustc when metadata are emitted
+ process_wrapper_flags.add("--rustc-quit-on-rmeta", "true")
+
+ rustc_flags.add("--error-format=" + error_format)
+
+ # Mangle symbols to disambiguate crates with the same name. This could
+ # happen only for non-final artifacts where we compute an output_hash,
+ # e.g., rust_library.
+ #
+ # For "final" artifacts and ones intended for distribution outside of
+ # Bazel, such as rust_binary, rust_static_library and rust_shared_library,
+ # where output_hash is None we don't need to add these flags.
+ if output_hash:
+ extra_filename = "-" + output_hash
+ rustc_flags.add("--codegen=metadata=" + extra_filename)
+ rustc_flags.add("--codegen=extra-filename=" + extra_filename)
+
if output_dir:
rustc_flags.add("--out-dir=" + output_dir)
- rustc_flags.add("--codegen=extra-filename=" + extra_filename)
compilation_mode = get_compilation_mode_opts(ctx, toolchain)
rustc_flags.add("--codegen=opt-level=" + compilation_mode.opt_level)
@@ -720,7 +879,9 @@
if emit:
rustc_flags.add("--emit=" + ",".join(emit_with_paths))
- rustc_flags.add("--color=always")
+ if error_format != "json":
+ # Color is not compatible with json output.
+ rustc_flags.add("--color=always")
rustc_flags.add("--target=" + toolchain.target_flag_value)
if hasattr(attr, "crate_features"):
rustc_flags.add_all(getattr(attr, "crate_features"), before_each = "--cfg", format_each = 'feature="%s"')
@@ -763,15 +924,19 @@
_add_native_link_flags(rustc_flags, dep_info, linkstamp_outs, ambiguous_libs, crate_info.type, toolchain, cc_toolchain, feature_configuration)
- # These always need to be added, even if not linking this crate.
- add_crate_link_flags(rustc_flags, dep_info, force_all_deps_direct)
+ use_metadata = _depend_on_metadata(crate_info, force_depend_on_objects)
- needs_extern_proc_macro_flag = "proc-macro" in [crate_info.type, crate_info.wrapped_crate_type] and \
- crate_info.edition != "2015"
+ # These always need to be added, even if not linking this crate.
+ add_crate_link_flags(rustc_flags, dep_info, force_all_deps_direct, use_metadata)
+
+ needs_extern_proc_macro_flag = _is_proc_macro(crate_info) and crate_info.edition != "2015"
if needs_extern_proc_macro_flag:
rustc_flags.add("--extern")
rustc_flags.add("proc_macro")
+ if toolchain.llvm_cov and ctx.configuration.coverage_enabled:
+ rustc_flags.add("--codegen=instrument-coverage")
+
# Make bin crate data deps available to tests.
for data in getattr(attr, "data", []):
if rust_common.crate_info in data:
@@ -781,6 +946,9 @@
env_basename = dep_crate_info.output.basename[:-(1 + len(dep_crate_info.output.extension))] if len(dep_crate_info.output.extension) > 0 else dep_crate_info.output.basename
env["CARGO_BIN_EXE_" + env_basename] = dep_crate_info.output.short_path
+ # Add environment variables from the Rust toolchain.
+ env.update(toolchain.env)
+
# Update environment with user provided variables.
env.update(expand_dict_value_locations(
ctx,
@@ -798,9 +966,15 @@
if hasattr(ctx.attr, "_extra_rustc_flags") and not is_exec_configuration(ctx):
rustc_flags.add_all(ctx.attr._extra_rustc_flags[ExtraRustcFlagsInfo].extra_rustc_flags)
+ if hasattr(ctx.attr, "_extra_rustc_flag") and not is_exec_configuration(ctx):
+ rustc_flags.add_all(ctx.attr._extra_rustc_flag[ExtraRustcFlagsInfo].extra_rustc_flags)
+
if hasattr(ctx.attr, "_extra_exec_rustc_flags") and is_exec_configuration(ctx):
rustc_flags.add_all(ctx.attr._extra_exec_rustc_flags[ExtraExecRustcFlagsInfo].extra_exec_rustc_flags)
+ if hasattr(ctx.attr, "_extra_exec_rustc_flag") and is_exec_configuration(ctx):
+ rustc_flags.add_all(ctx.attr._extra_exec_rustc_flag[ExtraExecRustcFlagsInfo].extra_exec_rustc_flags)
+
# Create a struct which keeps the arguments separate so each may be tuned or
# replaced where necessary
args = struct(
@@ -838,8 +1012,23 @@
- (DepInfo): The transitive dependencies of this crate.
- (DefaultInfo): The output file for this crate, and its runfiles.
"""
+ build_metadata = getattr(crate_info, "metadata", None)
+
cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
+ # Determine whether to use cc_common.link:
+ # * either if experimental_use_cc_common_link is 1,
+ # * or if experimental_use_cc_common_link is -1 and
+ # the toolchain experimental_use_cc_common_link is true.
+ experimental_use_cc_common_link = False
+ if hasattr(ctx.attr, "experimental_use_cc_common_link"):
+ if ctx.attr.experimental_use_cc_common_link == 0:
+ experimental_use_cc_common_link = False
+ elif ctx.attr.experimental_use_cc_common_link == 1:
+ experimental_use_cc_common_link = True
+ elif ctx.attr.experimental_use_cc_common_link == -1:
+ experimental_use_cc_common_link = toolchain._experimental_use_cc_common_link
+
dep_info, build_info, linkstamps = collect_deps(
deps = crate_info.deps,
proc_macro_deps = crate_info.proc_macro_deps,
@@ -865,8 +1054,23 @@
dep_info = dep_info,
build_info = build_info,
stamp = stamp,
+ experimental_use_cc_common_link = experimental_use_cc_common_link,
)
+ # The types of rustc outputs to emit.
+ # If we build metadata, we need to keep the command line of the two invocations
+ # (rlib and rmeta) as similar as possible, otherwise rustc rejects the rmeta as
+ # a candidate.
+ # Because of that we need to add emit=metadata to both the rlib and rmeta invocation.
+ #
+ # When cc_common linking is enabled, emit a `.o` file, which is later
+ # passed to the cc_common.link action.
+ emit = ["dep-info", "link"]
+ if build_metadata:
+ emit.append("metadata")
+ if experimental_use_cc_common_link:
+ emit = ["obj"]
+
args, env_from_args = construct_arguments(
ctx = ctx,
attr = attr,
@@ -874,6 +1078,7 @@
toolchain = toolchain,
tool_path = toolchain.rustc.path,
cc_toolchain = cc_toolchain,
+ emit = emit,
feature_configuration = feature_configuration,
crate_info = crate_info,
dep_info = dep_info,
@@ -886,8 +1091,35 @@
build_flags_files = build_flags_files,
force_all_deps_direct = force_all_deps_direct,
stamp = stamp,
+ use_json_output = bool(build_metadata),
)
+ args_metadata = None
+ if build_metadata:
+ args_metadata, _ = construct_arguments(
+ ctx = ctx,
+ attr = attr,
+ file = ctx.file,
+ toolchain = toolchain,
+ tool_path = toolchain.rustc.path,
+ cc_toolchain = cc_toolchain,
+ emit = emit,
+ feature_configuration = feature_configuration,
+ crate_info = crate_info,
+ dep_info = dep_info,
+ linkstamp_outs = linkstamp_outs,
+ ambiguous_libs = ambiguous_libs,
+ output_hash = output_hash,
+ rust_flags = rust_flags,
+ out_dir = out_dir,
+ build_env_files = build_env_files,
+ build_flags_files = build_flags_files,
+ force_all_deps_direct = force_all_deps_direct,
+ stamp = stamp,
+ use_json_output = True,
+ build_metadata = True,
+ )
+
env = dict(ctx.configuration.default_shell_env)
env.update(env_from_args)
@@ -896,15 +1128,25 @@
else:
formatted_version = ""
+ # Declares the outputs of the rustc compile action.
+ # By default this is the binary output; if cc_common.link is used, this is
+ # the main `.o` file (`output_o` below).
outputs = [crate_info.output]
+ # The `.o` output file, only used for linking via cc_common.link.
+ output_o = None
+ if experimental_use_cc_common_link:
+ obj_ext = ".o"
+ output_o = ctx.actions.declare_file(crate_info.name + obj_ext, sibling = crate_info.output)
+ outputs = [output_o]
+
# For a cdylib that might be added as a dependency to a cc_* target on Windows, it is important to include the
# interface library that rustc generates in the output files.
interface_library = None
if toolchain.os == "windows" and crate_info.type == "cdylib":
# Rustc generates the import library with a `.dll.lib` extension rather than the usual `.lib` one that msvc
# expects (see https://github.com/rust-lang/rust/pull/29520 for more context).
- interface_library = ctx.actions.declare_file(crate_info.output.basename + ".lib")
+ interface_library = ctx.actions.declare_file(crate_info.output.basename + ".lib", sibling = crate_info.output)
outputs.append(interface_library)
# The action might generate extra output that we don't want to include in the `DefaultInfo` files.
@@ -916,14 +1158,13 @@
dsym_folder = None
if crate_info.type in ("cdylib", "bin") and not crate_info.is_test:
if toolchain.os == "windows":
- pdb_file = ctx.actions.declare_file(crate_info.output.basename[:-len(crate_info.output.extension)] + "pdb")
+ pdb_file = ctx.actions.declare_file(crate_info.output.basename[:-len(crate_info.output.extension)] + "pdb", sibling = crate_info.output)
action_outputs.append(pdb_file)
elif toolchain.os == "darwin":
- dsym_folder = ctx.actions.declare_directory(crate_info.output.basename + ".dSYM")
+ dsym_folder = ctx.actions.declare_directory(crate_info.output.basename + ".dSYM", sibling = crate_info.output)
action_outputs.append(dsym_folder)
- # This uses startswith as on windows the basename will be process_wrapper_fake.exe.
- if not ctx.executable._process_wrapper.basename.startswith("process_wrapper_fake"):
+ if ctx.executable._process_wrapper:
# Run as normal
ctx.actions.run(
executable = ctx.executable._process_wrapper,
@@ -939,10 +1180,25 @@
len(crate_info.srcs.to_list()),
),
)
+ if args_metadata:
+ ctx.actions.run(
+ executable = ctx.executable._process_wrapper,
+ inputs = compile_inputs,
+ outputs = [build_metadata],
+ env = env,
+ arguments = args_metadata.all,
+ mnemonic = "RustcMetadata",
+ progress_message = "Compiling Rust metadata {} {}{} ({} files)".format(
+ crate_info.type,
+ ctx.label.name,
+ formatted_version,
+ len(crate_info.srcs.to_list()),
+ ),
+ )
else:
# Run without process_wrapper
- if build_env_files or build_flags_files or stamp:
- fail("build_env_files, build_flags_files, stamp are not supported if use_process_wrapper is False")
+ if build_env_files or build_flags_files or stamp or build_metadata:
+ fail("build_env_files, build_flags_files, stamp, build_metadata are not supported when building without process_wrapper")
ctx.actions.run(
executable = toolchain.rustc,
inputs = compile_inputs,
@@ -958,8 +1214,58 @@
),
)
+ if experimental_use_cc_common_link:
+ # Wrap the main `.o` file into a compilation output suitable for
+ # cc_common.link. The main `.o` file is useful in both PIC and non-PIC
+ # modes.
+ compilation_outputs = cc_common.create_compilation_outputs(
+ objects = depset([output_o]),
+ pic_objects = depset([output_o]),
+ )
+
+ # Collect the linking contexts of the standard library and dependencies.
+ linking_contexts = [toolchain.libstd_and_allocator_ccinfo.linking_context, toolchain.stdlib_linkflags.linking_context]
+
+ for dep in crate_info.deps.to_list():
+ if dep.cc_info:
+ linking_contexts.append(dep.cc_info.linking_context)
+
+ # In the cc_common.link action we need to pass the name of the final
+ # binary (output) relative to the package of this target.
+ # We compute it by stripping the path to the package directory,
+ # which is a prefix of the path of `crate_info.output`.
+
+ # The path to the package dir, including a trailing "/".
+ package_dir = ctx.bin_dir.path + "/"
+ if ctx.label.workspace_root:
+ package_dir = package_dir + ctx.label.workspace_root + "/"
+ if ctx.label.package:
+ package_dir = package_dir + ctx.label.package + "/"
+
+ if not crate_info.output.path.startswith(package_dir):
+ fail("The package dir path {} should be a prefix of the crate_info.output.path {}", package_dir, crate_info.output.path)
+
+ output_relative_to_package = crate_info.output.path[len(package_dir):]
+
+ cc_common.link(
+ actions = ctx.actions,
+ feature_configuration = feature_configuration,
+ cc_toolchain = cc_toolchain,
+ linking_contexts = linking_contexts,
+ compilation_outputs = compilation_outputs,
+ name = output_relative_to_package,
+ grep_includes = ctx.file._grep_includes,
+ stamp = ctx.attr.stamp,
+ )
+
+ outputs = [crate_info.output]
+
+ coverage_runfiles = []
+ if toolchain.llvm_cov and ctx.configuration.coverage_enabled and crate_info.is_test:
+ coverage_runfiles = [toolchain.llvm_cov, toolchain.llvm_profdata]
+
runfiles = ctx.runfiles(
- files = getattr(ctx.files, "data", []),
+ files = getattr(ctx.files, "data", []) + coverage_runfiles,
collect_data = True,
)
@@ -968,15 +1274,29 @@
out_binary = getattr(attr, "out_binary", False)
providers = [
- crate_info,
- dep_info,
DefaultInfo(
# nb. This field is required for cc_library to depend on our output.
files = depset(outputs),
runfiles = runfiles,
executable = crate_info.output if crate_info.type == "bin" or crate_info.is_test or out_binary else None,
),
+ coverage_common.instrumented_files_info(
+ ctx,
+ dependency_attributes = ["deps", "crate"],
+ extensions = ["rs"],
+ source_attributes = ["srcs"],
+ ),
]
+
+ if crate_info.type in ["staticlib", "cdylib"]:
+ # These rules are not supposed to be depended on by other rust targets, and
+ # as such they shouldn't provide a CrateInfo. However, one may still want to
+ # write a rust_test for them, so we provide the CrateInfo wrapped in a provider
+ # that rust_test understands.
+ providers.extend([rust_common.test_crate_info(crate = crate_info), dep_info])
+ else:
+ providers.extend([crate_info, dep_info])
+
if toolchain.target_arch != "wasm32":
providers += establish_cc_info(ctx, attr, crate_info, toolchain, cc_toolchain, feature_configuration, interface_library)
if pdb_file:
@@ -989,6 +1309,21 @@
def _is_dylib(dep):
return not bool(dep.static_library or dep.pic_static_library)
+def _collect_nonstatic_linker_inputs(cc_info):
+ shared_linker_inputs = []
+ for linker_input in cc_info.linking_context.linker_inputs.to_list():
+ dylibs = [
+ lib
+ for lib in linker_input.libraries
+ if _is_dylib(lib)
+ ]
+ if dylibs:
+ shared_linker_inputs.append(cc_common.create_linker_input(
+ owner = linker_input.owner,
+ libraries = depset(dylibs),
+ ))
+ return shared_linker_inputs
+
def establish_cc_info(ctx, attr, crate_info, toolchain, cc_toolchain, feature_configuration, interface_library):
"""If the produced crate is suitable yield a CcInfo to allow for interop with cc rules
@@ -1067,9 +1402,20 @@
CcInfo(linking_context = linking_context),
toolchain.stdlib_linkflags,
]
+
for dep in getattr(attr, "deps", []):
if CcInfo in dep:
- cc_infos.append(dep[CcInfo])
+ # A Rust staticlib or shared library doesn't need to propagate linker inputs
+ # of its dependencies, except for shared libraries.
+ if crate_info.type in ["cdylib", "staticlib"]:
+ shared_linker_inputs = _collect_nonstatic_linker_inputs(dep[CcInfo])
+ if shared_linker_inputs:
+ linking_context = cc_common.create_linking_context(
+ linker_inputs = depset(shared_linker_inputs),
+ )
+ cc_infos.append(CcInfo(linking_context = linking_context))
+ else:
+ cc_infos.append(dep[CcInfo])
if crate_info.type in ("rlib", "lib") and toolchain.libstd_and_allocator_ccinfo:
# TODO: if we already have an rlib in our deps, we could skip this
@@ -1138,7 +1484,8 @@
"""
# Windows has no rpath equivalent, so always return an empty depset.
- if toolchain.os == "windows":
+ # Fuchsia assembles shared libraries during packaging.
+ if toolchain.os == "windows" or toolchain.os == "fuchsia":
return depset([])
dylibs = [
@@ -1180,7 +1527,7 @@
dirs[f.dirname] = None
return dirs.keys()
-def add_crate_link_flags(args, dep_info, force_all_deps_direct = False):
+def add_crate_link_flags(args, dep_info, force_all_deps_direct = False, use_metadata = False):
"""Adds link flags to an Args object reference
Args:
@@ -1188,22 +1535,19 @@
dep_info (DepInfo): The current target's dependency info
force_all_deps_direct (bool, optional): Whether to pass the transitive rlibs with --extern
to the commandline as opposed to -L.
+ use_metadata (bool, optional): Build command line arugments using metadata for crates that provide it.
"""
- if force_all_deps_direct:
- args.add_all(
- depset(
- transitive = [
- dep_info.direct_crates,
- dep_info.transitive_crates,
- ],
- ),
- uniquify = True,
- map_each = _crate_to_link_flag,
- )
- else:
- # nb. Direct crates are linked via --extern regardless of their crate_type
- args.add_all(dep_info.direct_crates, map_each = _crate_to_link_flag)
+ direct_crates = depset(
+ transitive = [
+ dep_info.direct_crates,
+ dep_info.transitive_crates,
+ ],
+ ) if force_all_deps_direct else dep_info.direct_crates
+
+ crate_to_link_flags = _crate_to_link_flag_metadata if use_metadata else _crate_to_link_flag
+ args.add_all(direct_crates, uniquify = True, map_each = crate_to_link_flags)
+
args.add_all(
dep_info.transitive_crates,
map_each = _get_crate_dirname,
@@ -1211,6 +1555,29 @@
format_each = "-Ldependency=%s",
)
+def _crate_to_link_flag_metadata(crate):
+ """A helper macro used by `add_crate_link_flags` for adding crate link flags to a Arg object
+
+ Args:
+ crate (CrateInfo|AliasableDepInfo): A CrateInfo or an AliasableDepInfo provider
+
+ Returns:
+ list: Link flags for the given provider
+ """
+
+ # This is AliasableDepInfo, we should use the alias as a crate name
+ if hasattr(crate, "dep"):
+ name = crate.name
+ crate_info = crate.dep
+ else:
+ name = crate.name
+ crate_info = crate
+
+ lib_or_meta = crate_info.metadata
+ if not crate_info.metadata:
+ lib_or_meta = crate_info.output
+ return ["--extern={}={}".format(name, lib_or_meta.path)]
+
def _crate_to_link_flag(crate):
"""A helper macro used by `add_crate_link_flags` for adding crate link flags to a Arg object
@@ -1241,13 +1608,48 @@
"""
return crate.output.dirname
-def _portable_link_flags(lib, use_pic, ambiguous_libs):
+def _portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, for_windows):
artifact = get_preferred_artifact(lib, use_pic)
if ambiguous_libs and artifact.path in ambiguous_libs:
artifact = ambiguous_libs[artifact.path]
if lib.static_library or lib.pic_static_library:
+ # To ensure appropriate linker library argument order, in the presence
+ # of both native libraries that depend on rlibs and rlibs that depend
+ # on native libraries, we use an approach where we "sandwich" the
+ # rust libraries between two similar sections of all of native
+ # libraries:
+ # n1 n2 ... r1 r2 ... n1 n2 ...
+ # A B C
+ # This way any dependency from a native library to a rust library
+ # is resolved from A to B, and any dependency from a rust library to
+ # a native one is resolved from B to C.
+ # The question of resolving dependencies from a native library from A
+ # to any rust library is addressed in a different place, where we
+ # create symlinks to the rlibs, pretending they are native libraries,
+ # and adding references to these symlinks in the native section A.
+ # We rely in the behavior of -Clink-arg to put the linker args
+ # at the end of the linker invocation constructed by rustc.
+
+ # We skip adding `-Clink-arg=-l` for libstd and libtest from the standard library, as
+ # these two libraries are present both as an `.rlib` and a `.so` format.
+ # On linux, Rustc adds a -Bdynamic to the linker command line before the libraries specified
+ # with `-Clink-arg`, which leads to us linking against the `.so`s but not putting the
+ # corresponding value to the runtime library search paths, which results in a
+ # "cannot open shared object file: No such file or directory" error at exectuion time.
+ # We can fix this by adding a `-Clink-arg=-Bstatic` on linux, but we don't have that option for
+ # macos. The proper solution for this issue would be to remove `libtest-{hash}.so` and `libstd-{hash}.so`
+ # from the toolchain. However, it is not enough to change the toolchain's `rust_std_{...}` filegroups
+ # here: https://github.com/bazelbuild/rules_rust/blob/a9d5d894ad801002d007b858efd154e503796b9f/rust/private/repository_utils.bzl#L144
+ # because rustc manages to escape the sandbox and still finds them at linking time.
+ # We need to modify the repository rules to erase those files completely.
+ if "lib/rustlib" in artifact.path and (
+ artifact.basename.startswith("libtest-") or artifact.basename.startswith("libstd-") or
+ artifact.basename.startswith("test-") or artifact.basename.startswith("std-")
+ ):
+ return ["-lstatic=%s" % get_lib_name(artifact)]
return [
"-lstatic=%s" % get_lib_name(artifact),
+ "-Clink-arg=-l%s" % (get_lib_name(artifact) if not for_windows else artifact.basename),
]
elif _is_dylib(lib):
return [
@@ -1263,7 +1665,7 @@
if lib.alwayslink:
ret.extend(["-C", "link-arg=/WHOLEARCHIVE:%s" % get_preferred_artifact(lib, use_pic).path])
else:
- ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs))
+ ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_for_windows, for_windows = True))
return ret
def _make_link_flags_darwin(linker_input_and_use_pic_and_ambiguous_libs):
@@ -1276,7 +1678,7 @@
("link-arg=-Wl,-force_load,%s" % get_preferred_artifact(lib, use_pic).path),
])
else:
- ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs))
+ ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_default, for_windows = False))
return ret
def _make_link_flags_default(linker_input_and_use_pic_and_ambiguous_libs):
@@ -1293,7 +1695,7 @@
"link-arg=-Wl,--no-whole-archive",
])
else:
- ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs))
+ ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_default, for_windows = False))
return ret
def _libraries_dirnames(linker_input_and_use_pic_and_ambiguous_libs):
@@ -1314,7 +1716,6 @@
toolchain (rust_toolchain): The current `rust_toolchain`
cc_toolchain (CcToolchainInfo): The current `cc_toolchain`
feature_configuration (FeatureConfiguration): feature configuration to use with cc_toolchain
-
"""
if crate_type in ["lib", "rlib"]:
return
@@ -1323,10 +1724,13 @@
if toolchain.os == "windows":
make_link_flags = _make_link_flags_windows
+ get_lib_name = get_lib_name_for_windows
elif toolchain.os.startswith("mac") or toolchain.os.startswith("darwin"):
make_link_flags = _make_link_flags_darwin
+ get_lib_name = get_lib_name_default
else:
make_link_flags = _make_link_flags_default
+ get_lib_name = get_lib_name_default
# TODO(hlopko): Remove depset flattening by using lambdas once we are on >=Bazel 5.0
args_and_pic_and_ambiguous_libs = [(arg, use_pic, ambiguous_libs) for arg in dep_info.transitive_noncrates.to_list()]
@@ -1422,6 +1826,18 @@
build_setting = config.string_list(flag = True),
)
+def _extra_rustc_flag_impl(ctx):
+ return ExtraRustcFlagsInfo(extra_rustc_flags = [f for f in ctx.build_setting_value if f != ""])
+
+extra_rustc_flag = rule(
+ doc = (
+ "Add additional rustc_flag from the command line with `--@rules_rust//:extra_rustc_flag`. " +
+ "Multiple uses are accumulated and appended after the extra_rustc_flags."
+ ),
+ implementation = _extra_rustc_flag_impl,
+ build_setting = config.string(flag = True, allow_multiple = True),
+)
+
def _extra_exec_rustc_flags_impl(ctx):
return ExtraExecRustcFlagsInfo(extra_exec_rustc_flags = ctx.build_setting_value)
@@ -1434,3 +1850,15 @@
implementation = _extra_exec_rustc_flags_impl,
build_setting = config.string_list(flag = True),
)
+
+def _extra_exec_rustc_flag_impl(ctx):
+ return ExtraExecRustcFlagsInfo(extra_exec_rustc_flags = [f for f in ctx.build_setting_value if f != ""])
+
+extra_exec_rustc_flag = rule(
+ doc = (
+ "Add additional rustc_flags in the exec configuration from the command line with `--@rules_rust//:extra_exec_rustc_flag`. " +
+ "Multiple uses are accumulated and appended after the extra_exec_rustc_flags."
+ ),
+ implementation = _extra_exec_rustc_flag_impl,
+ build_setting = config.string(flag = True, allow_multiple = True),
+)