mirror of https://github.com/bazelbuild/rules_rust
Implement support for dylib linkage (#2414)
This PR implements dylib linkage against the standard library behind a feature flag `--@rules_rust//rust/settings:experimental_use_dylib_linkage`. The main part of this feature is [here](https://github.com/bazelbuild/rules_rust/pull/2414/files#diff-2a806da393e47c07ffe67c78ace69eb488b4ac44b029a46d8237b8e2a05637beR258) where we skip exporting static rust stdlibs and export only `libstd.so` instead. This feature is useful when the subset of libstd being statically linked to downstream shared libraries and binaries is **larger** than the entire dylib version of libstd. The following diagram is the high level of what dylib linkage is trying to achieve. ![Untitled Diagram drawio](https://github.com/bazelbuild/rules_rust/assets/13268391/d19f18f5-c2d1-4ddc-b170-773a6004f732) Running the feature against `android_binary` yields a size reduction on the shared library produced by `android_binary` because it doesn't statically link the rust stdlibs anymore. ``` > bazel build //:android_app --config=android_x86_64 > unzip -l bazel-bin/android_app.apk Archive: bazel-bin/android_app.apk Length Date Time Name --------- ---------- ----- ---- 1381968 2010-01-01 00:00 lib/x86_64/libandroid_app.so <--- static link with rust stdlibs --------- ------- 1390294 9 files ``` ``` > bazel build //:android_app --config=android_x86_64 --config=dylib_linkage > unzip -l bazel-bin/android_app.apk Archive: bazel-bin/android_app.apk Length Date Time Name --------- ---------- ----- ---- 8080 2010-01-01 00:00 lib/x86_64/libandroid_app.so <--- reduced size because of dynamic linking 13055776 2010-01-01 00:00 lib/x86_64/libstd-8d416d49cf02ecea.so --------- ------- 13072400 10 files ``` Here, the benefit comes when there are enough shared libraries statically linking against the rust stdlibs. "Enough" here means that the total up size of those libraries being more than just the entire `libstd.so`. TODO: I'm leaving this PR without unit tests until I get some feedback or suggestions on my approach. --------- Co-authored-by: scentini <rosica@google.com>
This commit is contained in:
parent
33fdddd03c
commit
e7f55168ac
|
@ -79,7 +79,7 @@ http_archive(
|
|||
|
||||
http_archive(
|
||||
name = "rules_testing",
|
||||
sha256 = "b84ed8546f1969d700ead4546de9f7637e0f058d835e47e865dcbb13c4210aed",
|
||||
strip_prefix = "rules_testing-0.5.0",
|
||||
url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.5.0/rules_testing-v0.5.0.tar.gz",
|
||||
sha256 = "02c62574631876a4e3b02a1820cb51167bb9cdcdea2381b2fa9d9b8b11c407c4",
|
||||
strip_prefix = "rules_testing-0.6.0",
|
||||
url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.6.0/rules_testing-v0.6.0.tar.gz",
|
||||
)
|
||||
|
|
|
@ -1176,10 +1176,11 @@ Run the test with `bazel test //hello_lib:greeting_test`.
|
|||
|
||||
<pre>
|
||||
rust_toolchain(<a href="#rust_toolchain-name">name</a>, <a href="#rust_toolchain-allocator_library">allocator_library</a>, <a href="#rust_toolchain-binary_ext">binary_ext</a>, <a href="#rust_toolchain-cargo">cargo</a>, <a href="#rust_toolchain-clippy_driver">clippy_driver</a>, <a href="#rust_toolchain-debug_info">debug_info</a>,
|
||||
<a href="#rust_toolchain-default_edition">default_edition</a>, <a href="#rust_toolchain-dylib_ext">dylib_ext</a>, <a href="#rust_toolchain-env">env</a>, <a href="#rust_toolchain-exec_triple">exec_triple</a>, <a href="#rust_toolchain-experimental_use_cc_common_link">experimental_use_cc_common_link</a>,
|
||||
<a href="#rust_toolchain-extra_exec_rustc_flags">extra_exec_rustc_flags</a>, <a href="#rust_toolchain-extra_rustc_flags">extra_rustc_flags</a>, <a href="#rust_toolchain-global_allocator_library">global_allocator_library</a>, <a href="#rust_toolchain-llvm_cov">llvm_cov</a>,
|
||||
<a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>, <a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>, <a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>, <a href="#rust_toolchain-rustc">rustc</a>,
|
||||
<a href="#rust_toolchain-rustc_lib">rustc_lib</a>, <a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
|
||||
<a href="#rust_toolchain-default_edition">default_edition</a>, <a href="#rust_toolchain-dylib_ext">dylib_ext</a>, <a href="#rust_toolchain-env">env</a>, <a href="#rust_toolchain-exec_triple">exec_triple</a>, <a href="#rust_toolchain-experimental_link_std_dylib">experimental_link_std_dylib</a>,
|
||||
<a href="#rust_toolchain-experimental_use_cc_common_link">experimental_use_cc_common_link</a>, <a href="#rust_toolchain-extra_exec_rustc_flags">extra_exec_rustc_flags</a>, <a href="#rust_toolchain-extra_rustc_flags">extra_rustc_flags</a>,
|
||||
<a href="#rust_toolchain-global_allocator_library">global_allocator_library</a>, <a href="#rust_toolchain-llvm_cov">llvm_cov</a>, <a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>, <a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>,
|
||||
<a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>, <a href="#rust_toolchain-rustc">rustc</a>, <a href="#rust_toolchain-rustc_lib">rustc_lib</a>, <a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>,
|
||||
<a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
|
||||
</pre>
|
||||
|
||||
Declares a Rust toolchain for use.
|
||||
|
@ -1241,6 +1242,7 @@ See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpu
|
|||
| <a id="rust_toolchain-dylib_ext"></a>dylib_ext | The extension for dynamic libraries created from rustc. | String | required | |
|
||||
| <a id="rust_toolchain-env"></a>env | Environment variables to set in actions. | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{}</code> |
|
||||
| <a id="rust_toolchain-exec_triple"></a>exec_triple | The platform triple for the toolchains execution environment. For more details see: https://docs.bazel.build/versions/master/skylark/rules.html#configurations | String | required | |
|
||||
| <a id="rust_toolchain-experimental_link_std_dylib"></a>experimental_link_std_dylib | Label to a boolean build setting that controls whether whether to link libstd dynamically. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>@rules_rust//rust/settings:experimental_link_std_dylib</code> |
|
||||
| <a id="rust_toolchain-experimental_use_cc_common_link"></a>experimental_use_cc_common_link | Label to a boolean build setting that controls whether cc_common.link is used to link rust binaries. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//rust/settings:experimental_use_cc_common_link</code> |
|
||||
| <a id="rust_toolchain-extra_exec_rustc_flags"></a>extra_exec_rustc_flags | Extra flags to pass to rustc in exec configuration | List of strings | optional | <code>[]</code> |
|
||||
| <a id="rust_toolchain-extra_rustc_flags"></a>extra_rustc_flags | Extra flags to pass to rustc in non-exec configuration | List of strings | optional | <code>[]</code> |
|
||||
|
@ -1446,7 +1448,7 @@ A toolchain for [rustfmt](https://rust-lang.github.io/rustfmt/)
|
|||
<pre>
|
||||
CrateInfo(<a href="#CrateInfo-aliases">aliases</a>, <a href="#CrateInfo-compile_data">compile_data</a>, <a href="#CrateInfo-compile_data_targets">compile_data_targets</a>, <a href="#CrateInfo-data">data</a>, <a href="#CrateInfo-deps">deps</a>, <a href="#CrateInfo-edition">edition</a>, <a href="#CrateInfo-is_test">is_test</a>, <a href="#CrateInfo-metadata">metadata</a>, <a href="#CrateInfo-name">name</a>,
|
||||
<a href="#CrateInfo-output">output</a>, <a href="#CrateInfo-owner">owner</a>, <a href="#CrateInfo-proc_macro_deps">proc_macro_deps</a>, <a href="#CrateInfo-root">root</a>, <a href="#CrateInfo-rustc_env">rustc_env</a>, <a href="#CrateInfo-rustc_env_files">rustc_env_files</a>, <a href="#CrateInfo-rustc_output">rustc_output</a>,
|
||||
<a href="#CrateInfo-rustc_rmeta_output">rustc_rmeta_output</a>, <a href="#CrateInfo-srcs">srcs</a>, <a href="#CrateInfo-type">type</a>, <a href="#CrateInfo-wrapped_crate_type">wrapped_crate_type</a>)
|
||||
<a href="#CrateInfo-rustc_rmeta_output">rustc_rmeta_output</a>, <a href="#CrateInfo-srcs">srcs</a>, <a href="#CrateInfo-std_dylib">std_dylib</a>, <a href="#CrateInfo-type">type</a>, <a href="#CrateInfo-wrapped_crate_type">wrapped_crate_type</a>)
|
||||
</pre>
|
||||
|
||||
A provider containing general Crate information.
|
||||
|
@ -1474,6 +1476,7 @@ A provider containing general Crate information.
|
|||
| <a id="CrateInfo-rustc_output"></a>rustc_output | File: The output from rustc from producing the output file. It is optional. |
|
||||
| <a id="CrateInfo-rustc_rmeta_output"></a>rustc_rmeta_output | File: The rmeta file produced for this crate. It is optional. |
|
||||
| <a id="CrateInfo-srcs"></a>srcs | depset[File]: All source Files that are part of the crate. |
|
||||
| <a id="CrateInfo-std_dylib"></a>std_dylib | File: libstd.so file |
|
||||
| <a id="CrateInfo-type"></a>type | str: The type of this crate (see [rustc --crate-type](https://doc.rust-lang.org/rustc/command-line-arguments.html#--crate-type-a-list-of-types-of-crates-for-the-compiler-to-emit)). |
|
||||
| <a id="CrateInfo-wrapped_crate_type"></a>wrapped_crate_type | str, optional: The original crate type for targets generated using a previously defined crate (typically tests using the <code>rust_test::crate</code> attribute) |
|
||||
|
||||
|
@ -1533,8 +1536,8 @@ Info about wasm-bindgen outputs.
|
|||
|
||||
<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-memchr_files">memchr_files</a>, <a href="#StdLibInfo-panic_files">panic_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-test_files">test_files</a>)
|
||||
<a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-memchr_files">memchr_files</a>, <a href="#StdLibInfo-panic_files">panic_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_dylib">std_dylib</a>, <a href="#StdLibInfo-std_files">std_files</a>,
|
||||
<a href="#StdLibInfo-std_rlibs">std_rlibs</a>, <a href="#StdLibInfo-test_files">test_files</a>)
|
||||
</pre>
|
||||
|
||||
A collection of files either found within the `rust-stdlib` artifact or generated based on existing files.
|
||||
|
@ -1553,6 +1556,7 @@ A collection of files either found within the `rust-stdlib` artifact or generate
|
|||
| <a id="StdLibInfo-panic_files"></a>panic_files | Depset[File]: <code>.a</code> files associated with <code>panic_unwind</code> and <code>panic_abort</code>. |
|
||||
| <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_dylib"></a>std_dylib | File: libstd.so file |
|
||||
| <a id="StdLibInfo-std_files"></a>std_files | Depset[File]: <code>.a</code> files associated with the <code>std</code> module. |
|
||||
| <a id="StdLibInfo-std_rlibs"></a>std_rlibs | List[File]: All <code>.rlib</code> files |
|
||||
| <a id="StdLibInfo-test_files"></a>test_files | Depset[File]: <code>.a</code> files associated with the <code>test</code> module. |
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<pre>
|
||||
CrateInfo(<a href="#CrateInfo-aliases">aliases</a>, <a href="#CrateInfo-compile_data">compile_data</a>, <a href="#CrateInfo-compile_data_targets">compile_data_targets</a>, <a href="#CrateInfo-data">data</a>, <a href="#CrateInfo-deps">deps</a>, <a href="#CrateInfo-edition">edition</a>, <a href="#CrateInfo-is_test">is_test</a>, <a href="#CrateInfo-metadata">metadata</a>, <a href="#CrateInfo-name">name</a>,
|
||||
<a href="#CrateInfo-output">output</a>, <a href="#CrateInfo-owner">owner</a>, <a href="#CrateInfo-proc_macro_deps">proc_macro_deps</a>, <a href="#CrateInfo-root">root</a>, <a href="#CrateInfo-rustc_env">rustc_env</a>, <a href="#CrateInfo-rustc_env_files">rustc_env_files</a>, <a href="#CrateInfo-rustc_output">rustc_output</a>,
|
||||
<a href="#CrateInfo-rustc_rmeta_output">rustc_rmeta_output</a>, <a href="#CrateInfo-srcs">srcs</a>, <a href="#CrateInfo-type">type</a>, <a href="#CrateInfo-wrapped_crate_type">wrapped_crate_type</a>)
|
||||
<a href="#CrateInfo-rustc_rmeta_output">rustc_rmeta_output</a>, <a href="#CrateInfo-srcs">srcs</a>, <a href="#CrateInfo-std_dylib">std_dylib</a>, <a href="#CrateInfo-type">type</a>, <a href="#CrateInfo-wrapped_crate_type">wrapped_crate_type</a>)
|
||||
</pre>
|
||||
|
||||
A provider containing general Crate information.
|
||||
|
@ -40,6 +40,7 @@ A provider containing general Crate information.
|
|||
| <a id="CrateInfo-rustc_output"></a>rustc_output | File: The output from rustc from producing the output file. It is optional. |
|
||||
| <a id="CrateInfo-rustc_rmeta_output"></a>rustc_rmeta_output | File: The rmeta file produced for this crate. It is optional. |
|
||||
| <a id="CrateInfo-srcs"></a>srcs | depset[File]: All source Files that are part of the crate. |
|
||||
| <a id="CrateInfo-std_dylib"></a>std_dylib | File: libstd.so file |
|
||||
| <a id="CrateInfo-type"></a>type | str: The type of this crate (see [rustc --crate-type](https://doc.rust-lang.org/rustc/command-line-arguments.html#--crate-type-a-list-of-types-of-crates-for-the-compiler-to-emit)). |
|
||||
| <a id="CrateInfo-wrapped_crate_type"></a>wrapped_crate_type | str, optional: The original crate type for targets generated using a previously defined crate (typically tests using the <code>rust_test::crate</code> attribute) |
|
||||
|
||||
|
@ -79,8 +80,8 @@ A provider containing information about a Crate's dependencies.
|
|||
|
||||
<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-memchr_files">memchr_files</a>, <a href="#StdLibInfo-panic_files">panic_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-test_files">test_files</a>)
|
||||
<a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-memchr_files">memchr_files</a>, <a href="#StdLibInfo-panic_files">panic_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_dylib">std_dylib</a>, <a href="#StdLibInfo-std_files">std_files</a>,
|
||||
<a href="#StdLibInfo-std_rlibs">std_rlibs</a>, <a href="#StdLibInfo-test_files">test_files</a>)
|
||||
</pre>
|
||||
|
||||
A collection of files either found within the `rust-stdlib` artifact or generated based on existing files.
|
||||
|
@ -99,6 +100,7 @@ A collection of files either found within the `rust-stdlib` artifact or generate
|
|||
| <a id="StdLibInfo-panic_files"></a>panic_files | Depset[File]: <code>.a</code> files associated with <code>panic_unwind</code> and <code>panic_abort</code>. |
|
||||
| <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_dylib"></a>std_dylib | File: libstd.so file |
|
||||
| <a id="StdLibInfo-std_files"></a>std_files | Depset[File]: <code>.a</code> files associated with the <code>std</code> module. |
|
||||
| <a id="StdLibInfo-std_rlibs"></a>std_rlibs | List[File]: All <code>.rlib</code> files |
|
||||
| <a id="StdLibInfo-test_files"></a>test_files | Depset[File]: <code>.a</code> files associated with the <code>test</code> module. |
|
||||
|
|
|
@ -37,10 +37,11 @@ A dedicated filegroup-like rule for Rust stdlib artifacts.
|
|||
|
||||
<pre>
|
||||
rust_toolchain(<a href="#rust_toolchain-name">name</a>, <a href="#rust_toolchain-allocator_library">allocator_library</a>, <a href="#rust_toolchain-binary_ext">binary_ext</a>, <a href="#rust_toolchain-cargo">cargo</a>, <a href="#rust_toolchain-clippy_driver">clippy_driver</a>, <a href="#rust_toolchain-debug_info">debug_info</a>,
|
||||
<a href="#rust_toolchain-default_edition">default_edition</a>, <a href="#rust_toolchain-dylib_ext">dylib_ext</a>, <a href="#rust_toolchain-env">env</a>, <a href="#rust_toolchain-exec_triple">exec_triple</a>, <a href="#rust_toolchain-experimental_use_cc_common_link">experimental_use_cc_common_link</a>,
|
||||
<a href="#rust_toolchain-extra_exec_rustc_flags">extra_exec_rustc_flags</a>, <a href="#rust_toolchain-extra_rustc_flags">extra_rustc_flags</a>, <a href="#rust_toolchain-global_allocator_library">global_allocator_library</a>, <a href="#rust_toolchain-llvm_cov">llvm_cov</a>,
|
||||
<a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>, <a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>, <a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>, <a href="#rust_toolchain-rustc">rustc</a>,
|
||||
<a href="#rust_toolchain-rustc_lib">rustc_lib</a>, <a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
|
||||
<a href="#rust_toolchain-default_edition">default_edition</a>, <a href="#rust_toolchain-dylib_ext">dylib_ext</a>, <a href="#rust_toolchain-env">env</a>, <a href="#rust_toolchain-exec_triple">exec_triple</a>, <a href="#rust_toolchain-experimental_link_std_dylib">experimental_link_std_dylib</a>,
|
||||
<a href="#rust_toolchain-experimental_use_cc_common_link">experimental_use_cc_common_link</a>, <a href="#rust_toolchain-extra_exec_rustc_flags">extra_exec_rustc_flags</a>, <a href="#rust_toolchain-extra_rustc_flags">extra_rustc_flags</a>,
|
||||
<a href="#rust_toolchain-global_allocator_library">global_allocator_library</a>, <a href="#rust_toolchain-llvm_cov">llvm_cov</a>, <a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>, <a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>,
|
||||
<a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>, <a href="#rust_toolchain-rustc">rustc</a>, <a href="#rust_toolchain-rustc_lib">rustc_lib</a>, <a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>,
|
||||
<a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
|
||||
</pre>
|
||||
|
||||
Declares a Rust toolchain for use.
|
||||
|
@ -102,6 +103,7 @@ See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpu
|
|||
| <a id="rust_toolchain-dylib_ext"></a>dylib_ext | The extension for dynamic libraries created from rustc. | String | required | |
|
||||
| <a id="rust_toolchain-env"></a>env | Environment variables to set in actions. | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{}</code> |
|
||||
| <a id="rust_toolchain-exec_triple"></a>exec_triple | The platform triple for the toolchains execution environment. For more details see: https://docs.bazel.build/versions/master/skylark/rules.html#configurations | String | required | |
|
||||
| <a id="rust_toolchain-experimental_link_std_dylib"></a>experimental_link_std_dylib | Label to a boolean build setting that controls whether whether to link libstd dynamically. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>@rules_rust//rust/settings:experimental_link_std_dylib</code> |
|
||||
| <a id="rust_toolchain-experimental_use_cc_common_link"></a>experimental_use_cc_common_link | Label to a boolean build setting that controls whether cc_common.link is used to link rust binaries. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//rust/settings:experimental_use_cc_common_link</code> |
|
||||
| <a id="rust_toolchain-extra_exec_rustc_flags"></a>extra_exec_rustc_flags | Extra flags to pass to rustc in exec configuration | List of strings | optional | <code>[]</code> |
|
||||
| <a id="rust_toolchain-extra_rustc_flags"></a>extra_rustc_flags | Extra flags to pass to rustc in non-exec configuration | List of strings | optional | <code>[]</code> |
|
||||
|
|
|
@ -35,6 +35,7 @@ CrateInfo = provider(
|
|||
"rustc_output": "File: The output from rustc from producing the output file. It is optional.",
|
||||
"rustc_rmeta_output": "File: The rmeta file produced for this crate. It is optional.",
|
||||
"srcs": "depset[File]: All source Files that are part of the crate.",
|
||||
"std_dylib": "File: libstd.so file",
|
||||
"type": (
|
||||
"str: The type of this crate " +
|
||||
"(see [rustc --crate-type](https://doc.rust-lang.org/rustc/command-line-arguments.html#--crate-type-a-list-of-types-of-crates-for-the-compiler-to-emit))."
|
||||
|
@ -122,6 +123,7 @@ StdLibInfo = provider(
|
|||
"panic_files": "Depset[File]: `.a` files associated with `panic_unwind` and `panic_abort`.",
|
||||
"self_contained_files": "List[File]: All `.o` files from the `self-contained` directory.",
|
||||
"srcs": "List[Target]: All targets from the original `srcs` attribute.",
|
||||
"std_dylib": "File: libstd.so file",
|
||||
"std_files": "Depset[File]: `.a` files associated with the `std` module.",
|
||||
"std_rlibs": "List[File]: All `.rlib` files",
|
||||
"test_files": "Depset[File]: `.a` files associated with the `test` module.",
|
||||
|
|
|
@ -38,6 +38,7 @@ load(
|
|||
"make_static_lib_symlink",
|
||||
"relativize",
|
||||
)
|
||||
load(":utils.bzl", "is_std_dylib")
|
||||
|
||||
BuildInfo = _BuildInfo
|
||||
|
||||
|
@ -1035,6 +1036,9 @@ def construct_arguments(
|
|||
# https://doc.rust-lang.org/rustc/instrument-coverage.html
|
||||
rustc_flags.add("--codegen=instrument-coverage")
|
||||
|
||||
if toolchain._experimental_link_std_dylib:
|
||||
rustc_flags.add("--codegen=prefer-dynamic")
|
||||
|
||||
# Make bin crate data deps available to tests.
|
||||
for data in getattr(attr, "data", []):
|
||||
if rust_common.crate_info in data:
|
||||
|
@ -1724,6 +1728,16 @@ def _compute_rpaths(toolchain, output_dir, dep_info, use_pic):
|
|||
for lib in linker_input.libraries
|
||||
if _is_dylib(lib)
|
||||
]
|
||||
|
||||
# Include std dylib if dylib linkage is enabled
|
||||
if toolchain._experimental_link_std_dylib:
|
||||
# TODO: Make toolchain.rust_std to only include libstd.so
|
||||
# When dylib linkage is enabled, toolchain.rust_std should only need to
|
||||
# include libstd.so. Hence, no filtering needed.
|
||||
for file in toolchain.rust_std.to_list():
|
||||
if is_std_dylib(file):
|
||||
dylibs.append(file)
|
||||
|
||||
if not dylibs:
|
||||
return depset([])
|
||||
|
||||
|
|
|
@ -879,3 +879,15 @@ def generate_output_diagnostics(ctx, sibling, require_process_wrapper = True):
|
|||
sibling.basename + ".rustc-output",
|
||||
sibling = sibling,
|
||||
)
|
||||
|
||||
def is_std_dylib(file):
|
||||
"""Whether the file is a dylib crate for std
|
||||
|
||||
"""
|
||||
basename = file.basename
|
||||
return (
|
||||
# for linux and darwin
|
||||
basename.startswith("libstd-") and (basename.endswith(".so") or basename.endswith(".dylib")) or
|
||||
# for windows
|
||||
basename.startswith("std-") and basename.endswith(".dll")
|
||||
)
|
||||
|
|
|
@ -99,6 +99,12 @@ incompatible_flag(
|
|||
issue = "https://github.com/bazelbuild/rules_rust/issues/2324",
|
||||
)
|
||||
|
||||
# A flag to control whether to link libstd dynamically.
|
||||
bool_flag(
|
||||
name = "experimental_link_std_dylib",
|
||||
build_setting_default = False,
|
||||
)
|
||||
|
||||
# A flag to remove the SYSROOT environment variable from `Rustc` actions.
|
||||
incompatible_flag(
|
||||
name = "incompatible_no_rustc_sysroot_env",
|
||||
|
|
|
@ -14,6 +14,8 @@ load(
|
|||
"dedent",
|
||||
"dedup_expand_location",
|
||||
"find_cc_toolchain",
|
||||
"is_exec_configuration",
|
||||
"is_std_dylib",
|
||||
"make_static_lib_symlink",
|
||||
)
|
||||
load("//rust/settings:incompatible.bzl", "IncompatibleFlagInfo")
|
||||
|
@ -75,6 +77,13 @@ def _rust_stdlib_filegroup_impl(ctx):
|
|||
print("File partitioned: {}".format(f.basename))
|
||||
fail("rust_toolchain couldn't properly partition rlibs in rust_std. Partitioned {} out of {} files. This is probably a bug in the rule implementation.".format(partitioned_files_len, len(dot_a_files)))
|
||||
|
||||
std_dylib = None
|
||||
|
||||
for file in rust_std:
|
||||
if is_std_dylib(file):
|
||||
std_dylib = file
|
||||
break
|
||||
|
||||
return [
|
||||
DefaultInfo(
|
||||
files = depset(ctx.files.srcs),
|
||||
|
@ -87,6 +96,7 @@ def _rust_stdlib_filegroup_impl(ctx):
|
|||
core_files = core_files,
|
||||
between_core_and_std_files = between_core_and_std_files,
|
||||
std_files = std_files,
|
||||
std_dylib = std_dylib,
|
||||
test_files = test_files,
|
||||
memchr_files = memchr_files,
|
||||
alloc_files = alloc_files,
|
||||
|
@ -237,14 +247,27 @@ def _make_libstd_and_allocator_ccinfo(ctx, rust_std, allocator_library, std = "s
|
|||
transitive = [memchr_inputs],
|
||||
order = "topological",
|
||||
)
|
||||
std_inputs = depset(
|
||||
[
|
||||
_ltl(f, ctx, cc_toolchain, feature_configuration)
|
||||
for f in rust_stdlib_info.std_files
|
||||
],
|
||||
transitive = [between_core_and_std_inputs],
|
||||
order = "topological",
|
||||
)
|
||||
|
||||
if _experimental_link_std_dylib(ctx):
|
||||
# std dylib has everything so that we do not need to include all std_files
|
||||
std_inputs = depset(
|
||||
[cc_common.create_library_to_link(
|
||||
actions = ctx.actions,
|
||||
feature_configuration = feature_configuration,
|
||||
cc_toolchain = cc_toolchain,
|
||||
dynamic_library = rust_stdlib_info.std_dylib,
|
||||
)],
|
||||
)
|
||||
else:
|
||||
std_inputs = depset(
|
||||
[
|
||||
_ltl(f, ctx, cc_toolchain, feature_configuration)
|
||||
for f in rust_stdlib_info.std_files
|
||||
],
|
||||
transitive = [between_core_and_std_inputs],
|
||||
order = "topological",
|
||||
)
|
||||
|
||||
test_inputs = depset(
|
||||
[
|
||||
_ltl(f, ctx, cc_toolchain, feature_configuration)
|
||||
|
@ -454,6 +477,9 @@ def _generate_sysroot(
|
|||
sysroot_anchor = sysroot_anchor,
|
||||
)
|
||||
|
||||
def _experimental_use_cc_common_link(ctx):
|
||||
return ctx.attr.experimental_use_cc_common_link[BuildSettingInfo].value
|
||||
|
||||
def _rust_toolchain_impl(ctx):
|
||||
"""The rust_toolchain implementation
|
||||
|
||||
|
@ -477,15 +503,14 @@ def _rust_toolchain_impl(ctx):
|
|||
pipelined_compilation = ctx.attr._pipelined_compilation[BuildSettingInfo].value
|
||||
no_std = ctx.attr._no_std[BuildSettingInfo].value
|
||||
|
||||
experimental_use_cc_common_link = ctx.attr.experimental_use_cc_common_link[BuildSettingInfo].value
|
||||
experimental_use_global_allocator = ctx.attr._experimental_use_global_allocator[BuildSettingInfo].value
|
||||
if experimental_use_cc_common_link:
|
||||
if _experimental_use_cc_common_link(ctx):
|
||||
if experimental_use_global_allocator and not ctx.attr.global_allocator_library:
|
||||
fail("rust_toolchain.experimental_use_cc_common_link with --@rules_rust//rust/settings:experimental_use_global_allocator " +
|
||||
"requires rust_toolchain.global_allocator_library to be set")
|
||||
if not ctx.attr.allocator_library:
|
||||
fail("rust_toolchain.experimental_use_cc_common_link requires rust_toolchain.allocator_library to be set")
|
||||
if experimental_use_global_allocator and not experimental_use_cc_common_link:
|
||||
if experimental_use_global_allocator and not _experimental_use_cc_common_link(ctx):
|
||||
fail(
|
||||
"Using @rules_rust//rust/settings:experimental_use_global_allocator requires" +
|
||||
"--@rules_rust//rust/settings:experimental_use_cc_common_link to be set",
|
||||
|
@ -639,7 +664,8 @@ def _rust_toolchain_impl(ctx):
|
|||
_rename_first_party_crates = rename_first_party_crates,
|
||||
_third_party_dir = third_party_dir,
|
||||
_pipelined_compilation = pipelined_compilation,
|
||||
_experimental_use_cc_common_link = experimental_use_cc_common_link,
|
||||
_experimental_link_std_dylib = _experimental_link_std_dylib(ctx),
|
||||
_experimental_use_cc_common_link = _experimental_use_cc_common_link(ctx),
|
||||
_experimental_use_global_allocator = experimental_use_global_allocator,
|
||||
_experimental_use_coverage_metadata_files = ctx.attr._experimental_use_coverage_metadata_files[BuildSettingInfo].value,
|
||||
_experimental_toolchain_generated_sysroot = ctx.attr._experimental_toolchain_generated_sysroot[IncompatibleFlagInfo].enabled,
|
||||
|
@ -652,6 +678,11 @@ def _rust_toolchain_impl(ctx):
|
|||
make_variable_info,
|
||||
]
|
||||
|
||||
def _experimental_link_std_dylib(ctx):
|
||||
return not is_exec_configuration(ctx) and \
|
||||
ctx.attr.experimental_link_std_dylib[BuildSettingInfo].value and \
|
||||
ctx.attr.rust_std[rust_common.stdlib_info].std_dylib != None
|
||||
|
||||
rust_toolchain = rule(
|
||||
implementation = _rust_toolchain_impl,
|
||||
fragments = ["cpp"],
|
||||
|
@ -702,6 +733,10 @@ rust_toolchain = rule(
|
|||
),
|
||||
mandatory = True,
|
||||
),
|
||||
"experimental_link_std_dylib": attr.label(
|
||||
default = Label("@rules_rust//rust/settings:experimental_link_std_dylib"),
|
||||
doc = "Label to a boolean build setting that controls whether whether to link libstd dynamically.",
|
||||
),
|
||||
"experimental_use_cc_common_link": attr.label(
|
||||
default = Label("//rust/settings:experimental_use_cc_common_link"),
|
||||
doc = "Label to a boolean build setting that controls whether cc_common.link is used to link rust binaries.",
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
load(":link_std_dylib_test.bzl", "link_std_dylib_test_suite")
|
||||
|
||||
link_std_dylib_test_suite(name = "link_std_dylib_test_suite")
|
|
@ -0,0 +1,7 @@
|
|||
// Analysis test shouldn't need this file.
|
||||
// This is a workaround until
|
||||
// https://github.com/bazelbuild/rules_rust/issues/2499
|
||||
// is fixed
|
||||
pub fn example_test_dep_fn() -> u32 {
|
||||
1
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
"""Analysis tests for experimental_link_std_dylib flag"""
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "CcInfo")
|
||||
load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library")
|
||||
load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite")
|
||||
|
||||
# buildifier: disable=bzl-visibility
|
||||
load("//rust/private:utils.bzl", "is_std_dylib")
|
||||
|
||||
def _test_rust_binary_impl(env, targets):
|
||||
env.expect.that_action(targets.default_binary.actions[0]) \
|
||||
.contains_none_of_flag_values([
|
||||
("--codegen", "prefer-dynamic"),
|
||||
])
|
||||
|
||||
# Make sure with @rules_rust//rust/settings:experimental_link_std_dylib,
|
||||
# the linker flags are set up correct so that the binary dynamically links
|
||||
# the stdlib
|
||||
env.expect.that_action(targets.binary_with_std_dylib.actions[0]) \
|
||||
.contains_flag_values([
|
||||
("--codegen", "prefer-dynamic"),
|
||||
])
|
||||
|
||||
def _test_rust_binary(name):
|
||||
rust_binary(
|
||||
name = name + "_rust_binary",
|
||||
srcs = ["main.rs"],
|
||||
edition = "2021",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
analysis_test(
|
||||
name = name,
|
||||
impl = _test_rust_binary_impl,
|
||||
targets = {
|
||||
"binary_with_std_dylib": name + "_rust_binary",
|
||||
"default_binary": name + "_rust_binary",
|
||||
},
|
||||
attrs = {
|
||||
"binary_with_std_dylib": {
|
||||
"@config_settings": {
|
||||
str(Label("@rules_rust//rust/settings:experimental_link_std_dylib")): True,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
def _export_static_stdlibs_in_cc_info(target):
|
||||
linker_inputs = target[CcInfo].linking_context.linker_inputs
|
||||
for linker_input in linker_inputs.to_list():
|
||||
for library in linker_input.libraries:
|
||||
if hasattr(library, "pic_static_library") and library.pic_static_library != None:
|
||||
basename = library.pic_static_library.basename
|
||||
if basename.startswith("libstd") and basename.endswith(".a"):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _export_libstd_dylib_in_cc_info(target):
|
||||
linker_inputs = target[CcInfo].linking_context.linker_inputs
|
||||
for linker_input in linker_inputs.to_list():
|
||||
for library in linker_input.libraries:
|
||||
if hasattr(library, "dynamic_library") and library.dynamic_library != None:
|
||||
if is_std_dylib(library.dynamic_library):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _test_rust_library_impl(env, targets):
|
||||
# By default, rust_library exports static stdlibs to downstream shared
|
||||
# and binary targets to statically link
|
||||
env.expect \
|
||||
.that_bool(_export_static_stdlibs_in_cc_info(targets.default_rlib)) \
|
||||
.equals(True)
|
||||
env.expect \
|
||||
.that_bool(_export_libstd_dylib_in_cc_info(targets.default_rlib)) \
|
||||
.equals(False)
|
||||
|
||||
# With @rules_rust//rust/settings:experimental_link_std_dylib
|
||||
# rust_library exports dylib std and does not export static stdlibs to
|
||||
# downstream shared and binary targets to dynamically link
|
||||
env.expect \
|
||||
.that_bool(_export_static_stdlibs_in_cc_info(targets.rlib_with_std_dylib)) \
|
||||
.equals(False)
|
||||
env.expect \
|
||||
.that_bool(_export_libstd_dylib_in_cc_info(targets.rlib_with_std_dylib)) \
|
||||
.equals(True)
|
||||
|
||||
def _test_rust_library(name):
|
||||
rust_library(
|
||||
name = name + "_rust_library",
|
||||
srcs = ["lib.rs"],
|
||||
edition = "2021",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
analysis_test(
|
||||
name = name,
|
||||
impl = _test_rust_library_impl,
|
||||
targets = {
|
||||
"default_rlib": name + "_rust_library",
|
||||
"rlib_with_std_dylib": name + "_rust_library",
|
||||
},
|
||||
attrs = {
|
||||
"rlib_with_std_dylib": {
|
||||
"@config_settings": {
|
||||
str(Label("@rules_rust//rust/settings:experimental_link_std_dylib")): True,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
def link_std_dylib_test_suite(name):
|
||||
test_suite(
|
||||
name = name,
|
||||
tests = [
|
||||
_test_rust_binary,
|
||||
_test_rust_library,
|
||||
],
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
// Analysis test shouldn't need this file.
|
||||
// This is a workaround until
|
||||
// https://github.com/bazelbuild/rules_rust/issues/2499
|
||||
// is fixed
|
||||
fn main() {
|
||||
println!("Hello world");
|
||||
}
|
Loading…
Reference in New Issue