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",