From 3bda9249a8acb57e6be5838b3183f76667ae8e3c Mon Sep 17 00:00:00 2001 From: Marcel Hlopko Date: Tue, 16 Feb 2021 09:18:55 +0100 Subject: [PATCH] Split rust_library and add //rust:defs.bzl This PR splits rust_library into multiple smaller rules: * rust_library: rust_library will represent a non-transitive library similar to how cc_library, java_library and others behave. It will always provide CrateInfo, and depending on it will always mean you can access the crate from source. Once we support dynamic linking we can consider producing both rlib and dylib from rust_library, but let's leave that for another discussion. * rust_static_library: this will only provide CcInfo and it will represent an archive of all transitive objects, both Rustc-made and native. * rust_shared_library: this will only provide CcInfo and it will represent an shared library of all transitive objects, both Rustc-made and native. * rust_proc_macro: similar to rust_library, but with different crate_type passed to rustc and different validation logic for its attributes. I this this makes sense based on these observations: * Right now rust_library covers all possible crate types except `bin`. * rust_library always provides CrateInfo, rust_libraries can depend on other rust_libraries. * When the crate type is `cdylib` or `staticlib`, rust_library provides CcInfo. * When the crate type is `cdylib` or `staticlib`, Rust code will not be able to access the crate by `extern crate Foo` in the source; the behavior will be similar to depending on a CcInfo providing rule. I believe smaller rules will make them less confusing and will allow us to have more focused implementations. This PR is mostly backwards compatible. //rust:rust.bzl#rust_library is a macro. If the crate_type attribute is present, macro dispatches to the right new rule. If it's not present, macro will choose the new rust_library. New rules are added, so people can migrate at their own pace. defs.bzl is the bzl file that we now expect people to load. Bazel docs recommend to store public rules in defs.bzl (https://docs.bazel.build/versions/master/skylark/deploying.html#repository-content). This change was first socialized at https://groups.google.com/g/rules_rust/c/kGMg6haEF44. Regenerate documentation Regenerate documentation Regenerate documentation Regenerate documentation Regenerate documentation --- docs/BUILD | 7 +- docs/all.bzl | 24 +- docs/{rust.md => defs.md} | 372 +++++---- docs/flatten.md | 370 +++++---- docs/index.md | 2 +- rust/BUILD | 1 + rust/defs.bzl | 98 +++ rust/private/rust.bzl | 829 ++++++++++++--------- rust/rust.bzl | 59 +- test/unit/native_deps/native_deps_test.bzl | 40 +- 10 files changed, 1104 insertions(+), 698 deletions(-) rename docs/{rust.md => defs.md} (53%) create mode 100644 rust/defs.bzl diff --git a/docs/BUILD b/docs/BUILD index 945d56605b..d526b95fd3 100644 --- a/docs/BUILD +++ b/docs/BUILD @@ -31,9 +31,12 @@ PAGES = { "cargo_build_script": [ "cargo_build_script", ], - "rust": [ - "rust_library", + "defs": [ "rust_binary", + "rust_library", + "rust_static_library", + "rust_shared_library", + "rust_proc_macro", "rust_benchmark", "rust_test", ], diff --git a/docs/all.bzl b/docs/all.bzl index 15b2569988..67c1054619 100644 --- a/docs/all.bzl +++ b/docs/all.bzl @@ -30,14 +30,7 @@ load( _rust_proto_toolchain = "rust_proto_toolchain", ) load( - "@rules_rust//rust:repositories.bzl", - _rust_repositories = "rust_repositories", - _rust_repository_set = "rust_repository_set", - _rust_toolchain_repository = "rust_toolchain_repository", - _rust_toolchain_repository_proxy = "rust_toolchain_repository_proxy", -) -load( - "@rules_rust//rust:rust.bzl", + "@rules_rust//rust:defs.bzl", _rust_analyzer = "rust_analyzer", _rust_benchmark = "rust_benchmark", _rust_binary = "rust_binary", @@ -45,8 +38,18 @@ load( _rust_doc = "rust_doc", _rust_doc_test = "rust_doc_test", _rust_library = "rust_library", + _rust_proc_macro = "rust_proc_macro", + _rust_shared_library = "rust_shared_library", + _rust_static_library = "rust_static_library", _rust_test = "rust_test", ) +load( + "@rules_rust//rust:repositories.bzl", + _rust_repositories = "rust_repositories", + _rust_repository_set = "rust_repository_set", + _rust_toolchain_repository = "rust_toolchain_repository", + _rust_toolchain_repository_proxy = "rust_toolchain_repository_proxy", +) load( "@rules_rust//rust:toolchain.bzl", _rust_toolchain = "rust_toolchain", @@ -61,8 +64,11 @@ load( _rust_wasm_bindgen_toolchain = "rust_wasm_bindgen_toolchain", ) -rust_library = _rust_library rust_binary = _rust_binary +rust_library = _rust_library +rust_static_library = _rust_static_library +rust_shared_library = _rust_shared_library +rust_proc_macro = _rust_proc_macro rust_test = _rust_test rust_doc = _rust_doc rust_doc_test = _rust_doc_test diff --git a/docs/rust.md b/docs/defs.md similarity index 53% rename from docs/rust.md rename to docs/defs.md index 929934477d..a0e69b32a5 100644 --- a/docs/rust.md +++ b/docs/defs.md @@ -1,6 +1,9 @@ # Rust rules -* [rust_library](#rust_library) * [rust_binary](#rust_binary) +* [rust_library](#rust_library) +* [rust_static_library](#rust_static_library) +* [rust_shared_library](#rust_shared_library) +* [rust_proc_macro](#rust_proc_macro) * [rust_benchmark](#rust_benchmark) * [rust_test](#rust_test) @@ -15,39 +18,39 @@ rust_benchmark(name, -rust_binary(name, aliases, compile_data, crate_features, crate_root, crate_type, data, deps, - edition, linker_script, out_binary, out_dir_tar, proc_macro_deps, rustc_env, - rustc_env_files, rustc_flags, srcs, version) +rust_binary(name, aliases, compile_data, crate_features, crate_root, data, deps, edition, + linker_script, out_binary, out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, + rustc_flags, srcs, version) Builds a Rust binary crate. @@ -131,31 +134,31 @@ library crate, `hello_lib`, and a binary crate, `hello_world` that uses the ```output [workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs - hello_world/ - BUILD - src/ - main.rs +WORKSPACE +hello_lib/ +BUILD +src/ +lib.rs +hello_world/ +BUILD +src/ +main.rs ``` `hello_lib/src/lib.rs`: ```rust pub struct Greeter { - greeting: String, +greeting: String, } impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } +pub fn new(greeting: &str) -> Greeter { +Greeter { greeting: greeting.to_string(), } +} - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } +pub fn greet(&self, thing: &str) { +println!("{} {}", &self.greeting, thing); +} } ``` @@ -166,8 +169,8 @@ package(default_visibility = ["//visibility:public"]) load("@rules_rust//rust:rust.bzl", "rust_library") rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], +name = "hello_lib", +srcs = ["src/lib.rs"], ) ``` @@ -176,8 +179,8 @@ rust_library( extern crate hello_lib; fn main() { - let hello = hello_lib::Greeter::new("Hello"); - hello.greet("world"); +let hello = hello_lib::Greeter::new("Hello"); +hello.greet("world"); } ``` @@ -186,9 +189,9 @@ fn main() { load("@rules_rust//rust:rust.bzl", "rust_binary") rust_binary( - name = "hello_world", - srcs = ["src/main.rs"], - deps = ["//hello_lib"], +name = "hello_world", +srcs = ["src/main.rs"], +deps = ["//hello_lib"], ) ``` @@ -197,14 +200,13 @@ Build and run `hello_world`: $ bazel run //hello_world INFO: Found 1 target... Target //examples/rust/hello_world:hello_world up-to-date: - bazel-bin/examples/rust/hello_world/hello_world +bazel-bin/examples/rust/hello_world/hello_world INFO: Elapsed time: 1.308s, Critical Path: 1.22s INFO: Running command line: bazel-bin/examples/rust/hello_world/hello_world Hello world ``` - **ATTRIBUTES** @@ -215,7 +217,6 @@ Hello world | compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | | crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | | crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | -| crate_type | - | String | optional | "bin" | | data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | | deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | | edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | @@ -235,9 +236,8 @@ Hello world ## rust_library
-rust_library(name, aliases, compile_data, crate_features, crate_root, crate_type, data, deps,
-             edition, out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs,
-             version)
+rust_library(name, aliases, compile_data, crate_features, crate_root, data, deps, edition,
+             out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs, version)
 
