Support linking Rust code into a C++ binary
This is based on a version of my upstream PR:
https://github.com/bazelbuild/rules_rust/pull/1350
Change-Id: Ica7097c10666d2e0017336cf7d81420605238493
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
diff --git a/WORKSPACE b/WORKSPACE
index 50aad8c..79af5a3 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -841,6 +841,7 @@
rust_toolchain_repository(
name = "rust",
+ allocator_library = "@//tools/rust:forward_allocator",
edition = "2021",
exec_triple = "x86_64-unknown-linux-gnu",
extra_target_triples = [
diff --git a/build_tests/BUILD b/build_tests/BUILD
index 29a1275..24fdad8 100644
--- a/build_tests/BUILD
+++ b/build_tests/BUILD
@@ -178,3 +178,16 @@
target_compatible_with = ["@platforms//os:linux"],
deps = [":ts_test"],
)
+
+rust_library(
+ name = "rust_in_cc_rs",
+ srcs = ["rust_in_cc.rs"],
+ target_compatible_with = ["@platforms//os:linux"],
+)
+
+cc_test(
+ name = "rust_in_cc",
+ srcs = ["rust_in_cc.cc"],
+ target_compatible_with = ["@platforms//os:linux"],
+ deps = [":rust_in_cc_rs"],
+)
diff --git a/build_tests/rust_in_cc.cc b/build_tests/rust_in_cc.cc
new file mode 100644
index 0000000..9c13b1b
--- /dev/null
+++ b/build_tests/rust_in_cc.cc
@@ -0,0 +1,19 @@
+// A very minimal rust_library linked into a cc_binary to make sure we still get
+// the allocator symbols linked in.
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern "C" int32_t rust_return5();
+
+extern "C" uint8_t c_return5() { return 5; }
+
+extern "C" void c_take5(uint8_t *) {}
+
+int main() {
+ const int rust_result = rust_return5();
+ printf("Rust says: %d\n", rust_result);
+ if (rust_result != 5) {
+ return 1;
+ }
+}
diff --git a/build_tests/rust_in_cc.rs b/build_tests/rust_in_cc.rs
new file mode 100644
index 0000000..0810609
--- /dev/null
+++ b/build_tests/rust_in_cc.rs
@@ -0,0 +1,19 @@
+extern "C" {
+ fn c_return5() -> u8;
+ fn c_take5(x: *mut u8);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rust_return5() -> i32 {
+ let layout = std::alloc::Layout::from_size_align(1, 1).unwrap();
+ let a = std::alloc::alloc(layout);
+ *a = c_return5();
+ // Do something so the compiler can't optimize out the alloc+free pair, which would invalidate
+ // this test.
+ if *a != 5 {
+ c_take5(a);
+ } else {
+ std::alloc::dealloc(a, layout);
+ }
+ 5
+}
diff --git a/third_party/rules_rust/.bazelci/presubmit.yml b/third_party/rules_rust/.bazelci/presubmit.yml
index 1e59628..b948e0a 100644
--- a/third_party/rules_rust/.bazelci/presubmit.yml
+++ b/third_party/rules_rust/.bazelci/presubmit.yml
@@ -20,6 +20,8 @@
- "//vendor_local_pkgs:crates_vendor"
- "//vendor_remote_manifests:crates_vendor_manifests"
- "//vendor_remote_pkgs:crates_vendor_pkgs"
+cc_binary_example_targets: &cc_binary_example_targets
+ - "//..."
tasks:
ubuntu2004:
build_targets: *default_linux_targets
@@ -297,6 +299,52 @@
- "//..."
test_targets:
- "//..."
+ cc_binary_examples_ubuntu2004:
+ name: Crate Universe Examples
+ platform: ubuntu2004
+ working_directory: examples/cc_binary
+ run_targets: *cc_binary_example_targets
+ build_targets:
+ - "//..."
+ test_targets:
+ - "//..."
+ build_flags: *aspects_flags
+ cc_binary_rbe_ubuntu1604:
+ name: Crate Universe Examples
+ platform: rbe_ubuntu1604
+ working_directory: examples/cc_binary
+ shell_commands:
+ - sed -i 's/^# load("@bazelci_rules/load("@bazelci_rules/' WORKSPACE.bazel
+ - sed -i 's/^# rbe_preconfig/rbe_preconfig/' WORKSPACE.bazel
+ run_targets: *cc_binary_example_targets
+ build_targets:
+ - "//..."
+ test_targets:
+ - "//..."
+ build_flags: *aspects_flags
+ cc_binary_examples_macos:
+ name: Crate Universe Examples
+ platform: macos
+ working_directory: examples/cc_binary
+ run_targets: *cc_binary_example_targets
+ build_targets:
+ - "//..."
+ test_targets:
+ - "//..."
+ build_flags: *aspects_flags
+ cc_binary_examples_windows:
+ name: Crate Universe Examples
+ platform: windows
+ working_directory: examples/cc_binary
+ batch_commands:
+ - echo startup --windows_enable_symlinks >> user.bazelrc
+ - echo build --enable_runfiles >> user.bazelrc # this is not enabled by default on windows and is necessary for the cargo build scripts
+ run_targets: *cc_binary_example_targets
+ build_flags: *aspects_flags
+ build_targets:
+ - "//..."
+ test_targets:
+ - "//..."
buildifier:
version: latest
warnings: "all"
diff --git a/third_party/rules_rust/docs/flatten.md b/third_party/rules_rust/docs/flatten.md
index f650bc9..0f82ad7 100644
--- a/third_party/rules_rust/docs/flatten.md
+++ b/third_party/rules_rust/docs/flatten.md
@@ -1141,9 +1141,9 @@
## rust_toolchain_repository
<pre>
-rust_toolchain_repository(<a href="#rust_toolchain_repository-name">name</a>, <a href="#rust_toolchain_repository-auth">auth</a>, <a href="#rust_toolchain_repository-dev_components">dev_components</a>, <a href="#rust_toolchain_repository-edition">edition</a>, <a href="#rust_toolchain_repository-exec_triple">exec_triple</a>, <a href="#rust_toolchain_repository-extra_target_triples">extra_target_triples</a>,
- <a href="#rust_toolchain_repository-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_toolchain_repository-iso_date">iso_date</a>, <a href="#rust_toolchain_repository-repo_mapping">repo_mapping</a>, <a href="#rust_toolchain_repository-rustfmt_version">rustfmt_version</a>, <a href="#rust_toolchain_repository-sha256s">sha256s</a>,
- <a href="#rust_toolchain_repository-toolchain_name_prefix">toolchain_name_prefix</a>, <a href="#rust_toolchain_repository-urls">urls</a>, <a href="#rust_toolchain_repository-version">version</a>)
+rust_toolchain_repository(<a href="#rust_toolchain_repository-name">name</a>, <a href="#rust_toolchain_repository-allocator_library">allocator_library</a>, <a href="#rust_toolchain_repository-auth">auth</a>, <a href="#rust_toolchain_repository-dev_components">dev_components</a>, <a href="#rust_toolchain_repository-edition">edition</a>, <a href="#rust_toolchain_repository-exec_triple">exec_triple</a>,
+ <a href="#rust_toolchain_repository-extra_target_triples">extra_target_triples</a>, <a href="#rust_toolchain_repository-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_toolchain_repository-iso_date">iso_date</a>, <a href="#rust_toolchain_repository-repo_mapping">repo_mapping</a>,
+ <a href="#rust_toolchain_repository-rustfmt_version">rustfmt_version</a>, <a href="#rust_toolchain_repository-sha256s">sha256s</a>, <a href="#rust_toolchain_repository-toolchain_name_prefix">toolchain_name_prefix</a>, <a href="#rust_toolchain_repository-urls">urls</a>, <a href="#rust_toolchain_repository-version">version</a>)
</pre>
Composes a single workspace containing the toolchain components for compiling on a given platform to a series of target platforms.
@@ -1156,6 +1156,7 @@
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="rust_toolchain_repository-name"></a>name | A unique name for this repository. | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required | |
+| <a id="rust_toolchain_repository-allocator_library"></a>allocator_library | Target that provides allocator functions when rust_library targets are embedded in a cc_binary. | String | optional | "" |
| <a id="rust_toolchain_repository-auth"></a>auth | Auth object compatible with repository_ctx.download to use when downloading files. See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details. | <a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a> | optional | {} |
| <a id="rust_toolchain_repository-dev_components"></a>dev_components | Whether to download the rustc-dev components (defaults to False). Requires version to be "nightly". | Boolean | optional | False |
| <a id="rust_toolchain_repository-edition"></a>edition | The rust edition to be used by default. | String | optional | "2018" |
@@ -1362,7 +1363,7 @@
<pre>
StdLibInfo(<a href="#StdLibInfo-alloc_files">alloc_files</a>, <a href="#StdLibInfo-between_alloc_and_core_files">between_alloc_and_core_files</a>, <a href="#StdLibInfo-between_core_and_std_files">between_core_and_std_files</a>, <a href="#StdLibInfo-core_files">core_files</a>,
- <a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_files">std_files</a>, <a href="#StdLibInfo-std_rlibs">std_rlibs</a>)
+ <a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-memchr_files">memchr_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_files">std_files</a>, <a href="#StdLibInfo-std_rlibs">std_rlibs</a>)
</pre>
A collection of files either found within the `rust-stdlib` artifact or generated based on existing files.
@@ -1377,6 +1378,7 @@
| <a id="StdLibInfo-between_core_and_std_files"></a>between_core_and_std_files | List[File]: <code>.a</code> files related to all modules except <code>adler</code>, <code>alloc</code>, <code>compiler_builtins</code>, <code>core</code>, and <code>std</code>. |
| <a id="StdLibInfo-core_files"></a>core_files | List[File]: <code>.a</code> files related to the <code>core</code> and <code>adler</code> modules |
| <a id="StdLibInfo-dot_a_files"></a>dot_a_files | Depset[File]: Generated <code>.a</code> files |
+| <a id="StdLibInfo-memchr_files"></a>memchr_files | Depset[File]: <code>.a</code> files associated with the <code>memchr</code> module. |
| <a id="StdLibInfo-self_contained_files"></a>self_contained_files | List[File]: All <code>.o</code> files from the <code>self-contained</code> directory. |
| <a id="StdLibInfo-srcs"></a>srcs | List[Target]: All targets from the original <code>srcs</code> attribute. |
| <a id="StdLibInfo-std_files"></a>std_files | Depset[File]: <code>.a</code> files associated with the <code>std</code> module. |
@@ -1611,8 +1613,9 @@
## rust_repository_set
<pre>
-rust_repository_set(<a href="#rust_repository_set-name">name</a>, <a href="#rust_repository_set-version">version</a>, <a href="#rust_repository_set-exec_triple">exec_triple</a>, <a href="#rust_repository_set-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_repository_set-extra_target_triples">extra_target_triples</a>, <a href="#rust_repository_set-iso_date">iso_date</a>,
- <a href="#rust_repository_set-rustfmt_version">rustfmt_version</a>, <a href="#rust_repository_set-edition">edition</a>, <a href="#rust_repository_set-dev_components">dev_components</a>, <a href="#rust_repository_set-sha256s">sha256s</a>, <a href="#rust_repository_set-urls">urls</a>, <a href="#rust_repository_set-auth">auth</a>, <a href="#rust_repository_set-register_toolchain">register_toolchain</a>)
+rust_repository_set(<a href="#rust_repository_set-name">name</a>, <a href="#rust_repository_set-version">version</a>, <a href="#rust_repository_set-exec_triple">exec_triple</a>, <a href="#rust_repository_set-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_repository_set-allocator_library">allocator_library</a>,
+ <a href="#rust_repository_set-extra_target_triples">extra_target_triples</a>, <a href="#rust_repository_set-iso_date">iso_date</a>, <a href="#rust_repository_set-rustfmt_version">rustfmt_version</a>, <a href="#rust_repository_set-edition">edition</a>, <a href="#rust_repository_set-dev_components">dev_components</a>, <a href="#rust_repository_set-sha256s">sha256s</a>,
+ <a href="#rust_repository_set-urls">urls</a>, <a href="#rust_repository_set-auth">auth</a>, <a href="#rust_repository_set-register_toolchain">register_toolchain</a>)
</pre>
Assembles a remote repository for the given toolchain params, produces a proxy repository to contain the toolchain declaration, and registers the toolchains.
@@ -1629,6 +1632,7 @@
| <a id="rust_repository_set-version"></a>version | The version of the tool among "nightly", "beta', or an exact version. | none |
| <a id="rust_repository_set-exec_triple"></a>exec_triple | The Rust-style target that this compiler runs on | none |
| <a id="rust_repository_set-include_rustc_srcs"></a>include_rustc_srcs | Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False. | <code>False</code> |
+| <a id="rust_repository_set-allocator_library"></a>allocator_library | Target that provides allocator functions when rust_library targets are embedded in a cc_binary. | <code>None</code> |
| <a id="rust_repository_set-extra_target_triples"></a>extra_target_triples | Additional rust-style targets that this set of toolchains should support. Defaults to []. | <code>[]</code> |
| <a id="rust_repository_set-iso_date"></a>iso_date | The date of the tool. Defaults to None. | <code>None</code> |
| <a id="rust_repository_set-rustfmt_version"></a>rustfmt_version | The version of rustfmt to be associated with the toolchain. Defaults to None. | <code>None</code> |
diff --git a/third_party/rules_rust/docs/providers.md b/third_party/rules_rust/docs/providers.md
index 0a78246..f4aa819 100644
--- a/third_party/rules_rust/docs/providers.md
+++ b/third_party/rules_rust/docs/providers.md
@@ -68,7 +68,7 @@
<pre>
StdLibInfo(<a href="#StdLibInfo-alloc_files">alloc_files</a>, <a href="#StdLibInfo-between_alloc_and_core_files">between_alloc_and_core_files</a>, <a href="#StdLibInfo-between_core_and_std_files">between_core_and_std_files</a>, <a href="#StdLibInfo-core_files">core_files</a>,
- <a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_files">std_files</a>, <a href="#StdLibInfo-std_rlibs">std_rlibs</a>)
+ <a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-memchr_files">memchr_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_files">std_files</a>, <a href="#StdLibInfo-std_rlibs">std_rlibs</a>)
</pre>
A collection of files either found within the `rust-stdlib` artifact or generated based on existing files.
@@ -83,6 +83,7 @@
| <a id="StdLibInfo-between_core_and_std_files"></a>between_core_and_std_files | List[File]: <code>.a</code> files related to all modules except <code>adler</code>, <code>alloc</code>, <code>compiler_builtins</code>, <code>core</code>, and <code>std</code>. |
| <a id="StdLibInfo-core_files"></a>core_files | List[File]: <code>.a</code> files related to the <code>core</code> and <code>adler</code> modules |
| <a id="StdLibInfo-dot_a_files"></a>dot_a_files | Depset[File]: Generated <code>.a</code> files |
+| <a id="StdLibInfo-memchr_files"></a>memchr_files | Depset[File]: <code>.a</code> files associated with the <code>memchr</code> module. |
| <a id="StdLibInfo-self_contained_files"></a>self_contained_files | List[File]: All <code>.o</code> files from the <code>self-contained</code> directory. |
| <a id="StdLibInfo-srcs"></a>srcs | List[Target]: All targets from the original <code>srcs</code> attribute. |
| <a id="StdLibInfo-std_files"></a>std_files | Depset[File]: <code>.a</code> files associated with the <code>std</code> module. |
diff --git a/third_party/rules_rust/docs/rust_repositories.md b/third_party/rules_rust/docs/rust_repositories.md
index 8f68ff7..27a6354 100644
--- a/third_party/rules_rust/docs/rust_repositories.md
+++ b/third_party/rules_rust/docs/rust_repositories.md
@@ -116,9 +116,9 @@
## rust_toolchain_repository
<pre>
-rust_toolchain_repository(<a href="#rust_toolchain_repository-name">name</a>, <a href="#rust_toolchain_repository-auth">auth</a>, <a href="#rust_toolchain_repository-dev_components">dev_components</a>, <a href="#rust_toolchain_repository-edition">edition</a>, <a href="#rust_toolchain_repository-exec_triple">exec_triple</a>, <a href="#rust_toolchain_repository-extra_target_triples">extra_target_triples</a>,
- <a href="#rust_toolchain_repository-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_toolchain_repository-iso_date">iso_date</a>, <a href="#rust_toolchain_repository-repo_mapping">repo_mapping</a>, <a href="#rust_toolchain_repository-rustfmt_version">rustfmt_version</a>, <a href="#rust_toolchain_repository-sha256s">sha256s</a>,
- <a href="#rust_toolchain_repository-toolchain_name_prefix">toolchain_name_prefix</a>, <a href="#rust_toolchain_repository-urls">urls</a>, <a href="#rust_toolchain_repository-version">version</a>)
+rust_toolchain_repository(<a href="#rust_toolchain_repository-name">name</a>, <a href="#rust_toolchain_repository-allocator_library">allocator_library</a>, <a href="#rust_toolchain_repository-auth">auth</a>, <a href="#rust_toolchain_repository-dev_components">dev_components</a>, <a href="#rust_toolchain_repository-edition">edition</a>, <a href="#rust_toolchain_repository-exec_triple">exec_triple</a>,
+ <a href="#rust_toolchain_repository-extra_target_triples">extra_target_triples</a>, <a href="#rust_toolchain_repository-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_toolchain_repository-iso_date">iso_date</a>, <a href="#rust_toolchain_repository-repo_mapping">repo_mapping</a>,
+ <a href="#rust_toolchain_repository-rustfmt_version">rustfmt_version</a>, <a href="#rust_toolchain_repository-sha256s">sha256s</a>, <a href="#rust_toolchain_repository-toolchain_name_prefix">toolchain_name_prefix</a>, <a href="#rust_toolchain_repository-urls">urls</a>, <a href="#rust_toolchain_repository-version">version</a>)
</pre>
Composes a single workspace containing the toolchain components for compiling on a given platform to a series of target platforms.
@@ -131,6 +131,7 @@
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="rust_toolchain_repository-name"></a>name | A unique name for this repository. | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required | |
+| <a id="rust_toolchain_repository-allocator_library"></a>allocator_library | Target that provides allocator functions when rust_library targets are embedded in a cc_binary. | String | optional | "" |
| <a id="rust_toolchain_repository-auth"></a>auth | Auth object compatible with repository_ctx.download to use when downloading files. See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details. | <a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a> | optional | {} |
| <a id="rust_toolchain_repository-dev_components"></a>dev_components | Whether to download the rustc-dev components (defaults to False). Requires version to be "nightly". | Boolean | optional | False |
| <a id="rust_toolchain_repository-edition"></a>edition | The rust edition to be used by default. | String | optional | "2018" |
@@ -193,8 +194,9 @@
## rust_repository_set
<pre>
-rust_repository_set(<a href="#rust_repository_set-name">name</a>, <a href="#rust_repository_set-version">version</a>, <a href="#rust_repository_set-exec_triple">exec_triple</a>, <a href="#rust_repository_set-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_repository_set-extra_target_triples">extra_target_triples</a>, <a href="#rust_repository_set-iso_date">iso_date</a>,
- <a href="#rust_repository_set-rustfmt_version">rustfmt_version</a>, <a href="#rust_repository_set-edition">edition</a>, <a href="#rust_repository_set-dev_components">dev_components</a>, <a href="#rust_repository_set-sha256s">sha256s</a>, <a href="#rust_repository_set-urls">urls</a>, <a href="#rust_repository_set-auth">auth</a>, <a href="#rust_repository_set-register_toolchain">register_toolchain</a>)
+rust_repository_set(<a href="#rust_repository_set-name">name</a>, <a href="#rust_repository_set-version">version</a>, <a href="#rust_repository_set-exec_triple">exec_triple</a>, <a href="#rust_repository_set-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_repository_set-allocator_library">allocator_library</a>,
+ <a href="#rust_repository_set-extra_target_triples">extra_target_triples</a>, <a href="#rust_repository_set-iso_date">iso_date</a>, <a href="#rust_repository_set-rustfmt_version">rustfmt_version</a>, <a href="#rust_repository_set-edition">edition</a>, <a href="#rust_repository_set-dev_components">dev_components</a>, <a href="#rust_repository_set-sha256s">sha256s</a>,
+ <a href="#rust_repository_set-urls">urls</a>, <a href="#rust_repository_set-auth">auth</a>, <a href="#rust_repository_set-register_toolchain">register_toolchain</a>)
</pre>
Assembles a remote repository for the given toolchain params, produces a proxy repository to contain the toolchain declaration, and registers the toolchains.
@@ -211,6 +213,7 @@
| <a id="rust_repository_set-version"></a>version | The version of the tool among "nightly", "beta', or an exact version. | none |
| <a id="rust_repository_set-exec_triple"></a>exec_triple | The Rust-style target that this compiler runs on | none |
| <a id="rust_repository_set-include_rustc_srcs"></a>include_rustc_srcs | Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False. | <code>False</code> |
+| <a id="rust_repository_set-allocator_library"></a>allocator_library | Target that provides allocator functions when rust_library targets are embedded in a cc_binary. | <code>None</code> |
| <a id="rust_repository_set-extra_target_triples"></a>extra_target_triples | Additional rust-style targets that this set of toolchains should support. Defaults to []. | <code>[]</code> |
| <a id="rust_repository_set-iso_date"></a>iso_date | The date of the tool. Defaults to None. | <code>None</code> |
| <a id="rust_repository_set-rustfmt_version"></a>rustfmt_version | The version of rustfmt to be associated with the toolchain. Defaults to None. | <code>None</code> |
diff --git a/third_party/rules_rust/rust/private/providers.bzl b/third_party/rules_rust/rust/private/providers.bzl
index b471ac0..de6d314 100644
--- a/third_party/rules_rust/rust/private/providers.bzl
+++ b/third_party/rules_rust/rust/private/providers.bzl
@@ -89,6 +89,7 @@
"between_core_and_std_files": "List[File]: `.a` files related to all modules except `adler`, `alloc`, `compiler_builtins`, `core`, and `std`.",
"core_files": "List[File]: `.a` files related to the `core` and `adler` modules",
"dot_a_files": "Depset[File]: Generated `.a` files",
+ "memchr_files": "Depset[File]: `.a` files associated with the `memchr` module.",
"self_contained_files": "List[File]: All `.o` files from the `self-contained` directory.",
"srcs": "List[Target]: All targets from the original `srcs` attribute.",
"std_files": "Depset[File]: `.a` files associated with the `std` module.",
diff --git a/third_party/rules_rust/rust/private/repository_utils.bzl b/third_party/rules_rust/rust/private/repository_utils.bzl
index b6c83aa..1c33331 100644
--- a/third_party/rules_rust/rust/private/repository_utils.bzl
+++ b/third_party/rules_rust/rust/private/repository_utils.bzl
@@ -191,6 +191,7 @@
clippy_driver = "@{workspace_name}//:clippy_driver_bin",
rustc_lib = "@{workspace_name}//:rustc_lib",
rustc_srcs = {rustc_srcs},
+ allocator_library = {allocator_library},
binary_ext = "{binary_ext}",
staticlib_ext = "{staticlib_ext}",
dylib_ext = "{dylib_ext}",
@@ -209,6 +210,7 @@
exec_triple,
target_triple,
include_rustc_srcs,
+ allocator_library,
default_edition,
include_rustfmt,
stdlib_linkflags = None):
@@ -220,6 +222,7 @@
exec_triple (str): The rust-style target that this compiler runs on
target_triple (str): The rust-style target triple of the tool
include_rustc_srcs (bool, optional): Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False.
+ allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
default_edition (str): Default Rust edition.
include_rustfmt (bool): Whether rustfmt is present in the toolchain.
stdlib_linkflags (list, optional): Overriden flags needed for linking to rust
@@ -240,6 +243,9 @@
rustfmt_label = "None"
if include_rustfmt:
rustfmt_label = "\"@{workspace_name}//:rustfmt_bin\"".format(workspace_name = workspace_name)
+ allocator_library_label = "None"
+ if allocator_library:
+ allocator_library_label = "\"{allocator_library}\"".format(allocator_library = allocator_library)
return _build_file_for_rust_toolchain_template.format(
toolchain_name = name,
@@ -248,6 +254,7 @@
staticlib_ext = system_to_staticlib_ext(system),
dylib_ext = system_to_dylib_ext(system),
rustc_srcs = rustc_srcs,
+ allocator_library = allocator_library_label,
stdlib_linkflags = stdlib_linkflags,
system = system,
default_edition = default_edition,
@@ -404,6 +411,7 @@
),
exec_triple = ctx.attr.exec_triple,
include_rustc_srcs = should_include_rustc_srcs(ctx),
+ allocator_library = ctx.attr.allocator_library,
target_triple = target_triple,
stdlib_linkflags = stdlib_linkflags,
workspace_name = ctx.attr.name,
diff --git a/third_party/rules_rust/rust/repositories.bzl b/third_party/rules_rust/rust/repositories.bzl
index 99f2f51..de5cb47 100644
--- a/third_party/rules_rust/rust/repositories.bzl
+++ b/third_party/rules_rust/rust/repositories.bzl
@@ -64,6 +64,7 @@
dev_components = False,
edition = None,
include_rustc_srcs = False,
+ allocator_library = None,
iso_date = None,
register_toolchains = True,
rustfmt_version = None,
@@ -94,6 +95,7 @@
edition (str, optional): The rust edition to be used by default (2015, 2018 (default), or 2021)
include_rustc_srcs (bool, optional): Whether to download rustc's src code. This is required in order to use rust-analyzer support.
See [rust_toolchain_repository.include_rustc_srcs](#rust_toolchain_repository-include_rustc_srcs). for more details
+ allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
iso_date (str, optional): The date of the nightly or beta release (ignored if the version is a specific version).
register_toolchains (bool): If true, repositories will be generated to produce and register `rust_toolchain` targets.
rustfmt_version (str, optional): The version of rustfmt. Either "nightly", "beta", or an exact version. Defaults to `version` if not specified.
@@ -117,6 +119,7 @@
exec_triple = exec_triple,
extra_target_triples = extra_target_triples,
include_rustc_srcs = include_rustc_srcs,
+ allocator_library = allocator_library,
iso_date = iso_date,
register_toolchain = register_toolchains,
rustfmt_version = rustfmt_version,
@@ -191,6 +194,9 @@
"selection from toolchain fetching."
),
attrs = {
+ "allocator_library": attr.string(
+ doc = "Target that provides allocator functions when rust_library targets are embedded in a cc_binary.",
+ ),
"auth": attr.string_dict(
doc = (
"Auth object compatible with repository_ctx.download to use when downloading files. " +
@@ -276,6 +282,7 @@
version,
exec_triple,
include_rustc_srcs = False,
+ allocator_library = None,
extra_target_triples = [],
iso_date = None,
rustfmt_version = None,
@@ -296,6 +303,7 @@
version (str): The version of the tool among "nightly", "beta', or an exact version.
exec_triple (str): The Rust-style target that this compiler runs on
include_rustc_srcs (bool, optional): Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False.
+ allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
extra_target_triples (list, optional): Additional rust-style targets that this set of
toolchains should support. Defaults to [].
iso_date (str, optional): The date of the tool. Defaults to None.
@@ -316,6 +324,7 @@
name = name,
exec_triple = exec_triple,
include_rustc_srcs = include_rustc_srcs,
+ allocator_library = allocator_library,
extra_target_triples = extra_target_triples,
iso_date = iso_date,
toolchain_name_prefix = DEFAULT_TOOLCHAIN_NAME_PREFIX,
diff --git a/third_party/rules_rust/rust/toolchain.bzl b/third_party/rules_rust/rust/toolchain.bzl
index 687e0df..083991a 100644
--- a/third_party/rules_rust/rust/toolchain.bzl
+++ b/third_party/rules_rust/rust/toolchain.bzl
@@ -11,6 +11,7 @@
core_files = []
between_core_and_std_files = []
std_files = []
+ memchr_files = []
alloc_files = []
self_contained_files = [
file
@@ -35,13 +36,14 @@
between_core_and_std_files = [
f
for f in dot_a_files
- if "alloc" not in f.basename and "compiler_builtins" not in f.basename and "core" not in f.basename and "adler" not in f.basename and "std" not in f.basename
+ if "alloc" not in f.basename and "compiler_builtins" not in f.basename and "core" not in f.basename and "adler" not in f.basename and "std" not in f.basename and "memchr" not in f.basename
]
+ memchr_files = [f for f in dot_a_files if "memchr" in f.basename]
std_files = [f for f in dot_a_files if "std" in f.basename]
- partitioned_files_len = len(alloc_files) + len(between_alloc_and_core_files) + len(core_files) + len(between_core_and_std_files) + len(std_files)
+ partitioned_files_len = len(alloc_files) + len(between_alloc_and_core_files) + len(core_files) + len(between_core_and_std_files) + len(memchr_files) + len(std_files)
if partitioned_files_len != len(dot_a_files):
- partitioned = alloc_files + between_alloc_and_core_files + core_files + between_core_and_std_files + std_files
+ partitioned = alloc_files + between_alloc_and_core_files + core_files + between_core_and_std_files + memchr_files + std_files
for f in sorted(partitioned):
# buildifier: disable=print
print("File partitioned: {}".format(f.basename))
@@ -58,6 +60,7 @@
core_files = core_files,
between_core_and_std_files = between_core_and_std_files,
std_files = std_files,
+ memchr_files = memchr_files,
alloc_files = alloc_files,
self_contained_files = self_contained_files,
srcs = ctx.attr.srcs,
@@ -168,12 +171,20 @@
for f in filtered_between_core_and_std_files
if "panic_abort" not in f.basename
]
+ memchr_inputs = depset(
+ [
+ _ltl(f, ctx, cc_toolchain, feature_configuration)
+ for f in rust_stdlib_info.memchr_files
+ ],
+ transitive = [core_inputs],
+ order = "topological",
+ )
between_core_and_std_inputs = depset(
[
_ltl(f, ctx, cc_toolchain, feature_configuration)
for f in filtered_between_core_and_std_files
],
- transitive = [core_inputs],
+ transitive = [memchr_inputs],
order = "topological",
)
std_inputs = depset(
@@ -185,20 +196,20 @@
order = "topological",
)
- link_inputs = cc_common.create_linker_input(
+ link_inputs = [depset([cc_common.create_linker_input(
owner = rust_std.label,
libraries = std_inputs,
- )
+ )])]
- allocator_inputs = None
+ allocator_inputs = []
if allocator_library:
- allocator_inputs = [allocator_library[CcInfo].linking_context.linker_inputs]
+ allocator_inputs = allocator_library[CcInfo].linking_context.linker_inputs.to_list()
cc_infos.append(CcInfo(
linking_context = cc_common.create_linking_context(
linker_inputs = depset(
- [link_inputs],
- transitive = allocator_inputs,
+ allocator_inputs,
+ transitive = link_inputs,
order = "topological",
),
),
diff --git a/tools/rust/BUILD b/tools/rust/BUILD
index fccc3e4..4d9e4d6 100644
--- a/tools/rust/BUILD
+++ b/tools/rust/BUILD
@@ -132,3 +132,9 @@
],
)
'''
+
+cc_library(
+ name = "forward_allocator",
+ srcs = ["forward_allocator.c"],
+ visibility = ["//visibility:public"],
+)
diff --git a/tools/rust/forward_allocator.c b/tools/rust/forward_allocator.c
new file mode 100644
index 0000000..3e6ba96
--- /dev/null
+++ b/tools/rust/forward_allocator.c
@@ -0,0 +1,46 @@
+#include <stdint.h>
+
+// This file has some exciting magic to get Rust code linking in a cc_binary.
+// The Rust compiler generates some similar symbol aliases when it links, so we
+// have to do it manually.
+//
+// It is intended to be used in rust_toolchain.allocator_library.
+//
+// https://github.com/rust-lang/rust/blob/master/library/alloc/src/alloc.rs
+// and https://github.com/rust-lang/rust/blob/master/library/std/src/alloc.rs
+// are the best source of docs I've found on these functions and variables.
+// https://doc.rust-lang.org/std/alloc/index.html talks about how this is
+// intended to be used.
+//
+// Also note
+// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html for
+// the sizes of the various integer types.
+//
+// This file strongly assumes that the default allocator is used. It will
+// not work with any other allocated switched in via `#[global_allocator]`.
+
+// New feature as of https://github.com/rust-lang/rust/pull/88098.
+uint8_t __rust_alloc_error_handler_should_panic = 0;
+
+uint8_t *__rdl_alloc(uintptr_t size, uintptr_t align);
+uint8_t *__rust_alloc(uintptr_t size, uintptr_t align) {
+ return __rdl_alloc(size, align);
+}
+void __rdl_dealloc(uint8_t *ptr, uintptr_t size, uintptr_t align);
+void __rust_dealloc(uint8_t *ptr, uintptr_t size, uintptr_t align) {
+ __rdl_dealloc(ptr, size, align);
+}
+uint8_t *__rdl_realloc(uint8_t *ptr, uintptr_t old_size, uintptr_t align,
+ uintptr_t new_size);
+uint8_t *__rust_realloc(uint8_t *ptr, uintptr_t old_size, uintptr_t align,
+ uintptr_t new_size) {
+ return __rdl_realloc(ptr, old_size, align, new_size);
+}
+uint8_t *__rdl_alloc_zeroed(uintptr_t size, uintptr_t align);
+uint8_t *__rust_alloc_zeroed(uintptr_t size, uintptr_t align) {
+ return __rdl_alloc_zeroed(size, align);
+}
+void __rdl_oom(uintptr_t size, uintptr_t align);
+void __rust_alloc_error_handler(uintptr_t size, uintptr_t align) {
+ __rdl_oom(size, align);
+}