Squashed 'third_party/rules_rust/' changes from 078c6908f..bf9ddeb7c
bf9ddeb7c Release 0.25.1 (#2049)
db5b2fd65 Update tinyjson (#2050)
6a7872ae3 Fix prost proto packages not sanitizing to valid module names (#2044)
c080d7bfa Moved legacy protobuf rules to `proto/protobuf` (#2043)
1281cc051 Remove debug code. (#2048)
cd126be1f Fix build failure finding crate_roots when mixed with generated sources (#2041)
7f751cddd Consolidate rust_prost_library and fix extension-only proto generation. (#2047)
6118c81f2 Release 0.25.0 (#2042)
a6f29fd07 Add Prost and Tonic rules. (#2033)
9442aed8c fix: `crate_type` more accurately corresponds to CC linking actions (#1975)
4f4e2b17b Re-enable zig example on CI (#2030)
2ded0c2f5 Fix flaky coverage test in CI (#2028)
36f8251f9 Exclude .tmp_git_root from globs (#1948)
ca750fa83 Eliminate Rustfmt action in Bindgen rules. Bindgen can run rustfmt (#2025)
c55ec0cfb Allow sysroots from cc_toolchains to be added to bindgen actions (#2024)
9314b1b0c Release 0.24.1 (#2023)
92ea74ade Making rust_std attr in rust_toolchain mandatory (#1984)
a54b8e14b Update `rust_library_group` to use `DepVariantInfo` (#2022)
47644346b Release v0.24.0 (#2020)
a6b0a7f39 Rust library group (#1848)
bc43f4841 Fix crate_universe's `all_crate_deps` and `aliases` functions failing in case the crate's Cargo.toml has condtional dependencies (#2018)
8f27ec7c5 fix: load cargo manifest without resolving abs path of deps (#2017)
23f99bb63 feature: `target_compatible_with` added to `CommonAttrs` (#1976)
11f8c9875 Make `rust_doc_test` inherit it's crate aliases attribute (#2007)
8e848414d Regenerated crate_universe outputs for all packages (#2011)
1b6365131 Don't use startup:windows (#2012)
e80582e75 Fix thumbv* platform resolution (#2010)
367f90ef0 Update bindgen version to 0.65.1 (#2008)
e6ed5bf90 Release 0.23.0 (#2003)
93b230bb8 Fix code coverage collection. (#2001)
0a14bfbb0 Minor CI and test cleanup (#2004)
3e2ee941a Update bindgen rules to build clang from source. (#1998)
5a1a7577d Split up cargo_build_script tests (#2002)
eb6413e83 Update various bash scripts to pipe errors to stderr (#1999)
affe947ac Update stardoc version (#1997)
7073146f8 Add support for armv8-m (#1993)
73a06f130 Added Rust 1.70.0 (#1991)
23c20a93f Fixes crates_vendor workspace name detection when using bzlmod (#1990)
f5813fa08 Set windows flags in platform-specific bazelrc (#1988)
c1632b5b5 Fix up anchor link (#1987)
56e760487 Fix typo in crate_universe-generated defs.bzl comment (#1981)
94cbe4c2c Symlink in the exec-root so that relative paths will work, unchanged. (#1781)
af8ef62eb Release 0.22.0 (#1974)
4aaa6de30 Allow specifying exec and target compatibility constraints (#1971)
f1b19c394 Update rules_apple in tests (#1972)
937e63399 Add T2 support for x86_64-unknown-none (#1967)
66b1bf165 fix: lld-link (MSVC) fix flags including `-l` prefix (#1958)
285dcbbb9 feature: expose `extra_rustc_flags` and `extra_exec_rustc_flags` at `rust_register_toolchains` (#1959)
0f25cb462 Removed `rust_toolchain.os` in favor of `rust_toolchain.exec_triple`. (#1960)
a2a1109dc Add T2 support for thumbv7em-none-eabi (#1957)
80f0eb488 Support for `no_std` mode (#1934)
99aaf0830 Rename crates_vendor_manifests to cvm to shorten windows path lengths (#1944)
0a57da049 Added tests for build script dependencies to crate_universe (#1943)
caffb0a08 Release 0.21.1 (#1936)
c869a17c7 Fix regression in building zlib (#1935)
24b9dea4f Release 0.21.0 (#1933)
7677c617e Add support for rustc flags to `rust_proto_library` (#1932)
fa304ae48 Updated zlib BUILD file to support darwin-arm64 (#1931)
a86313282 Added Rust 1.69.0 (#1930)
f0e12c707 Make BuildInfo provider public (#1920)
c6ad23aba Respect `#[global_allocator]` in `cc_common.link` builds (#1926)
d78752504 Exclude target directory from release tars (#1922)
0339cd18a [wasm-bindgen] Update to v0.2.84 (#1919)
07af5678e Handle corner case for windows architecture detection (#1915)
c56e7660d Fix optional deps by platform (#1911)
4663ff6a3 cc_common_link: also respect --custom_malloc if set (#1912)
dab425760 Add Rust 1.68.2 (#1908)
e4bd39f95 Add empty rustfmt.toml (#1907)
eaf513865 Support bzlmod (#1528)
1074ecbab Release v0.20.0 (#1900)
44aec0a79 ci: fix test config in cc_common_link_ubuntu2004 (#1904)
6571cde64 Adds per_crate_rustc_flag build setting. (#1827)
7a47449df Added Rust 1.68.1 (#1898)
e3bcdbad1 Fixed rustdoc warnings in crate_universe (#1897)
529f45900 Added `rustdoc_flags` attribute to rust_doc rule (#1867)
9e3499405 Have rustdoc return its output directory instead of zip default. (#1868)
9d6741f40 Implement support for optional crates enabled with dep: features (#1885)
fd10963ea Skip adding -lstatic to libtest and libstd on Darwin (#1620)
b3314b45e Release 0.19.1 (#1895)
c1a9fd86f Accumulate all features from cargo tree output (#1884)
206f71c95 Disable zig example (#1893)
1a5d07cd2 Add runfiles support to rust_stdlib_filegroup (#1890)
6996cd550 Deleted unused targets and cleanup docs (#1889)
a85e24e20 Fix triple constraints for iOS and watchOS (#1888)
e13fd3bad Release rules_rust and cargo-bazel (#1882)
9e9853d63 Add support for thumbv7em with hard float (#1871)
b3cd5962e Added Rust 1.68.0 (#1866)
f1b7aedf5 Support sparse indexes (#1857)
7f2dd433a Make fetch_shas work with mktemp from coreutils 8.32 (#1870)
a9cc01230 Update crate_universe dependencies (#1872)
c038e94ae Pipe stderr from cargo tree processes (#1879)
222d60322 Parallelize cargo tree calls (#1874)
cdbbf7131 Add Fuchsia platform support (#1833)
17e5b04c2 Use `_make_link_flags_darwin` when target os is `ios`. (#1843)
d9ecc8df4 crate_universe: Support fetching crates with git branch, tag or rev (#1846)
1c694cd60 Forward `toolchains` to `cargo_build_script` targets (#1862)
9affcbfa7 Skip detecting abi for empty values (#1830)
6193fe823 Re-enable crate_universe MacOS tests (#1861)
c25db95ae Updated Rust to 1.67.1 (#1864)
7b8fd06be Support `[patch]` in crate_universe when using multiple `Cargo.toml`s (#1856)
c645fe399 Silence windows build failure (#1863)
75bba7b50 Make rust_clippy providers match rustfmt_test (#1806)
f09d72755 Fix test assertion for arm64 macs (#1845)
f4113bfe1 Fix tests for new Apple toolchain (#1844)
20ce44e30 fix: use target_triple struct instead of string (#1835)
bdbded181 Fix code example in doc (#1838)
4f4014052 Fix typo: plced -> placed (#1834)
baeb0664d Remove ios/android/wasm support for gen_rust_project deps (#1684)
02557a47a Add `render_config` attribute to `crates_vendor`. (#1832)
4357fb154 Updated rules_rust to version 0.18.0 (#1829)
9adfdca9b Various cleanups (#1828)
4fa412385 Added update known shas to include T1-T2 triples (#1824)
905731ad9 Instructions on how to perform `rustfmt` check (#1822) (#1823)
108b1a187 Encapsulate running cargo into a struct (#1815)
57a099b63 Fixes resolver issue with root packages and another dependency format (#1819)
78ca9ba0a Use env method recently added to cargo_metadata (#1813)
92834930f Updated `rust_toolchain.target_json` to take encoded json strings (#1810)
84f1d0657 support `resolver = "2"` target-specific features (#1710)
a5853fd37 Use correct dynamic link args fro proc-macro crates (#1803)
b656e2553 Added tests for the `triple` constructor (#1811)
ea4a79ad9 Disable job in CI to avoid infrastructure failure. (#1816)
2fc02f030 Delete `rust_toolchain.rusrc_srcs` (#1807)
804d5fc1f Convert `rust_toolchain` attrs `exec_triple` and `target_triple` to structs (#1808)
499a2ca38 Updated platform triple values from strings to structs ("triple") (#1804)
aae1dbdcb Unify functions for computing constraint values for platform triple abi (#1805)
0d6d2b1eb Updated rules_rust version to `0.17.0` (#1800)
88e83f2df Added Rust 1.67.0 (#1799)
6922b5012 rustdoc_test: fix and test OUT_DIR (#1779)
ad01d1b0e [crate_universe] add an annotation to disable pipelining (#1733)
f651cd18f Add `CARGO_BAZEL_REPIN_ONLY` repinning allowlist (#1798)
d7f0debb0 Revert "Disable broken clang and ldd CI jobs (#1785)" (#1796)
96f82aaad Fix `cc_common.link` file output name (#1795)
5079b64d5 Fix use of `rustfmt_toolchain` when `rustc` is not provided (#1794)
23c650f35 Have `--experimental_use_cc_common_link` cover `rust_shared_library` (#1792)
ba0fb5956 Added support for `--nolegacy_external_runfiles` to `rust_doc_test` (#1790)
112242bb7 Prevent crates_vendor from restarting bazel. (#1791)
52231ef9f Added compatibility flags to `.bazelrc` to prevent regressions (#1789)
91cd399a0 Add "crate-name={}" tag to Crate Universe targets (#1787)
1b1dae196 Added Rust 1.66.1 (#1767)
fe17e8b8e Add file:// prefix to env var in docs (#1788)
0fe742bff Updated `rust_bindgen` to use `rustfmt_toolchain` (#1770)
042fd6c1c Update docs on setting Rust versions (#1786)
dddd8a0d4 Updated crate_universe dependencies (#1775)
a1330a71f Download `rustc` in `rustfmt_toolchain_repository` (#1769)
e96aad9aa Updated the ios_build example to use `crates_vendor` (#1778)
e315007df Disable broken clang and ldd CI jobs (#1785)
4e89d52a9 rustdoc_test: substitute the root of the current crate (#1777)
a52041fb5 Support `target_settings` in `rust_repository_set` and `rust_toolchain_repository` (#1758)
49906eb29 Update clippy and rustfmt aspects to require CrateInfo providers (#1772)
85564208e Updated rules_rust version to `0.16.1` (#1761)
614499a5b Fixed inability to deserialize crate_universe lockfiles (#1760)
9803d3034 Fix data and compile_data for rust_doc (#1741)
927a364cb Update Release github pipeline to trigger automatically (#1757)
7d03e05f8 Fix release pipeline (#1756)
cf7ca5dfd Updated rules_rust to version `0.16.0` (#1750)
203fe4b9a Remove unnecessary binary file (#1755)
941c7cca9 Don't propagate `compatible_with` to the underlying `cargo_build_script` `rust_binary` target (#1754)
a31490d9a Make loads from @rules_rust//rust:defs.bzl come out on one line (#1753)
7ebad4d50 Generate only the needed subset of binaries for bindgen and proto (#1751)
4ef3d4aaa Repin examples/crate_universe_unnamed (#1752)
d6e300359 Regenerate BUILD files using serde_starlark renderer (#1746)
e7c8a97d1 Convert BUILD.$name-$version.bazel to serde_starlark (#1743)
c09818d3b Exclude generated files from language stats and collapse in code review (#1747)
26a24f030 Added CI for single toolchain channel workspaces (#1712)
caed7d814 Report context on error failing to get version (#1744)
36b57af7b Add gen_binaries annotation to control which bins to make target for (#1718)
d916a6f52 crate_universe re-pinning now defaults to "workspace" (#1723)
f34661ee1 Propagate `compatible_with` attribute to the underlying `_build_script_run` target (#1745)
92977d1bf Re-pinned all dependencies managed by crate_universe (#1735)
d5289ad1c Added `rustfmt_toolchain` and refactored toolchain repository rules (#1719)
532e60ff0 Collect targets in a deterministic order (#1736)
52e02c25b Eliminate all use of hash-based collections from crate_universe (#1737)
31073ff8e Replace tera template with serde_starlark (#1734)
d4e5586d0 Support the RUNFILES_DIR environment variable. (#1732)
1357b85b1 Addressed clippy warnings from `clippy 0.1.67 (ec56537c 2022-12-15)` (#1717)
8bc9f788d Support dsym_folder output group in tests (#1703)
90c5b6eb7 Added CI for minimum supported Rust version (#1720)
be82ff8bd Match prerelease versions with annotation wildcard (#1716)
36c7f285b Arm Thumb Embedded Targets. (#1721)
5ef52e465 Update current_toolchain_files tests to use a dedicated test rule (#1714)
c75ea6f9e Add `Runfiles::current_repository` to runfiles library (#1713)
2f0511782 Updated rules_rust to version `0.15.0` (#1706)
019f87178 Added Rust 1.66.0 (#1705)
1469cd7cb Fix labels to work with canonical label literals. (#1700)
5826a500a Add riscv32imc and riscv64gc to the known sha targets (#1698)
40dee95ce Fixed typos: normla -> normal (#1699)
8f08e77ac load_arbitrary_tool uses tool_suburl to look up sha256 (#1695)
8faec3060 Fix typos in crate_universe rendered comments (#1691)
bd64711ff Silence flaky test (#1693)
46b7ea5af Added a build setting for toolchain channels (#1671)
70b272aad Updated rules_rust to version `0.14.0` (#1669)
91e597dd1 Updated all crates_vendor outputs (#1687)
9a047b0b9 Updated crate_universe dependencies (#1686)
3a91d2f5b Add RV64GC target (#1683)
d9e752ab4 Add per-toolchain `rustc_flags` (#1635)
56237415e stardoc: Use backtick not `<code>` for attr default values (#1682)
d4b31a494 Allow passing a bazel path to vendor explicitly (#1661)
d51bf9ce0 Updated crate_universe to work with `--nolegacy_external_runfiles` (#1680)
7f40636d1 crate_universe/private/crates_vendor.bzl typo fix (#1678)
025bf7db8 Merge cc toolchain flags into build script env (#1675)
b7c36c051 Fix confusing/misleading crate_universe docs (#1677)
29233e354 Revert #1564 (#1663)
ed32b6de2 Common glob excludes (#1673)
61b99cdd1 fix: add space to crate data exclude list (#1665)
8bb25b8b7 Support Windows ARM64 (aarch64-pc-windows-msvc) (#1664)
ddf2a4c23 Re-render crate BUILD files after #1647 (#1655)
44c7e1588 Group deps and aliases by platform triple rather than by cfg string when generating BUILD files. This avoid bazel errors due to duplicate keys/deps. (#1647)
de18d8bb6 Allow `buildifier` attribute to be a file (#1660)
aa0815dc9 Fix naming of ambiguous libs (#1625)
ff314d4ab Also pass -c opt to tests in opt mode CI (#1626)
ff4e90515 Reenable windows job (#1658)
c45b8e91f Updated rules_rust to version `0.13.0` (#1644)
87d6b6c37 Update `//util/label` to support `+` in packages (#1654)
ab6959db5 fix: Fix issue with wasi-0.11.0+wasi-snapshot-preview1 (#1632)
28c090ed0 Replaced custom platform constraint values with aliases to `@platforms` (#1652)
dfbea4f52 Deprecated `rust_toolchain.rustc_srcs` (#1653)
fd1db4391 Remove deprecated attributes from rust_toolchain and cargo_bootstrap (#1651)
c8ab970c4 Generated rust-project.json files now include sysroot paths (#1641)
0a3e04cf9 Fix vendoring when not in a package (#1646)
aece1e37d Deduplicate expand_location targets in rust-project.json crate creation to avoid a bazel crash (#1639)
03a0b2483 [docs] Fixing typos in CargoConfig doc strings (#1638)
bd4fd2ac5 Upgraded cfg-expr dependency to 0.12.0. (#1636)
330554a13 Disable failing job in CI (#1640)
849f106e6 Consider compilation mode when choosing `pic`/`nopic` object files to link (#1624)
53491d719 Updated rules_rust to version `0.12.0` (#1630)
8e8843724 Remove empty glob (#1628)
1f621a944 Added Rust 1.65.0 (#1627)
c6af4d025 Add `-c opt` mode to CI (#1621)
95320cc8b process_wrapper: print line on error to parse message as json (#1566)
81eaccf39 Fixed CI breakage (#1619)
478fc3a57 Fix ambiguous native dependencies in `proc_macro`s and `staticlib`s (#1611)
9e3d8415e Build deps of _build_script_run in 'exec' mode (#1561)
ea031082b Fixed outdated docs (#1614)
a8c540e49 Restore support for old cargo_build_script load statements (#1613)
295b5ccc7 Renamed `_build_script_run` rule to `cargo_build_script` (#1612)
3778069ec Remove references to Google mirror in docs (#1607)
aad54ba29 Updated crate_universe dependencies (#1606)
c349df2a6 Remove Google mirror from Starlark snippet in release notes (#1604)
0493b998d Avoid rendering a mock root package when possible (#1596)
b04aa053c process_wrapper: Apply substitutions to param files (#1565)
b209b3e15 Updated rules_rust to version `0.11.0`. (#1587)
b1079453b Typo correction on doc (#1593)
ca5678266 Updated crate_universe dependencies (#1591)
a364d448f Fixes crates_vendor labels in remote mode when used from the root workspace (#1575)
1cc37c268 Expose the output directory from cargo_build_script (#1588)
7ffe0a555 Ignore non-utf8 text in build script output (#1583)
c5b38fe00 Merge runfiles from transitive dependencies of rust_test crate attr (#1487)
da3d522d5 Fix build scripts targeting the wrong architecture (#1564)
d288ed634 Add `out_dir` support in `cargo_dep_env` (#1571)
78d6c1b46 fix: incorrect rustfmt edition query (#1582)
48927127e Set CARGO_MANIFEST_DIR at runtime for tests (#1559)
76bd69033 Add an output group for the .rmeta (#1585)
352bfeb05 Cleanup deprecated code (#1577)
86dc561f9 Move crate_root_src to utils (#1570)
beb554eb9 update to wasm-bindgen v0.2.83 (#1567)
73fd1616b Export AbsoluteLabel functionality (#1568)
c57e7a399 Remap $PWD to empty string instead of "." (#1563)
f0cdcedc2 Added Rust 1.64.0 (#1562)
1d326554a Update docs to show release policies and support (#1560)
78c793a0a Fix markdown typo in rust_analyzer.md (#1553)
c13980fb6 Add iOS examples (#1546)
8a5e07e9f Update apple_support (#1549)
6dacd9803 Strip leading '@'s for labels in the splicing manifest (#1547)
f73d1d6fb use crate_info.deps in establish_cc_info (#1543)
4845af6c0 Add android example (#1545)
9570b7aa7 Remove -lgcc from Android builds (#1541)
cb9ca1b81 Fix crate_universe/private/srcs.bzl to work with repo mappings (#1540)
d1fc9accc Minor cleanup of CI pipelines (#1534)
2bb077b3b Updated rules_rust to version 0.10.0 (#1533)
b8751b860 add cc config info to dummy wasm32 cc toolchain (#1532)
f5ed797ee Updates rust_test to use main.rs as the root when use_libtest_harness is false (#1518)
cfcaf21d5 Preserve directory structure of source files when some are generated (#1526)
51c065841 migrating to rbe_preconfig and remove bazel_toolchains (#1524)
055abd402 Fix typo in an example of crates_repository rule (#1520)
8bfed1cd2 Added Rust 1.63.0 (#1512)
3a69ce09b Update wasm_bindgen to 0.2.82 (#1513)
git-subtree-dir: third_party/rules_rust
git-subtree-split: bf9ddeb7c83a9fe8a7d87c76134cdd8e16131b62
Signed-off-by: Adam Snaider <adsnaider@gmail.com>
Change-Id: Id9490c68d6221da66953a915a25042ef8b848505
diff --git a/cargo/bootstrap/bootstrap_installer.rs b/cargo/bootstrap/bootstrap_installer.rs
index 32cb137..67239b7 100644
--- a/cargo/bootstrap/bootstrap_installer.rs
+++ b/cargo/bootstrap/bootstrap_installer.rs
@@ -29,7 +29,7 @@
fn main() {
if let Err(err) = install() {
- eprintln!("{:?}", err);
+ eprintln!("{err:?}");
std::process::exit(1);
};
}
diff --git a/cargo/cargo_bootstrap.bzl b/cargo/cargo_bootstrap.bzl
index 509ea47..10a0cfa 100644
--- a/cargo/cargo_bootstrap.bzl
+++ b/cargo/cargo_bootstrap.bzl
@@ -178,26 +178,22 @@
_detect_changes(repository_ctx)
if repository_ctx.attr.version in ("beta", "nightly"):
- version_str = "{}-{}".format(repository_ctx.attr.version, repository_ctx.attr.iso_date)
+ channel = repository_ctx.attr.version
+ version = repository_ctx.attr.iso_date
else:
- version_str = repository_ctx.attr.version
+ channel = "stable"
+ version = repository_ctx.attr.version
host_triple = get_host_triple(repository_ctx)
-
- if repository_ctx.attr.rust_toolchain_repository_template:
- # buildifier: disable=print
- print("Warning: `rust_toolchain_repository_template` is deprecated. Please use `rust_toolchain_cargo_template` and `rust_toolchain_rustc_template`")
- cargo_template = "@{}{}".format(repository_ctx.attr.rust_toolchain_repository_template, "//:bin/{tool}")
- rustc_template = "@{}{}".format(repository_ctx.attr.rust_toolchain_repository_template, "//:bin/{tool}")
- else:
- cargo_template = repository_ctx.attr.rust_toolchain_cargo_template
- rustc_template = repository_ctx.attr.rust_toolchain_rustc_template
+ cargo_template = repository_ctx.attr.rust_toolchain_cargo_template
+ rustc_template = repository_ctx.attr.rust_toolchain_rustc_template
tools = get_rust_tools(
cargo_template = cargo_template,
rustc_template = rustc_template,
host_triple = host_triple,
- version = version_str,
+ channel = channel,
+ version = version,
)
binary_name = repository_ctx.attr.binary or repository_ctx.name
@@ -271,20 +267,19 @@
doc = (
"The template to use for finding the host `cargo` binary. `{version}` (eg. '1.53.0'), " +
"`{triple}` (eg. 'x86_64-unknown-linux-gnu'), `{arch}` (eg. 'aarch64'), `{vendor}` (eg. 'unknown'), " +
- "`{system}` (eg. 'darwin'), and `{tool}` (eg. 'rustc.exe') will be replaced in the string if present."
+ "`{system}` (eg. 'darwin'), `{channel}` (eg. 'stable'), and `{tool}` (eg. 'rustc.exe') will be " +
+ "replaced in the string if present."
),
- default = "@rust_{system}_{arch}__{triple}_tools//:bin/{tool}",
- ),
- "rust_toolchain_repository_template": attr.string(
- doc = "**Deprecated**: Please use `rust_toolchain_cargo_template` and `rust_toolchain_rustc_template`",
+ default = "@rust_{system}_{arch}__{triple}__{channel}_tools//:bin/{tool}",
),
"rust_toolchain_rustc_template": attr.string(
doc = (
"The template to use for finding the host `rustc` binary. `{version}` (eg. '1.53.0'), " +
"`{triple}` (eg. 'x86_64-unknown-linux-gnu'), `{arch}` (eg. 'aarch64'), `{vendor}` (eg. 'unknown'), " +
- "`{system}` (eg. 'darwin'), and `{tool}` (eg. 'rustc.exe') will be replaced in the string if present."
+ "`{system}` (eg. 'darwin'), `{channel}` (eg. 'stable'), and `{tool}` (eg. 'rustc.exe') will be " +
+ "replaced in the string if present."
),
- default = "@rust_{system}_{arch}__{triple}_tools//:bin/{tool}",
+ default = "@rust_{system}_{arch}__{triple}__{channel}_tools//:bin/{tool}",
),
"srcs": attr.label_list(
doc = "Souce files of the crate to build. Passing source files here can be used to trigger rebuilds when changes are made",
diff --git a/cargo/cargo_build_script.bzl b/cargo/cargo_build_script.bzl
index 87ee88e..af21a91 100644
--- a/cargo/cargo_build_script.bzl
+++ b/cargo/cargo_build_script.bzl
@@ -1,498 +1,16 @@
-# buildifier: disable=module-docstring
-load("@bazel_skylib//lib:paths.bzl", "paths")
-load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "CPP_COMPILE_ACTION_NAME", "C_COMPILE_ACTION_NAME")
-load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
-load("//rust:defs.bzl", "rust_binary", "rust_common")
+"""Legacy load locations for Cargo build script rules
-# buildifier: disable=bzl-visibility
-load("//rust/private:providers.bzl", _DepInfo = "DepInfo")
+Instead, `defs.bzl` should be used.
+"""
-# buildifier: disable=bzl-visibility
-load("//rust/private:rustc.bzl", "BuildInfo", "get_compilation_mode_opts", "get_linker_and_args")
-
-# buildifier: disable=bzl-visibility
-load("//rust/private:utils.bzl", "dedent", "expand_dict_value_locations", "find_cc_toolchain", "find_toolchain", "name_to_crate_name")
-
-def get_cc_compile_args_and_env(cc_toolchain, feature_configuration):
- """Gather cc environment variables from the given `cc_toolchain`
-
- Args:
- cc_toolchain (cc_toolchain): The current rule's `cc_toolchain`.
- feature_configuration (FeatureConfiguration): Class used to construct command lines from CROSSTOOL features.
-
- Returns:
- tuple: A tuple of the following items:
- - (sequence): A flattened C command line flags for given action.
- - (sequence): A flattened CXX command line flags for given action.
- - (dict): C environment variables to be set for given action.
- """
- compile_variables = cc_common.create_compile_variables(
- feature_configuration = feature_configuration,
- cc_toolchain = cc_toolchain,
- )
- cc_c_args = cc_common.get_memory_inefficient_command_line(
- feature_configuration = feature_configuration,
- action_name = C_COMPILE_ACTION_NAME,
- variables = compile_variables,
- )
- cc_cxx_args = cc_common.get_memory_inefficient_command_line(
- feature_configuration = feature_configuration,
- action_name = CPP_COMPILE_ACTION_NAME,
- variables = compile_variables,
- )
- cc_env = cc_common.get_environment_variables(
- feature_configuration = feature_configuration,
- action_name = C_COMPILE_ACTION_NAME,
- variables = compile_variables,
- )
- return cc_c_args, cc_cxx_args, cc_env
-
-def _pwd_flags(args):
- """Prefix execroot-relative paths of known arguments with ${pwd}.
-
- Args:
- args (list): List of tool arguments.
-
- Returns:
- list: The modified argument list.
- """
- res = []
- for arg in args:
- s, opt, path = arg.partition("--sysroot=")
- if s == "" and not paths.is_absolute(path):
- res.append("{}${{pwd}}/{}".format(opt, path))
- else:
- res.append(arg)
- return res
-
-def _build_script_impl(ctx):
- """The implementation for the `_build_script_run` rule.
-
- Args:
- ctx (ctx): The rules context object
-
- Returns:
- list: A list containing a BuildInfo provider
- """
- script = ctx.executable.script
- 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")
- dep_env_out = ctx.actions.declare_file(ctx.label.name + ".depenv")
- 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
-
- streams = struct(
- stdout = ctx.actions.declare_file(ctx.label.name + ".stdout.log"),
- stderr = ctx.actions.declare_file(ctx.label.name + ".stderr.log"),
- )
-
- pkg_name = _name_to_pkg_name(ctx.label.name)
-
- toolchain_tools = [toolchain.all_files]
-
- cc_toolchain = find_cpp_toolchain(ctx)
-
- # Start with the default shell env, which contains any --action_env
- # settings passed in on the command line.
- env = dict(ctx.configuration.default_shell_env)
-
- env.update({
- "CARGO_CRATE_NAME": name_to_crate_name(pkg_name),
- "CARGO_MANIFEST_DIR": manifest_dir,
- "CARGO_PKG_NAME": pkg_name,
- "HOST": toolchain.exec_triple,
- "NUM_JOBS": "1",
- "OPT_LEVEL": compilation_mode_opt_level,
- "RUSTC": toolchain.rustc.path,
- "TARGET": toolchain.target_flag_value,
- # OUT_DIR is set by the runner itself, rather than on the action.
- })
-
- # This isn't exactly right, but Bazel doesn't have exact views of "debug" and "release", so...
- env.update({
- "DEBUG": {"dbg": "true", "fastbuild": "true", "opt": "false"}.get(ctx.var["COMPILATION_MODE"], "true"),
- "PROFILE": {"dbg": "debug", "fastbuild": "debug", "opt": "release"}.get(ctx.var["COMPILATION_MODE"], "unknown"),
- })
-
- if ctx.attr.version:
- version = ctx.attr.version.split("+")[0].split(".")
- patch = version[2].split("-") if len(version) > 2 else [""]
- env["CARGO_PKG_VERSION_MAJOR"] = version[0]
- env["CARGO_PKG_VERSION_MINOR"] = version[1] if len(version) > 1 else ""
- env["CARGO_PKG_VERSION_PATCH"] = patch[0]
- env["CARGO_PKG_VERSION_PRE"] = patch[1] if len(patch) > 1 else ""
- env["CARGO_PKG_VERSION"] = ctx.attr.version
-
- # Pull in env vars which may be required for the cc_toolchain to work (e.g. on OSX, the SDK version).
- # We hope that the linker env is sufficient for the whole cc_toolchain.
- cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
- linker, link_args, linker_env = get_linker_and_args(ctx, ctx.attr, cc_toolchain, feature_configuration, None)
- env.update(**linker_env)
- env["LD"] = linker
- env["LDFLAGS"] = " ".join(_pwd_flags(link_args))
-
- # MSVC requires INCLUDE to be set
- cc_c_args, cc_cxx_args, cc_env = get_cc_compile_args_and_env(cc_toolchain, feature_configuration)
- include = cc_env.get("INCLUDE")
- if include:
- env["INCLUDE"] = include
-
- if cc_toolchain:
- toolchain_tools.append(cc_toolchain.all_files)
-
- cc_executable = cc_toolchain.compiler_executable
- if cc_executable:
- env["CC"] = cc_executable
- env["CXX"] = cc_executable
- ar_executable = cc_toolchain.ar_executable
- if ar_executable:
- env["AR"] = ar_executable
-
- # Populate CFLAGS and CXXFLAGS that cc-rs relies on when building from source, in particular
- # to determine the deployment target when building for apple platforms (`macosx-version-min`
- # for example, itself derived from the `macos_minimum_os` Bazel argument).
- env["CFLAGS"] = " ".join(_pwd_flags(cc_c_args))
- env["CXXFLAGS"] = " ".join(_pwd_flags(cc_cxx_args))
-
- # Inform build scripts of rustc flags
- # https://github.com/rust-lang/cargo/issues/9600
- env["CARGO_ENCODED_RUSTFLAGS"] = "\\x1f".join([
- # Allow build scripts to locate the generated sysroot
- "--sysroot=${{pwd}}/{}".format(toolchain.sysroot),
- ] + ctx.attr.rustc_flags)
-
- for f in ctx.attr.crate_features:
- env["CARGO_FEATURE_" + f.upper().replace("-", "_")] = "1"
-
- # Add environment variables from the Rust toolchain.
- env.update(toolchain.env)
-
- env.update(expand_dict_value_locations(
- ctx,
- ctx.attr.build_script_env,
- getattr(ctx.attr, "data", []) +
- getattr(ctx.attr, "compile_data", []) +
- getattr(ctx.attr, "tools", []),
- ))
-
- tools = depset(
- direct = [
- script,
- ctx.executable._cargo_build_script_runner,
- ] + ctx.files.data + ctx.files.tools + ([toolchain.target_json] if toolchain.target_json else []),
- transitive = toolchain_tools,
- )
-
- links = ctx.attr.links or ""
-
- # dep_env_file contains additional environment variables coming from
- # direct dependency sys-crates' build scripts. These need to be made
- # available to the current crate build script.
- # See https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages
- # for details.
- args = ctx.actions.args()
- args.add_all([
- script.path,
- links,
- out_dir.path,
- env_out.path,
- flags_out.path,
- link_flags.path,
- link_search_paths.path,
- dep_env_out.path,
- streams.stdout.path,
- streams.stderr.path,
- ])
- build_script_inputs = []
- for dep in ctx.attr.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
- args.add(dep_env_file.path)
- build_script_inputs.append(dep_env_file)
- for dep_build_info in dep[rust_common.dep_info].transitive_build_infos.to_list():
- build_script_inputs.append(dep_build_info.out_dir)
-
- ctx.actions.run(
- executable = ctx.executable._cargo_build_script_runner,
- arguments = [args],
- outputs = [out_dir, env_out, flags_out, link_flags, link_search_paths, dep_env_out, streams.stdout, streams.stderr],
- tools = tools,
- inputs = build_script_inputs,
- mnemonic = "CargoBuildScriptRun",
- progress_message = "Running Cargo build script {}".format(pkg_name),
- env = env,
- )
-
- return [
- BuildInfo(
- out_dir = out_dir,
- rustc_env = env_out,
- dep_env = dep_env_out,
- flags = flags_out,
- link_flags = link_flags,
- link_search_paths = link_search_paths,
- ),
- OutputGroupInfo(streams = depset([streams.stdout, streams.stderr])),
- ]
-
-_build_script_run = rule(
- doc = (
- "A rule for running a crate's `build.rs` files to generate build information " +
- "which is then used to determine how to compile said crate."
- ),
- implementation = _build_script_impl,
- attrs = {
- "build_script_env": attr.string_dict(
- doc = "Environment variables for build scripts.",
- ),
- "crate_features": attr.string_list(
- doc = "The list of rust features that the build script should consider activated.",
- ),
- "data": attr.label_list(
- doc = "Data required by the build script.",
- allow_files = True,
- ),
- "deps": attr.label_list(
- doc = "The Rust dependencies of the crate",
- providers = [rust_common.dep_info],
- ),
- "links": attr.string(
- doc = "The name of the native library this crate links against.",
- ),
- "rustc_flags": attr.string_list(
- doc = dedent("""\
- List of compiler flags passed to `rustc`.
-
- These strings are subject to Make variable expansion for predefined
- source/output path variables like `$location`, `$execpath`, and
- `$rootpath`. This expansion is useful if you wish to pass a generated
- file of arguments to rustc: `@$(location //package:target)`.
- """),
- ),
- # The source of truth will be the `cargo_build_script` macro until stardoc
- # implements documentation inheritence. See https://github.com/bazelbuild/stardoc/issues/27
- "script": attr.label(
- doc = "The binary script to run, generally a `rust_binary` target.",
- executable = True,
- allow_files = True,
- mandatory = True,
- cfg = "exec",
- ),
- "tools": attr.label_list(
- doc = "Tools required by the build script.",
- allow_files = True,
- cfg = "exec",
- ),
- "version": attr.string(
- doc = "The semantic version (semver) of the crate",
- ),
- "_cargo_build_script_runner": attr.label(
- executable = True,
- allow_files = True,
- default = Label("//cargo/cargo_build_script_runner:cargo_build_script_runner"),
- cfg = "exec",
- ),
- "_cc_toolchain": attr.label(
- default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
- ),
- },
- fragments = ["cpp"],
- toolchains = [
- str(Label("//rust:toolchain_type")),
- "@bazel_tools//tools/cpp:toolchain_type",
- ],
- incompatible_use_toolchain_transition = True,
+load(
+ "//cargo/private:cargo_build_script.bzl",
+ _cargo_dep_env = "cargo_dep_env",
+)
+load(
+ "//cargo/private:cargo_build_script_wrapper.bzl",
+ _cargo_build_script = "cargo_build_script",
)
-def cargo_build_script(
- name,
- crate_features = [],
- version = None,
- deps = [],
- build_script_env = {},
- data = [],
- tools = [],
- links = None,
- rustc_env = {},
- rustc_flags = [],
- visibility = None,
- tags = None,
- **kwargs):
- """Compile and execute a rust build script to generate build attributes
-
- This rules take the same arguments as rust_binary.
-
- Example:
-
- Suppose you have a crate with a cargo build script `build.rs`:
-
- ```output
- [workspace]/
- hello_lib/
- BUILD
- build.rs
- src/
- lib.rs
- ```
-
- Then you want to use the build script in the following:
-
- `hello_lib/BUILD`:
- ```python
- package(default_visibility = ["//visibility:public"])
-
- load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library")
- load("@rules_rust//cargo:cargo_build_script.bzl", "cargo_build_script")
-
- # This will run the build script from the root of the workspace, and
- # collect the outputs.
- cargo_build_script(
- name = "build_script",
- srcs = ["build.rs"],
- # Optional environment variables passed during build.rs compilation
- rustc_env = {
- "CARGO_PKG_VERSION": "0.1.2",
- },
- # Optional environment variables passed during build.rs execution.
- # Note that as the build script's working directory is not execroot,
- # execpath/location will return an absolute path, instead of a relative
- # one.
- build_script_env = {
- "SOME_TOOL_OR_FILE": "$(execpath @tool//:binary)"
- }
- # Optional data/tool dependencies
- data = ["@tool//:binary"],
- )
-
- rust_library(
- name = "hello_lib",
- srcs = [
- "src/lib.rs",
- ],
- deps = [":build_script"],
- )
- ```
-
- The `hello_lib` target will be build with the flags and the environment variables declared by the \
- build script in addition to the file generated by it.
-
- Args:
- name (str): The name for the underlying rule. This should be the name of the package being compiled, optionally with a suffix of _build_script.
- crate_features (list, optional): A list of features to enable for the build script.
- version (str, optional): The semantic version (semver) of the crate.
- deps (list, optional): The dependencies of the crate.
- build_script_env (dict, optional): Environment variables for build scripts.
- data (list, optional): Files needed by the build script.
- tools (list, optional): Tools (executables) needed by the build script.
- links (str, optional): Name of the native library this crate links against.
- rustc_env (dict, optional): Environment variables to set in rustc when compiling the build script.
- rustc_flags (list, optional): List of compiler flags passed to `rustc`.
- visibility (list of label, optional): Visibility to apply to the generated build script output.
- tags: (list of str, optional): Tags to apply to the generated build script output.
- **kwargs: Forwards to the underlying `rust_binary` rule.
- """
-
- # This duplicates the code in _build_script_impl because we need to make these available both when we invoke rustc (this code) and when we run the compiled build script (_build_script_impl).
- # https://github.com/bazelbuild/rules_rust/issues/661 will hopefully remove this duplication.
- rustc_env = dict(rustc_env)
- if "CARGO_PKG_NAME" not in rustc_env:
- rustc_env["CARGO_PKG_NAME"] = _name_to_pkg_name(name)
- if "CARGO_CRATE_NAME" not in rustc_env:
- rustc_env["CARGO_CRATE_NAME"] = name_to_crate_name(_name_to_pkg_name(name))
-
- binary_tags = [tag for tag in tags or []]
- if "manual" not in binary_tags:
- binary_tags.append("manual")
-
- rust_binary(
- name = name + "_",
- crate_features = crate_features,
- version = version,
- deps = deps,
- data = data,
- rustc_env = rustc_env,
- rustc_flags = rustc_flags,
- tags = binary_tags,
- **kwargs
- )
- _build_script_run(
- name = name,
- script = ":{}_".format(name),
- crate_features = crate_features,
- version = version,
- build_script_env = build_script_env,
- links = links,
- deps = deps,
- data = data,
- tools = tools,
- rustc_flags = rustc_flags,
- visibility = visibility,
- tags = tags,
- )
-
-def _name_to_pkg_name(name):
- if name.endswith("_build_script"):
- return name[:-len("_build_script")]
- return name
-
-def _cargo_dep_env_implementation(ctx):
- empty_file = ctx.actions.declare_file(ctx.label.name + ".empty_file")
- empty_dir = ctx.actions.declare_directory(ctx.label.name + ".empty_dir")
- ctx.actions.write(
- output = empty_file,
- content = "",
- )
- ctx.actions.run(
- outputs = [empty_dir],
- executable = "true",
- )
- return [
- DefaultInfo(files = depset(ctx.files.src)),
- BuildInfo(
- dep_env = empty_file,
- flags = empty_file,
- link_flags = empty_file,
- link_search_paths = empty_file,
- out_dir = empty_dir,
- rustc_env = empty_file,
- ),
- _DepInfo(
- dep_env = ctx.file.src,
- direct_crates = depset(),
- link_search_path_files = depset(),
- transitive_build_infos = depset(),
- transitive_crate_outputs = depset(),
- transitive_crates = depset(),
- transitive_noncrates = depset(),
- ),
- ]
-
-cargo_dep_env = rule(
- implementation = _cargo_dep_env_implementation,
- doc = (
- "A rule for generating variables for dependent `cargo_build_script`s " +
- "without a build script. This is useful for using Bazel rules instead " +
- "of a build script, while also generating configuration information " +
- "for build scripts which depend on this crate."
- ),
- attrs = {
- "src": attr.label(
- doc = dedent("""\
- File containing additional environment variables to set for build scripts of direct dependencies.
-
- This has the same effect as a `cargo_build_script` which prints
- `cargo:VAR=VALUE` lines, but without requiring a build script.
-
- This files should contain a single variable per line, of format
- `NAME=value`, and newlines may be included in a value by ending a
- line with a trailing back-slash (`\\\\`).
- """),
- allow_single_file = True,
- mandatory = True,
- ),
- },
-)
+cargo_build_script = _cargo_build_script
+cargo_dep_env = _cargo_dep_env
diff --git a/cargo/cargo_build_script_runner/bin.rs b/cargo/cargo_build_script_runner/bin.rs
index 9e40fef..b7b78c2 100644
--- a/cargo/cargo_build_script_runner/bin.rs
+++ b/cargo/cargo_build_script_runner/bin.rs
@@ -32,7 +32,7 @@
let exec_root = env::current_dir().expect("Failed to get current directory");
let manifest_dir_env = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR was not set");
let rustc_env = env::var("RUSTC").expect("RUSTC was not set");
- let manifest_dir = exec_root.join(&manifest_dir_env);
+ let manifest_dir = exec_root.join(manifest_dir_env);
let rustc = exec_root.join(&rustc_env);
let Options {
progname,
@@ -48,15 +48,36 @@
input_dep_env_paths,
} = parse_args()?;
- let out_dir_abs = exec_root.join(&out_dir);
+ let out_dir_abs = exec_root.join(out_dir);
// For some reason Google's RBE does not create the output directory, force create it.
create_dir_all(&out_dir_abs)
.unwrap_or_else(|_| panic!("Failed to make output directory: {:?}", out_dir_abs));
+ if should_symlink_exec_root() {
+ // Symlink the execroot to the manifest_dir so that we can use relative paths in the arguments.
+ let exec_root_paths = std::fs::read_dir(&exec_root)
+ .map_err(|err| format!("Failed while listing exec root: {err:?}"))?;
+ for path in exec_root_paths {
+ let path = path
+ .map_err(|err| {
+ format!("Failed while getting path from exec root listing: {err:?}")
+ })?
+ .path();
+
+ let file_name = path
+ .file_name()
+ .ok_or_else(|| "Failed while getting file name".to_string())?;
+ let link = manifest_dir.join(file_name);
+
+ symlink_if_not_exists(&path, &link)
+ .map_err(|err| format!("Failed to symlink {path:?} to {link:?}: {err}"))?;
+ }
+ }
+
let target_env_vars =
get_target_env_vars(&rustc_env).expect("Error getting target env vars from rustc");
- let mut command = Command::new(exec_root.join(&progname));
+ let mut command = Command::new(exec_root.join(progname));
command
.current_dir(&manifest_dir)
.envs(target_env_vars)
@@ -127,7 +148,7 @@
format!(
"Build script process failed{}\n--stdout:\n{}\n--stderr:\n{}",
if let Some(exit_code) = process_output.status.code() {
- format!(" with exit code {}", exit_code)
+ format!(" with exit code {exit_code}")
} else {
String::new()
},
@@ -174,6 +195,42 @@
Ok(())
}
+fn should_symlink_exec_root() -> bool {
+ env::var("RULES_RUST_SYMLINK_EXEC_ROOT")
+ .map(|s| s == "1")
+ .unwrap_or(false)
+}
+
+/// Create a symlink from `link` to `original` if `link` doesn't already exist.
+#[cfg(windows)]
+fn symlink_if_not_exists(original: &Path, link: &Path) -> Result<(), String> {
+ if original.is_dir() {
+ std::os::windows::fs::symlink_dir(original, link)
+ .or_else(swallow_already_exists)
+ .map_err(|err| format!("Failed to create directory symlink: {err}"))
+ } else {
+ std::os::windows::fs::symlink_file(original, link)
+ .or_else(swallow_already_exists)
+ .map_err(|err| format!("Failed to create file symlink: {err}"))
+ }
+}
+
+/// Create a symlink from `link` to `original` if `link` doesn't already exist.
+#[cfg(not(windows))]
+fn symlink_if_not_exists(original: &Path, link: &Path) -> Result<(), String> {
+ std::os::unix::fs::symlink(original, link)
+ .or_else(swallow_already_exists)
+ .map_err(|err| format!("Failed to create symlink: {err}"))
+}
+
+fn swallow_already_exists(err: std::io::Error) -> std::io::Result<()> {
+ if err.kind() == std::io::ErrorKind::AlreadyExists {
+ Ok(())
+ } else {
+ Err(err)
+ }
+}
+
/// A representation of expected command line arguments.
struct Options {
progname: String,
@@ -236,15 +293,14 @@
env::var("TARGET").expect("missing TARGET")
))
.output()
- .map_err(|err| format!("Error running rustc to get target information: {}", err))?;
+ .map_err(|err| format!("Error running rustc to get target information: {err}"))?;
if !output.status.success() {
return Err(format!(
- "Error running rustc to get target information: {:?}",
- output
+ "Error running rustc to get target information: {output:?}",
));
}
let stdout = std::str::from_utf8(&output.stdout)
- .map_err(|err| format!("Non-UTF8 stdout from rustc: {:?}", err))?;
+ .map_err(|err| format!("Non-UTF8 stdout from rustc: {err:?}"))?;
Ok(parse_rustc_cfg_output(stdout))
}
@@ -280,7 +336,7 @@
Ok(_) => 0,
Err(err) => {
// Neatly print errors
- eprintln!("{}", err);
+ eprintln!("{err}");
1
}
});
diff --git a/cargo/cargo_build_script_runner/lib.rs b/cargo/cargo_build_script_runner/lib.rs
index b1aa793..8a1b765 100644
--- a/cargo/cargo_build_script_runner/lib.rs
+++ b/cargo/cargo_build_script_runner/lib.rs
@@ -103,12 +103,19 @@
/// Converts a [BufReader] into a vector of [BuildScriptOutput] enums.
fn outputs_from_reader<T: Read>(mut reader: BufReader<T>) -> Vec<BuildScriptOutput> {
let mut result = Vec::<BuildScriptOutput>::new();
- let mut line = String::new();
- while reader.read_line(&mut line).expect("Cannot read line") != 0 {
- if let Some(bso) = BuildScriptOutput::new(&line) {
- result.push(bso);
+ let mut buf = Vec::new();
+ while reader
+ .read_until(b'\n', &mut buf)
+ .expect("Cannot read line")
+ != 0
+ {
+ // like cargo, ignore any lines that are not valid utf8
+ if let Ok(line) = String::from_utf8(buf.clone()) {
+ if let Some(bso) = BuildScriptOutput::new(&line) {
+ result.push(bso);
+ }
}
- line.clear();
+ buf.clear();
}
result
}
@@ -176,11 +183,11 @@
for flag in outputs {
match flag {
- BuildScriptOutput::Cfg(e) => compile_flags.push(format!("--cfg={}", e)),
+ BuildScriptOutput::Cfg(e) => compile_flags.push(format!("--cfg={e}")),
BuildScriptOutput::Flags(e) => compile_flags.push(e.to_owned()),
- BuildScriptOutput::LinkArg(e) => compile_flags.push(format!("-Clink-arg={}", e)),
- BuildScriptOutput::LinkLib(e) => link_flags.push(format!("-l{}", e)),
- BuildScriptOutput::LinkSearch(e) => link_search_paths.push(format!("-L{}", e)),
+ BuildScriptOutput::LinkArg(e) => compile_flags.push(format!("-Clink-arg={e}")),
+ BuildScriptOutput::LinkLib(e) => link_flags.push(format!("-l{e}")),
+ BuildScriptOutput::LinkSearch(e) => link_search_paths.push(format!("-L{e}")),
_ => {}
}
}
@@ -232,11 +239,11 @@
cargo:rustc-env=SOME_PATH=/some/absolute/path/beep
cargo:rustc-link-arg=-weak_framework
cargo:rustc-link-arg=Metal
-",
+cargo:rustc-env=no_trailing_newline=true",
);
let reader = BufReader::new(buff);
let result = BuildScriptOutput::outputs_from_reader(reader);
- assert_eq!(result.len(), 12);
+ assert_eq!(result.len(), 13);
assert_eq!(result[0], BuildScriptOutput::LinkLib("sdfsdf".to_owned()));
assert_eq!(result[1], BuildScriptOutput::Env("FOO=BAR".to_owned()));
assert_eq!(
@@ -266,14 +273,17 @@
BuildScriptOutput::LinkArg("-weak_framework".to_owned())
);
assert_eq!(result[11], BuildScriptOutput::LinkArg("Metal".to_owned()));
-
+ assert_eq!(
+ result[12],
+ BuildScriptOutput::Env("no_trailing_newline=true".to_owned())
+ );
assert_eq!(
BuildScriptOutput::outputs_to_dep_env(&result, "ssh2", "/some/absolute/path"),
"DEP_SSH2_VERSION=123\nDEP_SSH2_VERSION_NUMBER=1010107f\nDEP_SSH2_INCLUDE_PATH=${pwd}/include".to_owned()
);
assert_eq!(
BuildScriptOutput::outputs_to_env(&result, "/some/absolute/path"),
- "FOO=BAR\nBAR=FOO\nSOME_PATH=${pwd}/beep".to_owned()
+ "FOO=BAR\nBAR=FOO\nSOME_PATH=${pwd}/beep\nno_trailing_newline=true".to_owned()
);
assert_eq!(
BuildScriptOutput::outputs_to_flags(&result, "/some/absolute/path"),
@@ -288,4 +298,22 @@
}
);
}
+
+ #[test]
+ fn invalid_utf8() {
+ let buff = Cursor::new(
+ b"
+cargo:rustc-env=valid1=1
+cargo:rustc-env=invalid=\xc3\x28
+cargo:rustc-env=valid2=2
+",
+ );
+ let reader = BufReader::new(buff);
+ let result = BuildScriptOutput::outputs_from_reader(reader);
+ assert_eq!(result.len(), 2);
+ assert_eq!(
+ &BuildScriptOutput::outputs_to_env(&result, "/some/absolute/path"),
+ "valid1=1\nvalid2=2"
+ );
+ }
}
diff --git a/cargo/defs.bzl b/cargo/defs.bzl
index 0ca086b..2801805 100644
--- a/cargo/defs.bzl
+++ b/cargo/defs.bzl
@@ -1,9 +1,21 @@
"""Common definitions for the `@rules_rust//cargo` package"""
-load(":cargo_bootstrap.bzl", _cargo_bootstrap_repository = "cargo_bootstrap_repository", _cargo_env = "cargo_env")
-load(":cargo_build_script.bzl", _cargo_build_script = "cargo_build_script")
+load(
+ "//cargo/private:cargo_build_script.bzl",
+ _cargo_dep_env = "cargo_dep_env",
+)
+load(
+ "//cargo/private:cargo_build_script_wrapper.bzl",
+ _cargo_build_script = "cargo_build_script",
+)
+load(
+ ":cargo_bootstrap.bzl",
+ _cargo_bootstrap_repository = "cargo_bootstrap_repository",
+ _cargo_env = "cargo_env",
+)
cargo_bootstrap_repository = _cargo_bootstrap_repository
cargo_env = _cargo_env
cargo_build_script = _cargo_build_script
+cargo_dep_env = _cargo_dep_env
diff --git a/cargo/features.bzl b/cargo/features.bzl
new file mode 100644
index 0000000..29b9921
--- /dev/null
+++ b/cargo/features.bzl
@@ -0,0 +1,6 @@
+"""Public Cargo features for Bazel."""
+
+# `symlink-exec-root` feature will symlink the execroot to the build script execution directory.
+#
+# This is useful for building with hermetic C++ toolchains.
+SYMLINK_EXEC_ROOT_FEATURE = "symlink-exec-root"
diff --git a/cargo/private/cargo_build_script.bzl b/cargo/private/cargo_build_script.bzl
new file mode 100644
index 0000000..959ce25
--- /dev/null
+++ b/cargo/private/cargo_build_script.bzl
@@ -0,0 +1,454 @@
+"""Rules for Cargo build scripts (`build.rs` files)"""
+
+load("@bazel_skylib//lib:paths.bzl", "paths")
+load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "CPP_COMPILE_ACTION_NAME", "C_COMPILE_ACTION_NAME")
+load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
+load("//cargo:features.bzl", "SYMLINK_EXEC_ROOT_FEATURE")
+load("//rust:defs.bzl", "rust_common")
+
+# buildifier: disable=bzl-visibility
+load("//rust/private:providers.bzl", _DepInfo = "DepInfo")
+
+# buildifier: disable=bzl-visibility
+load("//rust/private:rustc.bzl", "BuildInfo", "get_compilation_mode_opts", "get_linker_and_args")
+
+# buildifier: disable=bzl-visibility
+load("//rust/private:utils.bzl", "dedent", "expand_dict_value_locations", "find_cc_toolchain", "find_toolchain", _name_to_crate_name = "name_to_crate_name")
+load(":features.bzl", "feature_enabled")
+
+# Reexport for cargo_build_script_wrapper.bzl
+name_to_crate_name = _name_to_crate_name
+
+def get_cc_compile_args_and_env(cc_toolchain, feature_configuration):
+ """Gather cc environment variables from the given `cc_toolchain`
+
+ Args:
+ cc_toolchain (cc_toolchain): The current rule's `cc_toolchain`.
+ feature_configuration (FeatureConfiguration): Class used to construct command lines from CROSSTOOL features.
+
+ Returns:
+ tuple: A tuple of the following items:
+ - (sequence): A flattened C command line flags for given action.
+ - (sequence): A flattened CXX command line flags for given action.
+ - (dict): C environment variables to be set for given action.
+ """
+ compile_variables = cc_common.create_compile_variables(
+ feature_configuration = feature_configuration,
+ cc_toolchain = cc_toolchain,
+ )
+ cc_c_args = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = C_COMPILE_ACTION_NAME,
+ variables = compile_variables,
+ )
+ cc_cxx_args = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = CPP_COMPILE_ACTION_NAME,
+ variables = compile_variables,
+ )
+ cc_env = cc_common.get_environment_variables(
+ feature_configuration = feature_configuration,
+ action_name = C_COMPILE_ACTION_NAME,
+ variables = compile_variables,
+ )
+ return cc_c_args, cc_cxx_args, cc_env
+
+def _pwd_flags(args):
+ """Prefix execroot-relative paths of known arguments with ${pwd}.
+
+ Args:
+ args (list): List of tool arguments.
+
+ Returns:
+ list: The modified argument list.
+ """
+ res = []
+ for arg in args:
+ s, opt, path = arg.partition("--sysroot=")
+ if s == "" and not paths.is_absolute(path):
+ res.append("{}${{pwd}}/{}".format(opt, path))
+ else:
+ res.append(arg)
+ return res
+
+def _cargo_build_script_impl(ctx):
+ """The implementation for the `cargo_build_script` rule.
+
+ Args:
+ ctx (ctx): The rules context object
+
+ Returns:
+ list: A list containing a BuildInfo provider
+ """
+ script = ctx.executable.script
+ 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")
+ dep_env_out = ctx.actions.declare_file(ctx.label.name + ".depenv")
+ 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
+
+ streams = struct(
+ stdout = ctx.actions.declare_file(ctx.label.name + ".stdout.log"),
+ stderr = ctx.actions.declare_file(ctx.label.name + ".stderr.log"),
+ )
+
+ pkg_name = name_to_pkg_name(ctx.label.name)
+
+ toolchain_tools = [toolchain.all_files]
+
+ cc_toolchain = find_cpp_toolchain(ctx)
+
+ # Start with the default shell env, which contains any --action_env
+ # settings passed in on the command line.
+ env = dict(ctx.configuration.default_shell_env)
+
+ env.update({
+ "CARGO_CRATE_NAME": name_to_crate_name(pkg_name),
+ "CARGO_MANIFEST_DIR": manifest_dir,
+ "CARGO_PKG_NAME": pkg_name,
+ "HOST": toolchain.exec_triple.str,
+ "NUM_JOBS": "1",
+ "OPT_LEVEL": compilation_mode_opt_level,
+ "RUSTC": toolchain.rustc.path,
+ "TARGET": toolchain.target_flag_value,
+ # OUT_DIR is set by the runner itself, rather than on the action.
+ })
+
+ # This isn't exactly right, but Bazel doesn't have exact views of "debug" and "release", so...
+ env.update({
+ "DEBUG": {"dbg": "true", "fastbuild": "true", "opt": "false"}.get(ctx.var["COMPILATION_MODE"], "true"),
+ "PROFILE": {"dbg": "debug", "fastbuild": "debug", "opt": "release"}.get(ctx.var["COMPILATION_MODE"], "unknown"),
+ })
+
+ if ctx.attr.version:
+ version = ctx.attr.version.split("+")[0].split(".")
+ patch = version[2].split("-") if len(version) > 2 else [""]
+ env["CARGO_PKG_VERSION_MAJOR"] = version[0]
+ env["CARGO_PKG_VERSION_MINOR"] = version[1] if len(version) > 1 else ""
+ env["CARGO_PKG_VERSION_PATCH"] = patch[0]
+ env["CARGO_PKG_VERSION_PRE"] = patch[1] if len(patch) > 1 else ""
+ env["CARGO_PKG_VERSION"] = ctx.attr.version
+
+ # Pull in env vars which may be required for the cc_toolchain to work (e.g. on OSX, the SDK version).
+ # We hope that the linker env is sufficient for the whole cc_toolchain.
+ cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
+ linker, link_args, linker_env = get_linker_and_args(ctx, ctx.attr, "bin", cc_toolchain, feature_configuration, None)
+ env.update(**linker_env)
+ env["LD"] = linker
+ env["LDFLAGS"] = " ".join(_pwd_flags(link_args))
+
+ # MSVC requires INCLUDE to be set
+ cc_c_args, cc_cxx_args, cc_env = get_cc_compile_args_and_env(cc_toolchain, feature_configuration)
+ include = cc_env.get("INCLUDE")
+ if include:
+ env["INCLUDE"] = include
+
+ if cc_toolchain:
+ toolchain_tools.append(cc_toolchain.all_files)
+
+ cc_executable = cc_toolchain.compiler_executable
+ if cc_executable:
+ env["CC"] = cc_executable
+ env["CXX"] = cc_executable
+ ar_executable = cc_toolchain.ar_executable
+ if ar_executable:
+ env["AR"] = ar_executable
+
+ # Populate CFLAGS and CXXFLAGS that cc-rs relies on when building from source, in particular
+ # to determine the deployment target when building for apple platforms (`macosx-version-min`
+ # for example, itself derived from the `macos_minimum_os` Bazel argument).
+ env["CFLAGS"] = " ".join(_pwd_flags(cc_c_args))
+ env["CXXFLAGS"] = " ".join(_pwd_flags(cc_cxx_args))
+
+ # Inform build scripts of rustc flags
+ # https://github.com/rust-lang/cargo/issues/9600
+ env["CARGO_ENCODED_RUSTFLAGS"] = "\\x1f".join([
+ # Allow build scripts to locate the generated sysroot
+ "--sysroot=${{pwd}}/{}".format(toolchain.sysroot),
+ ] + ctx.attr.rustc_flags)
+
+ for f in ctx.attr.crate_features:
+ env["CARGO_FEATURE_" + f.upper().replace("-", "_")] = "1"
+
+ # Add environment variables from the Rust toolchain.
+ env.update(toolchain.env)
+
+ # Gather data from the `toolchains` attribute.
+ for target in ctx.attr.toolchains:
+ if DefaultInfo in target:
+ toolchain_tools.extend([
+ target[DefaultInfo].files,
+ target[DefaultInfo].default_runfiles.files,
+ ])
+ if platform_common.ToolchainInfo in target:
+ all_files = getattr(target[platform_common.ToolchainInfo], "all_files", depset([]))
+ if type(all_files) == "list":
+ all_files = depset(all_files)
+ toolchain_tools.append(all_files)
+
+ _merge_env_dict(env, expand_dict_value_locations(
+ ctx,
+ ctx.attr.build_script_env,
+ getattr(ctx.attr, "data", []) +
+ getattr(ctx.attr, "compile_data", []) +
+ getattr(ctx.attr, "tools", []),
+ ))
+
+ tools = depset(
+ direct = [
+ script,
+ ctx.executable._cargo_build_script_runner,
+ ] + ctx.files.data + ctx.files.tools + ([toolchain.target_json] if toolchain.target_json else []),
+ transitive = toolchain_tools,
+ )
+
+ links = ctx.attr.links or ""
+
+ # dep_env_file contains additional environment variables coming from
+ # direct dependency sys-crates' build scripts. These need to be made
+ # available to the current crate build script.
+ # See https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages
+ # for details.
+ args = ctx.actions.args()
+ args.add_all([
+ script.path,
+ links,
+ out_dir.path,
+ env_out.path,
+ flags_out.path,
+ link_flags.path,
+ link_search_paths.path,
+ dep_env_out.path,
+ streams.stdout.path,
+ streams.stderr.path,
+ ])
+ build_script_inputs = []
+ for dep in ctx.attr.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
+ args.add(dep_env_file.path)
+ build_script_inputs.append(dep_env_file)
+ for dep_build_info in dep[rust_common.dep_info].transitive_build_infos.to_list():
+ build_script_inputs.append(dep_build_info.out_dir)
+
+ if feature_enabled(ctx, SYMLINK_EXEC_ROOT_FEATURE):
+ env["RULES_RUST_SYMLINK_EXEC_ROOT"] = "1"
+
+ ctx.actions.run(
+ executable = ctx.executable._cargo_build_script_runner,
+ arguments = [args],
+ outputs = [out_dir, env_out, flags_out, link_flags, link_search_paths, dep_env_out, streams.stdout, streams.stderr],
+ tools = tools,
+ inputs = build_script_inputs,
+ mnemonic = "CargoBuildScriptRun",
+ progress_message = "Running Cargo build script {}".format(pkg_name),
+ env = env,
+ )
+
+ return [
+ BuildInfo(
+ out_dir = out_dir,
+ rustc_env = env_out,
+ dep_env = dep_env_out,
+ flags = flags_out,
+ link_flags = link_flags,
+ link_search_paths = link_search_paths,
+ ),
+ OutputGroupInfo(
+ streams = depset([streams.stdout, streams.stderr]),
+ out_dir = depset([out_dir]),
+ ),
+ ]
+
+cargo_build_script = rule(
+ doc = (
+ "A rule for running a crate's `build.rs` files to generate build information " +
+ "which is then used to determine how to compile said crate."
+ ),
+ implementation = _cargo_build_script_impl,
+ attrs = {
+ "build_script_env": attr.string_dict(
+ doc = "Environment variables for build scripts.",
+ ),
+ "crate_features": attr.string_list(
+ doc = "The list of rust features that the build script should consider activated.",
+ ),
+ "data": attr.label_list(
+ doc = "Data required by the build script.",
+ allow_files = True,
+ ),
+ "deps": attr.label_list(
+ doc = "The Rust dependencies of the crate",
+ providers = [rust_common.dep_info],
+ cfg = "exec",
+ ),
+ "links": attr.string(
+ doc = "The name of the native library this crate links against.",
+ ),
+ "rustc_flags": attr.string_list(
+ doc = dedent("""\
+ List of compiler flags passed to `rustc`.
+
+ These strings are subject to Make variable expansion for predefined
+ source/output path variables like `$location`, `$execpath`, and
+ `$rootpath`. This expansion is useful if you wish to pass a generated
+ file of arguments to rustc: `@$(location //package:target)`.
+ """),
+ ),
+ # The source of truth will be the `cargo_build_script` macro until stardoc
+ # implements documentation inheritence. See https://github.com/bazelbuild/stardoc/issues/27
+ "script": attr.label(
+ doc = "The binary script to run, generally a `rust_binary` target.",
+ executable = True,
+ allow_files = True,
+ mandatory = True,
+ cfg = "exec",
+ ),
+ "tools": attr.label_list(
+ doc = "Tools required by the build script.",
+ allow_files = True,
+ cfg = "exec",
+ ),
+ "version": attr.string(
+ doc = "The semantic version (semver) of the crate",
+ ),
+ "_cargo_build_script_runner": attr.label(
+ executable = True,
+ allow_files = True,
+ default = Label("//cargo/cargo_build_script_runner:cargo_build_script_runner"),
+ cfg = "exec",
+ ),
+ "_cc_toolchain": attr.label(
+ default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
+ ),
+ },
+ fragments = ["cpp"],
+ toolchains = [
+ str(Label("//rust:toolchain_type")),
+ "@bazel_tools//tools/cpp:toolchain_type",
+ ],
+ incompatible_use_toolchain_transition = True,
+)
+
+def _merge_env_dict(prefix_dict, suffix_dict):
+ """Merges suffix_dict into prefix_dict, appending rather than replacing certain env vars."""
+ for key in ["CFLAGS", "CXXFLAGS", "LDFLAGS"]:
+ if key in prefix_dict and key in suffix_dict and prefix_dict[key]:
+ prefix_dict[key] += " " + suffix_dict.pop(key)
+ prefix_dict.update(suffix_dict)
+
+def name_to_pkg_name(name):
+ """Sanitize the name of cargo_build_script targets.
+
+ Args:
+ name (str): The name value pass to the `cargo_build_script` wrapper.
+
+ Returns:
+ str: A cleaned up name for a build script target.
+ """
+ if name.endswith("_build_script"):
+ return name[:-len("_build_script")]
+ return name
+
+def _cargo_dep_env_implementation(ctx):
+ empty_file = ctx.actions.declare_file(ctx.label.name + ".empty_file")
+ empty_dir = ctx.actions.declare_directory(ctx.label.name + ".empty_dir")
+ ctx.actions.write(
+ output = empty_file,
+ content = "",
+ )
+ ctx.actions.run(
+ outputs = [empty_dir],
+ executable = "true",
+ )
+
+ build_infos = []
+ out_dir = ctx.file.out_dir
+ if out_dir:
+ if not out_dir.is_directory:
+ fail("out_dir must be a directory artifact")
+
+ # BuildInfos in this list are collected up for all transitive cargo_build_script
+ # dependencies. This is important for any flags set in `dep_env` which reference this
+ # `out_dir`.
+ #
+ # TLDR: This BuildInfo propagates up build script dependencies.
+ build_infos.append(BuildInfo(
+ dep_env = empty_file,
+ flags = empty_file,
+ link_flags = empty_file,
+ link_search_paths = empty_file,
+ out_dir = out_dir,
+ rustc_env = empty_file,
+ ))
+ return [
+ DefaultInfo(files = depset(ctx.files.src)),
+ # Parts of this BuildInfo is used when building all transitive dependencies
+ # (cargo_build_script and otherwise), alongside the DepInfo. This is how other rules
+ # identify this one as a valid dependency, but we don't otherwise have a use for it.
+ #
+ # TLDR: This BuildInfo propagates up normal (non build script) depenencies.
+ #
+ # In the future, we could consider setting rustc_env here, and also propagating dep_dir
+ # so files in it can be referenced there.
+ BuildInfo(
+ dep_env = empty_file,
+ flags = empty_file,
+ link_flags = empty_file,
+ link_search_paths = empty_file,
+ out_dir = empty_dir,
+ rustc_env = empty_file,
+ ),
+ # Information here is used directly by dependencies, and it is an error to have more than
+ # one dependency which sets this. This is the main way to specify information from build
+ # scripts, which is what we're looking to do.
+ _DepInfo(
+ dep_env = ctx.file.src,
+ direct_crates = depset(),
+ link_search_path_files = depset(),
+ transitive_build_infos = depset(direct = build_infos),
+ transitive_crate_outputs = depset(),
+ transitive_crates = depset(),
+ transitive_noncrates = depset(),
+ ),
+ ]
+
+cargo_dep_env = rule(
+ implementation = _cargo_dep_env_implementation,
+ doc = (
+ "A rule for generating variables for dependent `cargo_build_script`s " +
+ "without a build script. This is useful for using Bazel rules instead " +
+ "of a build script, while also generating configuration information " +
+ "for build scripts which depend on this crate."
+ ),
+ attrs = {
+ "out_dir": attr.label(
+ doc = dedent("""\
+ Folder containing additional inputs when building all direct dependencies.
+
+ This has the same effect as a `cargo_build_script` which prints
+ puts files into `$OUT_DIR`, but without requiring a build script.
+ """),
+ allow_single_file = True,
+ mandatory = False,
+ ),
+ "src": attr.label(
+ doc = dedent("""\
+ File containing additional environment variables to set for build scripts of direct dependencies.
+
+ This has the same effect as a `cargo_build_script` which prints
+ `cargo:VAR=VALUE` lines, but without requiring a build script.
+
+ This files should contain a single variable per line, of format
+ `NAME=value`, and newlines may be included in a value by ending a
+ line with a trailing back-slash (`\\\\`).
+ """),
+ allow_single_file = True,
+ mandatory = True,
+ ),
+ },
+)
diff --git a/cargo/private/cargo_build_script_wrapper.bzl b/cargo/private/cargo_build_script_wrapper.bzl
new file mode 100644
index 0000000..e354acb
--- /dev/null
+++ b/cargo/private/cargo_build_script_wrapper.bzl
@@ -0,0 +1,153 @@
+"""Rules for Cargo build scripts (`build.rs` files)"""
+
+load(
+ "//cargo/private:cargo_build_script.bzl",
+ "name_to_crate_name",
+ "name_to_pkg_name",
+ _build_script_run = "cargo_build_script",
+)
+load("//rust:defs.bzl", "rust_binary")
+
+def cargo_build_script(
+ name,
+ crate_features = [],
+ version = None,
+ deps = [],
+ build_script_env = {},
+ data = [],
+ tools = [],
+ links = None,
+ rustc_env = {},
+ rustc_flags = [],
+ visibility = None,
+ tags = None,
+ **kwargs):
+ """Compile and execute a rust build script to generate build attributes
+
+ This rules take the same arguments as rust_binary.
+
+ Example:
+
+ Suppose you have a crate with a cargo build script `build.rs`:
+
+ ```output
+ [workspace]/
+ hello_lib/
+ BUILD
+ build.rs
+ src/
+ lib.rs
+ ```
+
+ Then you want to use the build script in the following:
+
+ `hello_lib/BUILD`:
+ ```python
+ package(default_visibility = ["//visibility:public"])
+
+ load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library")
+ load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
+
+ # This will run the build script from the root of the workspace, and
+ # collect the outputs.
+ cargo_build_script(
+ name = "build_script",
+ srcs = ["build.rs"],
+ # Optional environment variables passed during build.rs compilation
+ rustc_env = {
+ "CARGO_PKG_VERSION": "0.1.2",
+ },
+ # Optional environment variables passed during build.rs execution.
+ # Note that as the build script's working directory is not execroot,
+ # execpath/location will return an absolute path, instead of a relative
+ # one.
+ build_script_env = {
+ "SOME_TOOL_OR_FILE": "$(execpath @tool//:binary)"
+ }
+ # Optional data/tool dependencies
+ data = ["@tool//:binary"],
+ )
+
+ rust_library(
+ name = "hello_lib",
+ srcs = [
+ "src/lib.rs",
+ ],
+ deps = [":build_script"],
+ )
+ ```
+
+ The `hello_lib` target will be build with the flags and the environment variables declared by the \
+ build script in addition to the file generated by it.
+
+ Args:
+ name (str): The name for the underlying rule. This should be the name of the package
+ being compiled, optionally with a suffix of `_build_script`.
+ crate_features (list, optional): A list of features to enable for the build script.
+ version (str, optional): The semantic version (semver) of the crate.
+ deps (list, optional): The dependencies of the crate.
+ build_script_env (dict, optional): Environment variables for build scripts.
+ data (list, optional): Files needed by the build script.
+ tools (list, optional): Tools (executables) needed by the build script.
+ links (str, optional): Name of the native library this crate links against.
+ rustc_env (dict, optional): Environment variables to set in rustc when compiling the build script.
+ rustc_flags (list, optional): List of compiler flags passed to `rustc`.
+ visibility (list of label, optional): Visibility to apply to the generated build script output.
+ tags: (list of str, optional): Tags to apply to the generated build script output.
+ **kwargs: Forwards to the underlying `rust_binary` rule. An exception is the `compatible_with`
+ attribute, which shouldn't be forwarded to the `rust_binary`, as the `rust_binary` is only
+ built and used in `exec` mode. We propagate the `compatible_with` attribute to the `_build_scirpt_run`
+ target.
+ """
+
+ # This duplicates the code in _cargo_build_script_impl because we need to make these
+ # available both when we invoke rustc (this code) and when we run the compiled build
+ # script (_cargo_build_script_impl). https://github.com/bazelbuild/rules_rust/issues/661
+ # will hopefully remove this duplication.
+ rustc_env = dict(rustc_env)
+ if "CARGO_PKG_NAME" not in rustc_env:
+ rustc_env["CARGO_PKG_NAME"] = name_to_pkg_name(name)
+ if "CARGO_CRATE_NAME" not in rustc_env:
+ rustc_env["CARGO_CRATE_NAME"] = name_to_crate_name(name_to_pkg_name(name))
+
+ binary_tags = [tag for tag in tags or []]
+ if "manual" not in binary_tags:
+ binary_tags.append("manual")
+ build_script_kwargs = {}
+ binary_kwargs = kwargs
+ if "compatible_with" in kwargs:
+ build_script_kwargs["compatible_with"] = kwargs["compatible_with"]
+ binary_kwargs.pop("compatible_with")
+
+ if "toolchains" in kwargs:
+ build_script_kwargs["toolchains"] = kwargs["toolchains"]
+
+ if "features" in kwargs:
+ build_script_kwargs["features"] = kwargs["features"]
+
+ rust_binary(
+ name = name + "_",
+ crate_features = crate_features,
+ version = version,
+ deps = deps,
+ data = data,
+ rustc_env = rustc_env,
+ rustc_flags = rustc_flags,
+ tags = binary_tags,
+ **binary_kwargs
+ )
+ _build_script_run(
+ name = name,
+ script = ":{}_".format(name),
+ crate_features = crate_features,
+ version = version,
+ build_script_env = build_script_env,
+ links = links,
+ deps = deps,
+ data = data,
+ tools = tools,
+ rustc_flags = rustc_flags,
+ visibility = visibility,
+ tags = tags,
+ **build_script_kwargs
+ )
diff --git a/cargo/private/cargo_utils.bzl b/cargo/private/cargo_utils.bzl
index ef8eb28..b70d8e2 100644
--- a/cargo/private/cargo_utils.bzl
+++ b/cargo/private/cargo_utils.bzl
@@ -6,6 +6,7 @@
template,
abi = None,
arch = None,
+ channel = None,
system = None,
tool = None,
triple = None,
@@ -17,6 +18,7 @@
template (str): The template to use for rendering
abi (str, optional): The host ABI
arch (str, optional): The host CPU architecture
+ channel (str, optional): The toolchain channel. Eg. `stable`, `nightly`.
system (str, optional): The host system name
tool (str, optional): The tool to expect in the particular repository.
Eg. `cargo`, `rustc`, `stdlib`.
@@ -47,16 +49,20 @@
if version:
template = template.replace("{version}", version)
+ if channel:
+ template = template.replace("{channel}", channel)
+
return template
-def get_rust_tools(cargo_template, rustc_template, host_triple, version):
+def get_rust_tools(cargo_template, rustc_template, host_triple, channel, version):
"""Retrieve `cargo` and `rustc` labels based on the host triple.
Args:
cargo_template (str): A template used to identify the label of the host `cargo` binary.
rustc_template (str): A template used to identify the label of the host `rustc` binary.
host_triple (struct): The host's triple. See `@rules_rust//rust/platform:triple.bzl`.
- version (str): The version of Cargo+Rustc to use.
+ channel (str): The Rust toolchain channel.
+ version (str): The version (or iso date in case of beta or nightly channels) of Cargo+Rustc to use.
Returns:
struct: A struct containing the labels of expected tools
@@ -66,6 +72,7 @@
cargo_label = Label(_resolve_repository_template(
template = cargo_template,
version = version,
+ channel = channel,
triple = host_triple.str,
arch = host_triple.arch,
vendor = host_triple.vendor,
@@ -77,6 +84,7 @@
rustc_label = Label(_resolve_repository_template(
template = rustc_template,
version = version,
+ channel = channel,
triple = host_triple.str,
arch = host_triple.arch,
vendor = host_triple.vendor,
diff --git a/cargo/private/features.bzl b/cargo/private/features.bzl
new file mode 100644
index 0000000..5d396b9
--- /dev/null
+++ b/cargo/private/features.bzl
@@ -0,0 +1,24 @@
+"""Feature helpers."""
+
+def feature_enabled(ctx, feature_name, default = False):
+ """Check if a feature is enabled.
+
+ If the feature is explicitly enabled or disabled, return accordingly.
+
+ In the case where the feature is not explicitly enabled or disabled, return the default value.
+
+ Args:
+ ctx: The context object.
+ feature_name: The name of the feature.
+ default: The default value to return if the feature is not explicitly enabled or disabled.
+
+ Returns:
+ Boolean defining whether the feature is enabled.
+ """
+ if feature_name in ctx.disabled_features:
+ return False
+
+ if feature_name in ctx.features:
+ return True
+
+ return default