Builds a Rust library crate. @@ -248,28 +248,28 @@ Suppose you have the following directory structure for a simple Rust library cra ```output [workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - greeter.rs - lib.rs +WORKSPACE +hello_lib/ +BUILD +src/ +greeter.rs +lib.rs ``` `hello_lib/src/greeter.rs`: ```rust pub struct Greeter { - greeting: String, +greeting: String, } impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } +pub fn new(greeting: &str) -> Greeter { +Greeter { greeting: greeting.to_string(), } +} - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } +pub fn greet(&self, thing: &str) { +println!("{} {}", &self.greeting, thing); +} } ``` @@ -286,11 +286,11 @@ package(default_visibility = ["//visibility:public"]) load("@rules_rust//rust:rust.bzl", "rust_library") rust_library( - name = "hello_lib", - srcs = [ - "src/greeter.rs", - "src/lib.rs", - ], +name = "hello_lib", +srcs = [ +"src/greeter.rs", +"src/lib.rs", +], ) ``` @@ -299,7 +299,7 @@ Build the library: $ bazel build //hello_lib INFO: Found 1 target... Target //examples/rust/hello_lib:hello_lib up-to-date: - bazel-bin/examples/rust/hello_lib/libhello_lib.rlib +bazel-bin/examples/rust/hello_lib/libhello_lib.rlib INFO: Elapsed time: 1.245s, Critical Path: 1.01s ``` @@ -314,7 +314,6 @@ INFO: Elapsed time: 1.245s, Critical Path: 1.01s | compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | | crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | | crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | -| crate_type | The type of linkage to use for building this library. Options include "lib", "rlib", "dylib", "cdylib", "staticlib", and "proc-macro".

The exact output file will depend on the toolchain used. | String | optional | "rlib" | | data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | | deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | | edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | @@ -327,6 +326,126 @@ INFO: Elapsed time: 1.245s, Critical Path: 1.01s | version | A version to inject in the cargo environment variable. | String | optional | "0.0.0" | + + +## rust_proc_macro + +
+rust_proc_macro(name, aliases, compile_data, crate_features, crate_root, data, deps, edition,
+                out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs, version)
+
+ +Builds a Rust proc-macro crate. + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| aliases | Remap crates to a new name or moniker for linkage to this target

These are other rust_library targets and will be presented as the new name given. | Dictionary: Label -> String | optional | {} | +| compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | +| crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | +| crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | +| data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | +| deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | +| edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | +| out_dir_tar | __Deprecated__, do not use, see [#cargo_build_script] instead. | Label | optional | None | +| proc_macro_deps | List of rust_library targets with kind proc-macro used to help build this library target. | List of labels | optional | [] | +| rustc_env | Dictionary of additional "key": "value" environment variables to set for rustc.

rust_test()/rust_binary() rules can use $(rootpath //package:target) to pass in the location of a generated file or external tool. Cargo build scripts that wish to expand locations should use cargo_build_script()'s build_script_env argument instead, as build scripts are run in a different environment - see cargo_build_script()'s documentation for more. | Dictionary: String -> String | optional | {} | +| rustc_env_files | Files containing additional environment variables to set for rustc.

These 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 (\).

The order that these files will be processed is unspecified, so multiple definitions of a particular variable are discouraged. | List of labels | optional | [] | +| rustc_flags | List of compiler flags passed to rustc. | List of strings | optional | [] | +| srcs | List of Rust .rs source files used to build the library.

If srcs contains more than one file, then there must be a file either named lib.rs. Otherwise, crate_root must be set to the source file that is the root of the crate to be passed to rustc to build this crate. | List of labels | optional | [] | +| version | A version to inject in the cargo environment variable. | String | optional | "0.0.0" | + + + + +## rust_shared_library + +
+rust_shared_library(name, aliases, compile_data, crate_features, crate_root, data, deps, edition,
+                    out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs,
+                    version)
+
+ +Builds a Rust shared library. + +This shared library will contain all transitively reachable crates and native objects. +It is meant to be used when producing an artifact that is then consumed by some other build system +(for example to produce a shared library that Python program links against). + +This rule provides CcInfo, so it can be used everywhere Bazel expects `rules_cc`. + +When building the whole binary in Bazel, use `rust_library` instead. + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| aliases | Remap crates to a new name or moniker for linkage to this target

These are other rust_library targets and will be presented as the new name given. | Dictionary: Label -> String | optional | {} | +| compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | +| crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | +| crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | +| data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | +| deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | +| edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | +| out_dir_tar | __Deprecated__, do not use, see [#cargo_build_script] instead. | Label | optional | None | +| proc_macro_deps | List of rust_library targets with kind proc-macro used to help build this library target. | List of labels | optional | [] | +| rustc_env | Dictionary of additional "key": "value" environment variables to set for rustc.

rust_test()/rust_binary() rules can use $(rootpath //package:target) to pass in the location of a generated file or external tool. Cargo build scripts that wish to expand locations should use cargo_build_script()'s build_script_env argument instead, as build scripts are run in a different environment - see cargo_build_script()'s documentation for more. | Dictionary: String -> String | optional | {} | +| rustc_env_files | Files containing additional environment variables to set for rustc.

These 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 (\).

The order that these files will be processed is unspecified, so multiple definitions of a particular variable are discouraged. | List of labels | optional | [] | +| rustc_flags | List of compiler flags passed to rustc. | List of strings | optional | [] | +| srcs | List of Rust .rs source files used to build the library.

If srcs contains more than one file, then there must be a file either named lib.rs. Otherwise, crate_root must be set to the source file that is the root of the crate to be passed to rustc to build this crate. | List of labels | optional | [] | +| version | A version to inject in the cargo environment variable. | String | optional | "0.0.0" | + + + + +## rust_static_library + +
+rust_static_library(name, aliases, compile_data, crate_features, crate_root, data, deps, edition,
+                    out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs,
+                    version)
+
+ +Builds a Rust static library. + +This static library will contain all transitively reachable crates and native objects. +It is meant to be used when producing an artifact that is then consumed by some other build system +(for example to produce an archive that Python program links against). + +This rule provides CcInfo, so it can be used everywhere Bazel expects `rules_cc`. + +When building the whole binary in Bazel, use `rust_library` instead. + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| aliases | Remap crates to a new name or moniker for linkage to this target

These are other rust_library targets and will be presented as the new name given. | Dictionary: Label -> String | optional | {} | +| compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | +| crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | +| crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | +| data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | +| deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | +| edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | +| out_dir_tar | __Deprecated__, do not use, see [#cargo_build_script] instead. | Label | optional | None | +| proc_macro_deps | List of rust_library targets with kind proc-macro used to help build this library target. | List of labels | optional | [] | +| rustc_env | Dictionary of additional "key": "value" environment variables to set for rustc.

rust_test()/rust_binary() rules can use $(rootpath //package:target) to pass in the location of a generated file or external tool. Cargo build scripts that wish to expand locations should use cargo_build_script()'s build_script_env argument instead, as build scripts are run in a different environment - see cargo_build_script()'s documentation for more. | Dictionary: String -> String | optional | {} | +| rustc_env_files | Files containing additional environment variables to set for rustc.

These 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 (\).

The order that these files will be processed is unspecified, so multiple definitions of a particular variable are discouraged. | List of labels | optional | [] | +| rustc_flags | List of compiler flags passed to rustc. | List of strings | optional | [] | +| srcs | List of Rust .rs source files used to build the library.

If srcs contains more than one file, then there must be a file either named lib.rs. Otherwise, crate_root must be set to the source file that is the root of the crate to be passed to rustc to build this crate. | List of labels | optional | [] | +| version | A version to inject in the cargo environment variable. | String | optional | "0.0.0" | + + ## rust_test @@ -340,92 +459,92 @@ Builds a Rust test crate. Examples: -Suppose you have the following directory structure for a Rust library crate with unit test code in the library sources: +Suppose you have the following directory structure for a Rust library crate with unit test code in the library sources: ```output [workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs +WORKSPACE +hello_lib/ +BUILD +src/ +lib.rs ``` `hello_lib/src/lib.rs`: ```rust pub struct Greeter { - greeting: String, +greeting: String, } impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } +pub fn new(greeting: &str) -> Greeter { +Greeter { greeting: greeting.to_string(), } +} - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } +pub fn greet(&self, thing: &str) { +println!("{} {}", &self.greeting, thing); +} } #[cfg(test)] mod test { - use super::Greeter; +use super::Greeter; - #[test] - fn test_greeting() { - let hello = Greeter::new("Hi"); - assert_eq!("Hi Rust", hello.greet("Rust")); - } +#[test] +fn test_greeting() { +let hello = Greeter::new("Hi"); +assert_eq!("Hi Rust", hello.greet("Rust")); +} } ``` -To build and run the tests, simply add a `rust_test` rule with no `srcs` and only depends on the `hello_lib` `rust_library` target: +To build and run the tests, simply add a `rust_test` rule with no `srcs` and only depends on the `hello_lib` `rust_library` target: `hello_lib/BUILD`: ```python package(default_visibility = ["//visibility:public"]) -load("@rules_rust//rust:rust.bzl", "rust_library", "rust_test") +load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], +name = "hello_lib", +srcs = ["src/lib.rs"], ) rust_test( - name = "hello_lib_test", - deps = [":hello_lib"], +name = "hello_lib_test", +deps = [":hello_lib"], ) ``` Run the test with `bazel build //hello_lib:hello_lib_test`. -To run a crate or lib with the `#[cfg(test)]` configuration, handling inline tests, you should specify the crate directly like so. +To run a crate or lib with the `#[cfg(test)]` configuration, handling inline tests, you should specify the crate directly like so. ```python rust_test( - name = "hello_lib_test", - crate = ":hello_lib", - # You may add other deps that are specific to the test configuration - deps = ["//some/dev/dep"], +name = "hello_lib_test", +crate = ":hello_lib", +# You may add other deps that are specific to the test configuration +deps = ["//some/dev/dep"], ) ``` ### Example: `test` directory -Integration tests that live in the [`tests` directory][int-tests], they are essentially built as separate crates. Suppose you have the following directory structure where `greeting.rs` is an integration test for the `hello_lib` library crate: +Integration tests that live in the [`tests` directory][int-tests], they are essentially built as separate crates. Suppose you have the following directory structure where `greeting.rs` is an integration test for the `hello_lib` library crate: [int-tests]: http://doc.rust-lang.org/book/testing.html#the-tests-directory ```output [workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs - tests/ - greeting.rs +WORKSPACE +hello_lib/ +BUILD +src/ +lib.rs +tests/ +greeting.rs ``` `hello_lib/tests/greeting.rs`: @@ -436,8 +555,8 @@ use hello_lib; #[test] fn test_greeting() { - let hello = greeter::Greeter::new("Hello"); - assert_eq!("Hello world", hello.greeting("world")); +let hello = greeter::Greeter::new("Hello"); +assert_eq!("Hello world", hello.greeting("world")); } ``` @@ -448,23 +567,22 @@ with `greeting.rs` in `srcs` and a dependency on the `hello_lib` target: ```python package(default_visibility = ["//visibility:public"]) -load("@rules_rust//rust:rust.bzl", "rust_library", "rust_test") +load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], +name = "hello_lib", +srcs = ["src/lib.rs"], ) rust_test( - name = "greeting_test", - srcs = ["tests/greeting.rs"], - deps = [":hello_lib"], +name = "greeting_test", +srcs = ["tests/greeting.rs"], +deps = [":hello_lib"], ) ``` Run the test with `bazel build //hello_lib:hello_lib_test`. - **ATTRIBUTES** diff --git a/docs/flatten.md b/docs/flatten.md index 872eb04022..b6cc6a3376 100644 --- a/docs/flatten.md +++ b/docs/flatten.md @@ -15,11 +15,14 @@ * [rust_doc_test](#rust_doc_test) * [rust_grpc_library](#rust_grpc_library) * [rust_library](#rust_library) +* [rust_proc_macro](#rust_proc_macro) * [rust_proto_library](#rust_proto_library) * [rust_proto_repositories](#rust_proto_repositories) * [rust_proto_toolchain](#rust_proto_toolchain) * [rust_repositories](#rust_repositories) * [rust_repository_set](#rust_repository_set) +* [rust_shared_library](#rust_shared_library) +* [rust_static_library](#rust_static_library) * [rust_test](#rust_test) * [rust_toolchain](#rust_toolchain) * [rust_toolchain_repository](#rust_toolchain_repository) @@ -59,39 +62,39 @@ rust_benchmark(name, -rust_binary(name, aliases, compile_data, crate_features, crate_root, crate_type, data, deps, - edition, linker_script, out_binary, out_dir_tar, proc_macro_deps, rustc_env, - rustc_env_files, rustc_flags, srcs, version) +rust_binary(name, aliases, compile_data, crate_features, crate_root, data, deps, edition, + linker_script, out_binary, out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, + rustc_flags, srcs, version) Builds a Rust binary crate. @@ -175,31 +178,31 @@ library crate, `hello_lib`, and a binary crate, `hello_world` that uses the ```output [workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs - hello_world/ - BUILD - src/ - main.rs +WORKSPACE +hello_lib/ +BUILD +src/ +lib.rs +hello_world/ +BUILD +src/ +main.rs ``` `hello_lib/src/lib.rs`: ```rust pub struct Greeter { - greeting: String, +greeting: String, } impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } +pub fn new(greeting: &str) -> Greeter { +Greeter { greeting: greeting.to_string(), } +} - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } +pub fn greet(&self, thing: &str) { +println!("{} {}", &self.greeting, thing); +} } ``` @@ -210,8 +213,8 @@ package(default_visibility = ["//visibility:public"]) load("@rules_rust//rust:rust.bzl", "rust_library") rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], +name = "hello_lib", +srcs = ["src/lib.rs"], ) ``` @@ -220,8 +223,8 @@ rust_library( extern crate hello_lib; fn main() { - let hello = hello_lib::Greeter::new("Hello"); - hello.greet("world"); +let hello = hello_lib::Greeter::new("Hello"); +hello.greet("world"); } ``` @@ -230,9 +233,9 @@ fn main() { load("@rules_rust//rust:rust.bzl", "rust_binary") rust_binary( - name = "hello_world", - srcs = ["src/main.rs"], - deps = ["//hello_lib"], +name = "hello_world", +srcs = ["src/main.rs"], +deps = ["//hello_lib"], ) ``` @@ -241,14 +244,13 @@ Build and run `hello_world`: $ bazel run //hello_world INFO: Found 1 target... Target //examples/rust/hello_world:hello_world up-to-date: - bazel-bin/examples/rust/hello_world/hello_world +bazel-bin/examples/rust/hello_world/hello_world INFO: Elapsed time: 1.308s, Critical Path: 1.22s INFO: Running command line: bazel-bin/examples/rust/hello_world/hello_world Hello world ``` - **ATTRIBUTES** @@ -259,7 +261,6 @@ Hello world | compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | | crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | | crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | -| crate_type | - | String | optional | "bin" | | data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | | deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | | edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | @@ -535,9 +536,8 @@ rust_binary( ## rust_library
-rust_library(name, aliases, compile_data, crate_features, crate_root, crate_type, data, deps,
-             edition, out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs,
-             version)
+rust_library(name, aliases, compile_data, crate_features, crate_root, data, deps, edition,
+             out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs, version)
 
Builds a Rust library crate. @@ -548,28 +548,28 @@ Suppose you have the following directory structure for a simple Rust library cra ```output [workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - greeter.rs - lib.rs +WORKSPACE +hello_lib/ +BUILD +src/ +greeter.rs +lib.rs ``` `hello_lib/src/greeter.rs`: ```rust pub struct Greeter { - greeting: String, +greeting: String, } impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } +pub fn new(greeting: &str) -> Greeter { +Greeter { greeting: greeting.to_string(), } +} - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } +pub fn greet(&self, thing: &str) { +println!("{} {}", &self.greeting, thing); +} } ``` @@ -586,11 +586,11 @@ package(default_visibility = ["//visibility:public"]) load("@rules_rust//rust:rust.bzl", "rust_library") rust_library( - name = "hello_lib", - srcs = [ - "src/greeter.rs", - "src/lib.rs", - ], +name = "hello_lib", +srcs = [ +"src/greeter.rs", +"src/lib.rs", +], ) ``` @@ -599,7 +599,7 @@ Build the library: $ bazel build //hello_lib INFO: Found 1 target... Target //examples/rust/hello_lib:hello_lib up-to-date: - bazel-bin/examples/rust/hello_lib/libhello_lib.rlib +bazel-bin/examples/rust/hello_lib/libhello_lib.rlib INFO: Elapsed time: 1.245s, Critical Path: 1.01s ``` @@ -614,7 +614,6 @@ INFO: Elapsed time: 1.245s, Critical Path: 1.01s | compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | | crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | | crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | -| crate_type | The type of linkage to use for building this library. Options include "lib", "rlib", "dylib", "cdylib", "staticlib", and "proc-macro".

The exact output file will depend on the toolchain used. | String | optional | "rlib" | | data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | | deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | | edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | @@ -627,6 +626,40 @@ INFO: Elapsed time: 1.245s, Critical Path: 1.01s | version | A version to inject in the cargo environment variable. | String | optional | "0.0.0" | + + +## rust_proc_macro + +
+rust_proc_macro(name, aliases, compile_data, crate_features, crate_root, data, deps, edition,
+                out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs, version)
+
+ +Builds a Rust proc-macro crate. + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| aliases | Remap crates to a new name or moniker for linkage to this target

These are other rust_library targets and will be presented as the new name given. | Dictionary: Label -> String | optional | {} | +| compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | +| crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | +| crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | +| data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | +| deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | +| edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | +| out_dir_tar | __Deprecated__, do not use, see [#cargo_build_script] instead. | Label | optional | None | +| proc_macro_deps | List of rust_library targets with kind proc-macro used to help build this library target. | List of labels | optional | [] | +| rustc_env | Dictionary of additional "key": "value" environment variables to set for rustc.

rust_test()/rust_binary() rules can use $(rootpath //package:target) to pass in the location of a generated file or external tool. Cargo build scripts that wish to expand locations should use cargo_build_script()'s build_script_env argument instead, as build scripts are run in a different environment - see cargo_build_script()'s documentation for more. | Dictionary: String -> String | optional | {} | +| rustc_env_files | Files containing additional environment variables to set for rustc.

These 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 (\).

The order that these files will be processed is unspecified, so multiple definitions of a particular variable are discouraged. | List of labels | optional | [] | +| rustc_flags | List of compiler flags passed to rustc. | List of strings | optional | [] | +| srcs | List of Rust .rs source files used to build the library.

If srcs contains more than one file, then there must be a file either named lib.rs. Otherwise, crate_root must be set to the source file that is the root of the crate to be passed to rustc to build this crate. | List of labels | optional | [] | +| version | A version to inject in the cargo environment variable. | String | optional | "0.0.0" | + + ## rust_proto_library @@ -725,6 +758,92 @@ See @rules_rust//proto:BUILD for examples of defining the toolchain. | protoc | The location of the protoc binary. It should be an executable target. | Label | optional | @com_google_protobuf//:protoc | + + +## rust_shared_library + +
+rust_shared_library(name, aliases, compile_data, crate_features, crate_root, data, deps, edition,
+                    out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs,
+                    version)
+
+ +Builds a Rust shared library. + +This shared library will contain all transitively reachable crates and native objects. +It is meant to be used when producing an artifact that is then consumed by some other build system +(for example to produce a shared library that Python program links against). + +This rule provides CcInfo, so it can be used everywhere Bazel expects `rules_cc`. + +When building the whole binary in Bazel, use `rust_library` instead. + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| aliases | Remap crates to a new name or moniker for linkage to this target

These are other rust_library targets and will be presented as the new name given. | Dictionary: Label -> String | optional | {} | +| compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | +| crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | +| crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | +| data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | +| deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | +| edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | +| out_dir_tar | __Deprecated__, do not use, see [#cargo_build_script] instead. | Label | optional | None | +| proc_macro_deps | List of rust_library targets with kind proc-macro used to help build this library target. | List of labels | optional | [] | +| rustc_env | Dictionary of additional "key": "value" environment variables to set for rustc.

rust_test()/rust_binary() rules can use $(rootpath //package:target) to pass in the location of a generated file or external tool. Cargo build scripts that wish to expand locations should use cargo_build_script()'s build_script_env argument instead, as build scripts are run in a different environment - see cargo_build_script()'s documentation for more. | Dictionary: String -> String | optional | {} | +| rustc_env_files | Files containing additional environment variables to set for rustc.

These 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 (\).

The order that these files will be processed is unspecified, so multiple definitions of a particular variable are discouraged. | List of labels | optional | [] | +| rustc_flags | List of compiler flags passed to rustc. | List of strings | optional | [] | +| srcs | List of Rust .rs source files used to build the library.

If srcs contains more than one file, then there must be a file either named lib.rs. Otherwise, crate_root must be set to the source file that is the root of the crate to be passed to rustc to build this crate. | List of labels | optional | [] | +| version | A version to inject in the cargo environment variable. | String | optional | "0.0.0" | + + + + +## rust_static_library + +
+rust_static_library(name, aliases, compile_data, crate_features, crate_root, data, deps, edition,
+                    out_dir_tar, proc_macro_deps, rustc_env, rustc_env_files, rustc_flags, srcs,
+                    version)
+
+ +Builds a Rust static library. + +This static library will contain all transitively reachable crates and native objects. +It is meant to be used when producing an artifact that is then consumed by some other build system +(for example to produce an archive that Python program links against). + +This rule provides CcInfo, so it can be used everywhere Bazel expects `rules_cc`. + +When building the whole binary in Bazel, use `rust_library` instead. + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| aliases | Remap crates to a new name or moniker for linkage to this target

These are other rust_library targets and will be presented as the new name given. | Dictionary: Label -> String | optional | {} | +| compile_data | List of files used by this rule at compile time.

This attribute can be used to specify any data files that are embedded into the library, such as via the [include_str!](https://doc.rust-lang.org/std/macro.include_str!.html) macro. | List of labels | optional | [] | +| crate_features | List of features to enable for this crate.

Features are defined in the code using the #[cfg(feature = "foo")] configuration option. The features listed here will be passed to rustc with --cfg feature="${feature_name}" flags. | List of strings | optional | [] | +| crate_root | The file that will be passed to rustc to be used for building this crate.

If crate_root is not set, then this rule will look for a lib.rs file (or main.rs for rust_binary) or the single file in srcs if srcs contains only one file. | Label | optional | None | +| data | List of files used by this rule at compile time and runtime.

If including data at compile time with include_str!() and similar, prefer compile_data over data, to prevent the data also being included in the runfiles. | List of labels | optional | [] | +| deps | List of other libraries to be linked to this library target.

These can be either other rust_library targets or cc_library targets if linking a native library. | List of labels | optional | [] | +| edition | The rust edition to use for this crate. Defaults to the edition specified in the rust_toolchain. | String | optional | "" | +| out_dir_tar | __Deprecated__, do not use, see [#cargo_build_script] instead. | Label | optional | None | +| proc_macro_deps | List of rust_library targets with kind proc-macro used to help build this library target. | List of labels | optional | [] | +| rustc_env | Dictionary of additional "key": "value" environment variables to set for rustc.

rust_test()/rust_binary() rules can use $(rootpath //package:target) to pass in the location of a generated file or external tool. Cargo build scripts that wish to expand locations should use cargo_build_script()'s build_script_env argument instead, as build scripts are run in a different environment - see cargo_build_script()'s documentation for more. | Dictionary: String -> String | optional | {} | +| rustc_env_files | Files containing additional environment variables to set for rustc.

These 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 (\).

The order that these files will be processed is unspecified, so multiple definitions of a particular variable are discouraged. | List of labels | optional | [] | +| rustc_flags | List of compiler flags passed to rustc. | List of strings | optional | [] | +| srcs | List of Rust .rs source files used to build the library.

If srcs contains more than one file, then there must be a file either named lib.rs. Otherwise, crate_root must be set to the source file that is the root of the crate to be passed to rustc to build this crate. | List of labels | optional | [] | +| version | A version to inject in the cargo environment variable. | String | optional | "0.0.0" | + + ## rust_test @@ -738,92 +857,92 @@ Builds a Rust test crate. Examples: -Suppose you have the following directory structure for a Rust library crate with unit test code in the library sources: +Suppose you have the following directory structure for a Rust library crate with unit test code in the library sources: ```output [workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs +WORKSPACE +hello_lib/ +BUILD +src/ +lib.rs ``` `hello_lib/src/lib.rs`: ```rust pub struct Greeter { - greeting: String, +greeting: String, } impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } +pub fn new(greeting: &str) -> Greeter { +Greeter { greeting: greeting.to_string(), } +} - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } +pub fn greet(&self, thing: &str) { +println!("{} {}", &self.greeting, thing); +} } #[cfg(test)] mod test { - use super::Greeter; +use super::Greeter; - #[test] - fn test_greeting() { - let hello = Greeter::new("Hi"); - assert_eq!("Hi Rust", hello.greet("Rust")); - } +#[test] +fn test_greeting() { +let hello = Greeter::new("Hi"); +assert_eq!("Hi Rust", hello.greet("Rust")); +} } ``` -To build and run the tests, simply add a `rust_test` rule with no `srcs` and only depends on the `hello_lib` `rust_library` target: +To build and run the tests, simply add a `rust_test` rule with no `srcs` and only depends on the `hello_lib` `rust_library` target: `hello_lib/BUILD`: ```python package(default_visibility = ["//visibility:public"]) -load("@rules_rust//rust:rust.bzl", "rust_library", "rust_test") +load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], +name = "hello_lib", +srcs = ["src/lib.rs"], ) rust_test( - name = "hello_lib_test", - deps = [":hello_lib"], +name = "hello_lib_test", +deps = [":hello_lib"], ) ``` Run the test with `bazel build //hello_lib:hello_lib_test`. -To run a crate or lib with the `#[cfg(test)]` configuration, handling inline tests, you should specify the crate directly like so. +To run a crate or lib with the `#[cfg(test)]` configuration, handling inline tests, you should specify the crate directly like so. ```python rust_test( - name = "hello_lib_test", - crate = ":hello_lib", - # You may add other deps that are specific to the test configuration - deps = ["//some/dev/dep"], +name = "hello_lib_test", +crate = ":hello_lib", +# You may add other deps that are specific to the test configuration +deps = ["//some/dev/dep"], ) ``` ### Example: `test` directory -Integration tests that live in the [`tests` directory][int-tests], they are essentially built as separate crates. Suppose you have the following directory structure where `greeting.rs` is an integration test for the `hello_lib` library crate: +Integration tests that live in the [`tests` directory][int-tests], they are essentially built as separate crates. Suppose you have the following directory structure where `greeting.rs` is an integration test for the `hello_lib` library crate: [int-tests]: http://doc.rust-lang.org/book/testing.html#the-tests-directory ```output [workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs - tests/ - greeting.rs +WORKSPACE +hello_lib/ +BUILD +src/ +lib.rs +tests/ +greeting.rs ``` `hello_lib/tests/greeting.rs`: @@ -834,8 +953,8 @@ use hello_lib; #[test] fn test_greeting() { - let hello = greeter::Greeter::new("Hello"); - assert_eq!("Hello world", hello.greeting("world")); +let hello = greeter::Greeter::new("Hello"); +assert_eq!("Hello world", hello.greeting("world")); } ``` @@ -846,23 +965,22 @@ with `greeting.rs` in `srcs` and a dependency on the `hello_lib` target: ```python package(default_visibility = ["//visibility:public"]) -load("@rules_rust//rust:rust.bzl", "rust_library", "rust_test") +load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], +name = "hello_lib", +srcs = ["src/lib.rs"], ) rust_test( - name = "greeting_test", - srcs = ["tests/greeting.rs"], - deps = [":hello_lib"], +name = "greeting_test", +srcs = ["tests/greeting.rs"], +deps = [":hello_lib"], ) ``` Run the test with `bazel build //hello_lib:hello_lib_test`. - **ATTRIBUTES** diff --git a/docs/index.md b/docs/index.md index 3c6cc26d34..00d1abdb6c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -39,7 +39,7 @@ supported in certain environments. ## Rules -- [rust](rust.md): standard rust rules for building and testing libraries and binaries. +- [defs](defs.md): standard rust rules for building and testing libraries and binaries. - [rust_doc](rust_doc.md): rules for generating and testing rust documentation. - [rust_proto](rust_proto.md): rules for generating [protobuf](https://developers.google.com/protocol-buffers). and [gRPC](https://grpc.io) stubs. diff --git a/rust/BUILD b/rust/BUILD index d38e41a8ca..d5c8d38e30 100644 --- a/rust/BUILD +++ b/rust/BUILD @@ -6,6 +6,7 @@ exports_files([ "known_shas.bzl", "repositories.bzl", "rust.bzl", + "defs.bzl", "toolchain.bzl", ]) diff --git a/rust/defs.bzl b/rust/defs.bzl new file mode 100644 index 0000000000..da664323a3 --- /dev/null +++ b/rust/defs.bzl @@ -0,0 +1,98 @@ +# Copyright 2021 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point to all Rust rules and supported APIs.""" + +load( + "//rust/private:clippy.bzl", + _rust_clippy = "rust_clippy", + _rust_clippy_aspect = "rust_clippy_aspect", +) +load("//rust/private:common.bzl", _rust_common = "rust_common") +load( + "//rust/private:rust.bzl", + _rust_benchmark = "rust_benchmark", + _rust_binary = "rust_binary", + _rust_library = "rust_library", + _rust_proc_macro = "rust_proc_macro", + _rust_shared_library = "rust_shared_library", + _rust_static_library = "rust_static_library", + _rust_test = "rust_test", + _rust_test_binary = "rust_test_binary", +) +load( + "//rust/private:rust_analyzer.bzl", + _rust_analyzer = "rust_analyzer", + _rust_analyzer_aspect = "rust_analyzer_aspect", +) +load( + "//rust/private:rustc.bzl", + _error_format = "error_format", +) +load( + "//rust/private:rustdoc.bzl", + _rust_doc = "rust_doc", +) +load( + "//rust/private:rustdoc_test.bzl", + _rust_doc_test = "rust_doc_test", +) + +rust_library = _rust_library +# See @rules_rust//rust/private:rust.bzl for a complete description. + +rust_static_library = _rust_static_library +# See @rules_rust//rust/private:rust.bzl for a complete description. + +rust_shared_library = _rust_shared_library +# See @rules_rust//rust/private:rust.bzl for a complete description. + +rust_proc_macro = _rust_proc_macro +# See @rules_rust//rust/private:rust.bzl for a complete description. + +rust_binary = _rust_binary +# See @rules_rust//rust/private:rust.bzl for a complete description. + +rust_test = _rust_test +# See @rules_rust//rust/private:rust.bzl for a complete description. + +rust_test_binary = _rust_test_binary +# See @rules_rust//rust/private:rust.bzl for a complete description. + +rust_benchmark = _rust_benchmark +# See @rules_rust//rust/private:rust.bzl for a complete description. + +rust_doc = _rust_doc +# See @rules_rust//rust/private:rustdoc.bzl for a complete description. + +rust_doc_test = _rust_doc_test +# See @rules_rust//rust/private:rustdoc_test.bzl for a complete description. + +rust_clippy_aspect = _rust_clippy_aspect +# See @rules_rust//rust/private:clippy.bzl for a complete description. + +rust_clippy = _rust_clippy +# See @rules_rust//rust/private:clippy.bzl for a complete description. + +error_format = _error_format +# See @rules_rust//rust/private:rustc.bzl for a complete description. + +rust_common = _rust_common +# See @rules_rust//rust/private:common.bzl for a complete description. + +rust_analyzer_aspect = _rust_analyzer_aspect +# See @rules_rust//rust:private/rust_analyzer.bzl for a complete description. + +rust_analyzer = _rust_analyzer +# See @rules_rust//rust:private/rust_analyzer.bzl for a complete description. diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index c9ebba6a82..17131c6b9e 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -36,7 +36,7 @@ def _determine_lib_name(name, crate_type, toolchain, lib_hash = ""): Args: name (str): The name of the current target - crate_type (str): The `crate_type` attribute from a `rust_library` + crate_type (str): The `crate_type` toolchain (rust_toolchain): The current `rust_toolchain` lib_hash (str, optional): The hashed crate root path. Defaults to "". @@ -136,11 +136,56 @@ def _shortest_src_with_basename(srcs, basename): return shortest def _rust_library_impl(ctx): - """The implementation of the `rust_library` rule + """The implementation of the `rust_library` rule. Args: ctx (ctx): The rule's context object + Returns: + list: A list of providers. + """ + return _rust_library_common(ctx, "rlib") + +def _rust_static_library_impl(ctx): + """The implementation of the `rust_static_library` rule. + + Args: + ctx (ctx): The rule's context object + + Returns: + list: A list of providers. + """ + return _rust_library_common(ctx, "staticlib") + +def _rust_shared_library_impl(ctx): + """The implementation of the `rust_shared_library` rule. + + Args: + ctx (ctx): The rule's context object + + Returns: + list: A list of providers. + """ + return _rust_library_common(ctx, "cdylib") + +def _rust_proc_macro_impl(ctx): + """The implementation of the `rust_proc_macro` rule. + + Args: + ctx (ctx): The rule's context object + + Returns: + list: A list of providers. + """ + return _rust_library_common(ctx, "proc-macro") + +def _rust_library_common(ctx, crate_type): + """The common implementation of the library-like rules. + + Args: + ctx (ctx): The rule's context object + crate_type (String): one of lib|rlib|dylib|staticlib|cdylib|proc-macro + Returns: list: A list of providers. See `rustc_compile_action` """ @@ -155,7 +200,6 @@ def _rust_library_impl(ctx): output_hash = determine_output_hash(crate_root) crate_name = name_to_crate_name(ctx.label.name) - crate_type = getattr(ctx.attr, "crate_type") rust_lib_name = _determine_lib_name( crate_name, crate_type, @@ -198,16 +242,14 @@ def _rust_binary_impl(ctx): output = ctx.actions.declare_file(ctx.label.name + toolchain.binary_ext) - crate_type = getattr(ctx.attr, "crate_type") - return rustc_compile_action( ctx = ctx, toolchain = toolchain, - crate_type = crate_type, + crate_type = "bin", crate_info = rust_common.crate_info( name = crate_name, - type = crate_type, - root = crate_root_src(ctx.attr, ctx.files.srcs, crate_type), + type = "bin", + root = crate_root_src(ctx.attr, ctx.files.srcs, crate_type = "bin"), srcs = ctx.files.srcs, deps = ctx.attr.deps, proc_macro_deps = ctx.attr.proc_macro_deps, @@ -239,6 +281,7 @@ def _create_test_launcher(ctx, toolchain, output, providers): # the execution environment is windows. if toolchain.os == "windows": launcher = ctx.actions.declare_file(name_to_crate_name(ctx.label.name + ".launcher.exe")) + # Because the windows target is a batch file, it expects native windows paths (with backslashes) args.add_all([ ctx.executable._launcher.path.replace("/", "\\"), @@ -251,8 +294,8 @@ def _create_test_launcher(ctx, toolchain, output, providers): launcher, ]) - # Because returned executables must be created from the same rule, the - # launcher target is simply copied and exposed. + # Because returned executables must be created from the same rule, the + # launcher target is simply copied and exposed. ctx.actions.run( outputs = [launcher], tools = [ctx.executable._launcher], @@ -279,7 +322,7 @@ def _create_test_launcher(ctx, toolchain, output, providers): ctx.actions.write( output = environ_file, - content = "\n".join(environ_list) + content = "\n".join(environ_list), ) launcher_files = [environ_file] @@ -587,18 +630,6 @@ _common_attrs = { ), } -_rust_library_attrs = { - "crate_type": attr.string( - doc = _tidy(""" - The type of linkage to use for building this library. - Options include `"lib"`, `"rlib"`, `"dylib"`, `"cdylib"`, `"staticlib"`, and `"proc-macro"`. - - The exact output file will depend on the toolchain used. - """), - default = "rlib", - ), -} - _rust_test_attrs = { "crate": attr.label( mandatory = False, @@ -638,84 +669,138 @@ _rust_test_attrs = { rust_library = rule( implementation = _rust_library_impl, - attrs = dict(_common_attrs.items() + - _rust_library_attrs.items()), + attrs = dict(_common_attrs.items()), fragments = ["cpp"], host_fragments = ["cpp"], toolchains = [ str(Label("//rust:toolchain")), "@bazel_tools//tools/cpp:toolchain_type", ], - doc = """\ -Builds a Rust library crate. - -Example: - -Suppose you have the following directory structure for a simple Rust library crate: - -```output -[workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - greeter.rs - lib.rs -``` - -`hello_lib/src/greeter.rs`: -```rust -pub struct Greeter { - greeting: String, -} + doc = _tidy("""\ + Builds a Rust library crate. + + Example: + + Suppose you have the following directory structure for a simple Rust library crate: + + ```output + [workspace]/ + WORKSPACE + hello_lib/ + BUILD + src/ + greeter.rs + lib.rs + ``` + + `hello_lib/src/greeter.rs`: + ```rust + pub struct Greeter { + greeting: String, + } + + impl Greeter { + pub fn new(greeting: &str) -> Greeter { + Greeter { greeting: greeting.to_string(), } + } + + pub fn greet(&self, thing: &str) { + println!("{} {}", &self.greeting, thing); + } + } + ``` + + `hello_lib/src/lib.rs`: + + ```rust + pub mod greeter; + ``` + + `hello_lib/BUILD`: + ```python + package(default_visibility = ["//visibility:public"]) + + load("@rules_rust//rust:rust.bzl", "rust_library") + + rust_library( + name = "hello_lib", + srcs = [ + "src/greeter.rs", + "src/lib.rs", + ], + ) + ``` + + Build the library: + ```output + $ bazel build //hello_lib + INFO: Found 1 target... + Target //examples/rust/hello_lib:hello_lib up-to-date: + bazel-bin/examples/rust/hello_lib/libhello_lib.rlib + INFO: Elapsed time: 1.245s, Critical Path: 1.01s + ``` + """), +) -impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } +rust_static_library = rule( + implementation = _rust_static_library_impl, + attrs = dict(_common_attrs.items()), + fragments = ["cpp"], + host_fragments = ["cpp"], + toolchains = [ + str(Label("//rust:toolchain")), + "@bazel_tools//tools/cpp:toolchain_type", + ], + doc = _tidy("""\ + Builds a Rust static library. - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } -} -``` + This static library will contain all transitively reachable crates and native objects. + It is meant to be used when producing an artifact that is then consumed by some other build system + (for example to produce an archive that Python program links against). -`hello_lib/src/lib.rs`: + This rule provides CcInfo, so it can be used everywhere Bazel expects `rules_cc`. -```rust -pub mod greeter; -``` + When building the whole binary in Bazel, use `rust_library` instead. + """), +) -`hello_lib/BUILD`: -```python -package(default_visibility = ["//visibility:public"]) +rust_shared_library = rule( + implementation = _rust_shared_library_impl, + attrs = dict(_common_attrs.items()), + fragments = ["cpp"], + host_fragments = ["cpp"], + toolchains = [ + str(Label("//rust:toolchain")), + "@bazel_tools//tools/cpp:toolchain_type", + ], + doc = _tidy("""\ + Builds a Rust shared library. -load("@rules_rust//rust:rust.bzl", "rust_library") + This shared library will contain all transitively reachable crates and native objects. + It is meant to be used when producing an artifact that is then consumed by some other build system + (for example to produce a shared library that Python program links against). -rust_library( - name = "hello_lib", - srcs = [ - "src/greeter.rs", - "src/lib.rs", - ], + This rule provides CcInfo, so it can be used everywhere Bazel expects `rules_cc`. + + When building the whole binary in Bazel, use `rust_library` instead. + """), ) -``` - -Build the library: -```output -$ bazel build //hello_lib -INFO: Found 1 target... -Target //examples/rust/hello_lib:hello_lib up-to-date: - bazel-bin/examples/rust/hello_lib/libhello_lib.rlib -INFO: Elapsed time: 1.245s, Critical Path: 1.01s -``` -""", + +rust_proc_macro = rule( + implementation = _rust_proc_macro_impl, + attrs = dict(_common_attrs.items()), + fragments = ["cpp"], + host_fragments = ["cpp"], + toolchains = [ + str(Label("//rust:toolchain")), + "@bazel_tools//tools/cpp:toolchain_type", + ], + doc = _tidy("""\ + Builds a Rust proc-macro crate. + """), ) _rust_binary_attrs = { - "crate_type": attr.string( - default = "bin", - ), "linker_script": attr.label( doc = _tidy(""" Link script to forward into linker via rustc options. @@ -736,90 +821,90 @@ rust_binary = rule( str(Label("//rust:toolchain")), "@bazel_tools//tools/cpp:toolchain_type", ], - doc = """\ -Builds a Rust binary crate. - -Example: - -Suppose you have the following directory structure for a Rust project with a -library crate, `hello_lib`, and a binary crate, `hello_world` that uses the -`hello_lib` library: - -```output -[workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs - hello_world/ - BUILD - src/ - main.rs -``` - -`hello_lib/src/lib.rs`: -```rust -pub struct Greeter { - greeting: String, -} - -impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } - - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } -} -``` - -`hello_lib/BUILD`: -```python -package(default_visibility = ["//visibility:public"]) - -load("@rules_rust//rust:rust.bzl", "rust_library") - -rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], -) -``` - -`hello_world/src/main.rs`: -```rust -extern crate hello_lib; - -fn main() { - let hello = hello_lib::Greeter::new("Hello"); - hello.greet("world"); -} -``` - -`hello_world/BUILD`: -```python -load("@rules_rust//rust:rust.bzl", "rust_binary") - -rust_binary( - name = "hello_world", - srcs = ["src/main.rs"], - deps = ["//hello_lib"], -) -``` - -Build and run `hello_world`: -``` -$ bazel run //hello_world -INFO: Found 1 target... -Target //examples/rust/hello_world:hello_world up-to-date: - bazel-bin/examples/rust/hello_world/hello_world -INFO: Elapsed time: 1.308s, Critical Path: 1.22s - -INFO: Running command line: bazel-bin/examples/rust/hello_world/hello_world -Hello world -``` -""", + doc = _tidy("""\ + Builds a Rust binary crate. + + Example: + + Suppose you have the following directory structure for a Rust project with a + library crate, `hello_lib`, and a binary crate, `hello_world` that uses the + `hello_lib` library: + + ```output + [workspace]/ + WORKSPACE + hello_lib/ + BUILD + src/ + lib.rs + hello_world/ + BUILD + src/ + main.rs + ``` + + `hello_lib/src/lib.rs`: + ```rust + pub struct Greeter { + greeting: String, + } + + impl Greeter { + pub fn new(greeting: &str) -> Greeter { + Greeter { greeting: greeting.to_string(), } + } + + pub fn greet(&self, thing: &str) { + println!("{} {}", &self.greeting, thing); + } + } + ``` + + `hello_lib/BUILD`: + ```python + package(default_visibility = ["//visibility:public"]) + + load("@rules_rust//rust:rust.bzl", "rust_library") + + rust_library( + name = "hello_lib", + srcs = ["src/lib.rs"], + ) + ``` + + `hello_world/src/main.rs`: + ```rust + extern crate hello_lib; + + fn main() { + let hello = hello_lib::Greeter::new("Hello"); + hello.greet("world"); + } + ``` + + `hello_world/BUILD`: + ```python + load("@rules_rust//rust:rust.bzl", "rust_binary") + + rust_binary( + name = "hello_world", + srcs = ["src/main.rs"], + deps = ["//hello_lib"], + ) + ``` + + Build and run `hello_world`: + ``` + $ bazel run //hello_world + INFO: Found 1 target... + Target //examples/rust/hello_world:hello_world up-to-date: + bazel-bin/examples/rust/hello_world/hello_world + INFO: Elapsed time: 1.308s, Critical Path: 1.22s + + INFO: Running command line: bazel-bin/examples/rust/hello_world/hello_world + Hello world + ``` +"""), ) rust_test = rule( @@ -834,141 +919,141 @@ rust_test = rule( str(Label("//rust:toolchain")), "@bazel_tools//tools/cpp:toolchain_type", ], - doc = """\ -Builds a Rust test crate. - -Examples: - -Suppose you have the following directory structure for a Rust library crate \ -with unit test code in the library sources: - -```output -[workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs -``` - -`hello_lib/src/lib.rs`: -```rust -pub struct Greeter { - greeting: String, -} - -impl Greeter { - pub fn new(greeting: &str) -> Greeter { - Greeter { greeting: greeting.to_string(), } - } + doc = _tidy("""\ + Builds a Rust test crate. + + Examples: + + Suppose you have the following directory structure for a Rust library crate \ + with unit test code in the library sources: + + ```output + [workspace]/ + WORKSPACE + hello_lib/ + BUILD + src/ + lib.rs + ``` + + `hello_lib/src/lib.rs`: + ```rust + pub struct Greeter { + greeting: String, + } + + impl Greeter { + pub fn new(greeting: &str) -> Greeter { + Greeter { greeting: greeting.to_string(), } + } + + pub fn greet(&self, thing: &str) { + println!("{} {}", &self.greeting, thing); + } + } + + #[cfg(test)] + mod test { + use super::Greeter; + + #[test] + fn test_greeting() { + let hello = Greeter::new("Hi"); + assert_eq!("Hi Rust", hello.greet("Rust")); + } + } + ``` + + To build and run the tests, simply add a `rust_test` rule with no `srcs` and \ + only depends on the `hello_lib` `rust_library` target: + + `hello_lib/BUILD`: + ```python + package(default_visibility = ["//visibility:public"]) + + load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") + + rust_library( + name = "hello_lib", + srcs = ["src/lib.rs"], + ) - pub fn greet(&self, thing: &str) { - println!("{} {}", &self.greeting, thing); - } -} + rust_test( + name = "hello_lib_test", + deps = [":hello_lib"], + ) + ``` -#[cfg(test)] -mod test { - use super::Greeter; + Run the test with `bazel build //hello_lib:hello_lib_test`. - #[test] - fn test_greeting() { - let hello = Greeter::new("Hi"); - assert_eq!("Hi Rust", hello.greet("Rust")); - } -} -``` + To run a crate or lib with the `#[cfg(test)]` configuration, handling inline \ + tests, you should specify the crate directly like so. -To build and run the tests, simply add a `rust_test` rule with no `srcs` and \ -only depends on the `hello_lib` `rust_library` target: + ```python + rust_test( + name = "hello_lib_test", + crate = ":hello_lib", + # You may add other deps that are specific to the test configuration + deps = ["//some/dev/dep"], + ) + ``` -`hello_lib/BUILD`: -```python -package(default_visibility = ["//visibility:public"]) + ### Example: `test` directory -load("@rules_rust//rust:rust.bzl", "rust_library", "rust_test") + Integration tests that live in the [`tests` directory][int-tests], they are \ + essentially built as separate crates. Suppose you have the following directory \ + structure where `greeting.rs` is an integration test for the `hello_lib` \ + library crate: -rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], -) + [int-tests]: http://doc.rust-lang.org/book/testing.html#the-tests-directory -rust_test( - name = "hello_lib_test", - deps = [":hello_lib"], -) -``` + ```output + [workspace]/ + WORKSPACE + hello_lib/ + BUILD + src/ + lib.rs + tests/ + greeting.rs + ``` -Run the test with `bazel build //hello_lib:hello_lib_test`. + `hello_lib/tests/greeting.rs`: + ```rust + extern crate hello_lib; -To run a crate or lib with the `#[cfg(test)]` configuration, handling inline \ -tests, you should specify the crate directly like so. + use hello_lib; -```python -rust_test( - name = "hello_lib_test", - crate = ":hello_lib", - # You may add other deps that are specific to the test configuration - deps = ["//some/dev/dep"], -) -``` - -### Example: `test` directory - -Integration tests that live in the [`tests` directory][int-tests], they are \ -essentially built as separate crates. Suppose you have the following directory \ -structure where `greeting.rs` is an integration test for the `hello_lib` \ -library crate: - -[int-tests]: http://doc.rust-lang.org/book/testing.html#the-tests-directory - -```output -[workspace]/ - WORKSPACE - hello_lib/ - BUILD - src/ - lib.rs - tests/ - greeting.rs -``` - -`hello_lib/tests/greeting.rs`: -```rust -extern crate hello_lib; - -use hello_lib; - -#[test] -fn test_greeting() { - let hello = greeter::Greeter::new("Hello"); - assert_eq!("Hello world", hello.greeting("world")); -} -``` + #[test] + fn test_greeting() { + let hello = greeter::Greeter::new("Hello"); + assert_eq!("Hello world", hello.greeting("world")); + } + ``` -To build the `greeting.rs` integration test, simply add a `rust_test` target -with `greeting.rs` in `srcs` and a dependency on the `hello_lib` target: + To build the `greeting.rs` integration test, simply add a `rust_test` target + with `greeting.rs` in `srcs` and a dependency on the `hello_lib` target: -`hello_lib/BUILD`: -```python -package(default_visibility = ["//visibility:public"]) + `hello_lib/BUILD`: + ```python + package(default_visibility = ["//visibility:public"]) -load("@rules_rust//rust:rust.bzl", "rust_library", "rust_test") + load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") -rust_library( - name = "hello_lib", - srcs = ["src/lib.rs"], -) + rust_library( + name = "hello_lib", + srcs = ["src/lib.rs"], + ) -rust_test( - name = "greeting_test", - srcs = ["tests/greeting.rs"], - deps = [":hello_lib"], -) -``` + rust_test( + name = "greeting_test", + srcs = ["tests/greeting.rs"], + deps = [":hello_lib"], + ) + ``` -Run the test with `bazel build //hello_lib:hello_lib_test`. -""", + Run the test with `bazel build //hello_lib:hello_lib_test`. +"""), ) rust_test_binary = rule( @@ -982,17 +1067,17 @@ rust_test_binary = rule( str(Label("//rust:toolchain")), "@bazel_tools//tools/cpp:toolchain_type", ], - doc = """\ -Builds a Rust test binary, without marking this rule as a Bazel test. + doc = _tidy("""\ + Builds a Rust test binary, without marking this rule as a Bazel test. -**Warning**: This rule is currently experimental. + **Warning**: This rule is currently experimental. -This should be used when you want to run the test binary from a different test -rule (such as [`sh_test`](https://docs.bazel.build/versions/master/be/shell.html#sh_test)), -and know that running the test binary directly will fail. + This should be used when you want to run the test binary from a different test + rule (such as [`sh_test`](https://docs.bazel.build/versions/master/be/shell.html#sh_test)), + and know that running the test binary directly will fail. -See `rust_test` for example usage. -""", + See `rust_test` for example usage. + """), ) rust_benchmark = rule( @@ -1005,86 +1090,86 @@ rust_benchmark = rule( str(Label("//rust:toolchain")), "@bazel_tools//tools/cpp:toolchain_type", ], - doc = """\ -Builds a Rust benchmark test. - -**Warning**: This rule is currently experimental. [Rust Benchmark tests][rust-bench] \ -require the `Bencher` interface in the unstable `libtest` crate, which is behind the \ -`test` unstable feature gate. As a result, using this rule would require using a nightly \ -binary release of Rust. - -[rust-bench]: https://doc.rust-lang.org/book/benchmark-tests.html - -Example: - -Suppose you have the following directory structure for a Rust project with a \ -library crate, `fibonacci` with benchmarks under the `benches/` directory: - -```output -[workspace]/ - WORKSPACE - fibonacci/ - BUILD - src/ - lib.rs - benches/ - fibonacci_bench.rs -``` - -`fibonacci/src/lib.rs`: -```rust -pub fn fibonacci(n: u64) -> u64 { - if n < 2 { - return n; - } - let mut n1: u64 = 0; - let mut n2: u64 = 1; - for _ in 1..n { - let sum = n1 + n2; - n1 = n2; - n2 = sum; - } - n2 -} -``` - -`fibonacci/benches/fibonacci_bench.rs`: -```rust -#![feature(test)] - -extern crate test; -extern crate fibonacci; - -use test::Bencher; - -#[bench] -fn bench_fibonacci(b: &mut Bencher) { - b.iter(|| fibonacci::fibonacci(40)); -} -``` - -To build the benchmark test, add a `rust_benchmark` target: - -`fibonacci/BUILD`: -```python -package(default_visibility = ["//visibility:public"]) - -load("@rules_rust//rust:rust.bzl", "rust_library", "rust_benchmark") - -rust_library( - name = "fibonacci", - srcs = ["src/lib.rs"], -) + doc = _tidy("""\ + Builds a Rust benchmark test. + + **Warning**: This rule is currently experimental. [Rust Benchmark tests][rust-bench] \ + require the `Bencher` interface in the unstable `libtest` crate, which is behind the \ + `test` unstable feature gate. As a result, using this rule would require using a nightly \ + binary release of Rust. + + [rust-bench]: https://doc.rust-lang.org/book/benchmark-tests.html + + Example: + + Suppose you have the following directory structure for a Rust project with a \ + library crate, `fibonacci` with benchmarks under the `benches/` directory: + + ```output + [workspace]/ + WORKSPACE + fibonacci/ + BUILD + src/ + lib.rs + benches/ + fibonacci_bench.rs + ``` + + `fibonacci/src/lib.rs`: + ```rust + pub fn fibonacci(n: u64) -> u64 { + if n < 2 { + return n; + } + let mut n1: u64 = 0; + let mut n2: u64 = 1; + for _ in 1..n { + let sum = n1 + n2; + n1 = n2; + n2 = sum; + } + n2 + } + ``` + + `fibonacci/benches/fibonacci_bench.rs`: + ```rust + #![feature(test)] + + extern crate test; + extern crate fibonacci; + + use test::Bencher; + + #[bench] + fn bench_fibonacci(b: &mut Bencher) { + b.iter(|| fibonacci::fibonacci(40)); + } + ``` + + To build the benchmark test, add a `rust_benchmark` target: + + `fibonacci/BUILD`: + ```python + package(default_visibility = ["//visibility:public"]) + + load("@rules_rust//rust:defs.bzl", "rust_library", "rust_benchmark") + + rust_library( + name = "fibonacci", + srcs = ["src/lib.rs"], + ) -rust_benchmark( - name = "fibonacci_bench", - srcs = ["benches/fibonacci_bench.rs"], - deps = [":fibonacci"], -) -``` + rust_benchmark( + name = "fibonacci_bench", + srcs = ["benches/fibonacci_bench.rs"], + deps = [":fibonacci"], + ) + ``` -Run the benchmark test using: `bazel run //fibonacci:fibonacci_bench`. -""", + Run the benchmark test using: `bazel run //fibonacci:fibonacci_bench`. + """), ) def name_to_crate_name(name): diff --git a/rust/rust.bzl b/rust/rust.bzl index 1562635820..6da41269ba 100644 --- a/rust/rust.bzl +++ b/rust/rust.bzl @@ -12,42 +12,51 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Public entry point to all Rust rules and supported APIs.""" +"""Deprecated, please use //rust:defs.bzl.""" load( - "//rust/private:clippy.bzl", - _rust_clippy = "rust_clippy", - _rust_clippy_aspect = "rust_clippy_aspect", -) -load("//rust/private:common.bzl", _rust_common = "rust_common") -load( - "//rust/private:rust.bzl", + "//rust:defs.bzl", + _error_format = "error_format", _rust_benchmark = "rust_benchmark", _rust_binary = "rust_binary", + _rust_clippy = "rust_clippy", + _rust_clippy_aspect = "rust_clippy_aspect", + _rust_common = "rust_common", + _rust_doc = "rust_doc", + _rust_doc_test = "rust_doc_test", _rust_library = "rust_library", + _rust_proc_macro = "rust_proc_macro", + _rust_shared_library = "rust_shared_library", + _rust_static_library = "rust_static_library", _rust_test = "rust_test", _rust_test_binary = "rust_test_binary", -) -load( - "//rust/private:rust_analyzer.bzl", _rust_analyzer = "rust_analyzer", _rust_analyzer_aspect = "rust_analyzer_aspect", ) -load( - "//rust/private:rustc.bzl", - _error_format = "error_format", -) -load( - "//rust/private:rustdoc.bzl", - _rust_doc = "rust_doc", -) -load( - "//rust/private:rustdoc_test.bzl", - _rust_doc_test = "rust_doc_test", -) -rust_library = _rust_library -# See @rules_rust//rust/private:rust.bzl for a complete description. +def rust_library(**args): + """Deprecated. Use the version from "@rules_rust//rust:defs.bzl" instead. + + Args: + **args: args to pass to the relevant rule. + + Returns: + a target. + """ + if "crate_type" in args: + crate_type = args.pop("crate_type") + if crate_type in ["lib", "rlib", "dylib"]: + return _rust_library(**args) + elif crate_type == "cdylib": + return _rust_shared_library(**args) + elif crate_type == "staticlib": + return _rust_static_library(**args) + elif crate_type == "proc-macro": + return _rust_proc_macro(**args) + else: + fail("Unexpected crate_type: " + crate_type) + else: + return _rust_library(**args) rust_binary = _rust_binary # See @rules_rust//rust/private:rust.bzl for a complete description. diff --git a/test/unit/native_deps/native_deps_test.bzl b/test/unit/native_deps/native_deps_test.bzl index 8bf318f9a3..326974dce0 100644 --- a/test/unit/native_deps/native_deps_test.bzl +++ b/test/unit/native_deps/native_deps_test.bzl @@ -2,9 +2,7 @@ load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("@rules_cc//cc:defs.bzl", "cc_library") - -# buildifier: disable=bzl-visibility -load("//rust/private:rust.bzl", "rust_binary", "rust_library") +load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_proc_macro", "rust_shared_library", "rust_static_library") def _assert_argv_contains_not(env, action, flag): asserts.true( @@ -81,55 +79,35 @@ def _bin_has_native_libs_test_impl(ctx): _assert_argv_contains(env, action, "-lstatic=native_dep") return analysistest.end(env) -lib_has_no_native_libs_test = analysistest.make(_lib_has_no_native_libs_test_impl) rlib_has_no_native_libs_test = analysistest.make(_rlib_has_no_native_libs_test_impl) staticlib_has_native_libs_test = analysistest.make(_staticlib_has_native_libs_test_impl) -dylib_has_native_libs_test = analysistest.make(_dylib_has_native_libs_test_impl) cdylib_has_native_libs_test = analysistest.make(_cdylib_has_native_libs_test_impl) proc_macro_has_native_libs_test = analysistest.make(_proc_macro_has_native_libs_test_impl) bin_has_native_libs_test = analysistest.make(_bin_has_native_libs_test_impl) def _native_dep_test(): - rust_library( - name = "lib_has_no_native_dep", - srcs = ["lib_using_native_dep.rs"], - deps = [":native_dep"], - crate_type = "lib", - ) - rust_library( name = "rlib_has_no_native_dep", srcs = ["lib_using_native_dep.rs"], deps = [":native_dep"], - crate_type = "rlib", ) - rust_library( + rust_static_library( name = "staticlib_has_native_dep", srcs = ["lib_using_native_dep.rs"], deps = [":native_dep"], - crate_type = "staticlib", - ) - - rust_library( - name = "dylib_has_native_dep", - srcs = ["lib_using_native_dep.rs"], - deps = [":native_dep"], - crate_type = "dylib", ) - rust_library( + rust_shared_library( name = "cdylib_has_native_dep", srcs = ["lib_using_native_dep.rs"], deps = [":native_dep"], - crate_type = "cdylib", ) - rust_library( + rust_proc_macro( name = "proc_macro_has_native_dep", srcs = ["proc_macro_using_native_dep.rs"], deps = [":native_dep"], - crate_type = "proc-macro", edition = "2018", ) @@ -144,10 +122,6 @@ def _native_dep_test(): srcs = ["native_dep.cc"], ) - lib_has_no_native_libs_test( - name = "lib_has_no_native_libs_test", - target_under_test = ":lib_has_no_native_dep", - ) rlib_has_no_native_libs_test( name = "rlib_has_no_native_libs_test", target_under_test = ":rlib_has_no_native_dep", @@ -156,10 +130,6 @@ def _native_dep_test(): name = "staticlib_has_native_libs_test", target_under_test = ":staticlib_has_native_dep", ) - dylib_has_native_libs_test( - name = "dylib_has_native_libs_test", - target_under_test = ":dylib_has_native_dep", - ) cdylib_has_native_libs_test( name = "cdylib_has_native_libs_test", target_under_test = ":cdylib_has_native_dep", @@ -184,10 +154,8 @@ def native_deps_test_suite(name): native.test_suite( name = name, tests = [ - ":lib_has_no_native_libs_test", ":rlib_has_no_native_libs_test", ":staticlib_has_native_libs_test", - ":dylib_has_native_libs_test", ":cdylib_has_native_libs_test", ":proc_macro_has_native_libs_test", ":bin_has_native_libs_test",