From 77d099b1dd6ad7287ef126dc5413d009cf336e9e Mon Sep 17 00:00:00 2001 From: Roman Kashitsyn Date: Fri, 22 Apr 2022 13:41:45 +0200 Subject: [PATCH 1/5] feat: support extra deps in rust_doc_test Currently, `rust_doc_test` (unlike `rust_test`) doesn't support adding extra test-only dependencies, which makes it unnecessarily hard to migrate doc tests from Cargo to rules_rust. This change extends the `rust_doc_test` rust to support extra test-only dependencies. --- examples/hello_lib/BUILD.bazel | 8 +++++++ examples/hello_lib/src/frobnicate.rs | 19 ++++++++++++++++ examples/hello_lib/src/greeter.rs | 11 ++++++++++ rust/private/rustdoc_test.bzl | 33 ++++++++++++++++++++++++---- 4 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 examples/hello_lib/src/frobnicate.rs diff --git a/examples/hello_lib/BUILD.bazel b/examples/hello_lib/BUILD.bazel index e8fb6f6023..bf80280a5c 100644 --- a/examples/hello_lib/BUILD.bazel +++ b/examples/hello_lib/BUILD.bazel @@ -28,6 +28,13 @@ rust_static_library( ], ) +# A helper library used only in doc tests. +# We use it to check that the doc tests can use test-only dependencies. +rust_library( + name = "frobnicate", + srcs = ["src/frobnicate.rs"], +) + # Regression test for #368: static lib with dependencies fail. rust_static_library( name = "hello_test_staticlib", @@ -65,6 +72,7 @@ rust_doc( rust_doc_test( name = "hello_lib_doc_test", crate = ":hello_lib", + deps = [":frobnicate"], ) rust_analyzer( diff --git a/examples/hello_lib/src/frobnicate.rs b/examples/hello_lib/src/frobnicate.rs new file mode 100644 index 0000000000..af753ac58c --- /dev/null +++ b/examples/hello_lib/src/frobnicate.rs @@ -0,0 +1,19 @@ +// Copyright 2022 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. + +/// Properly frobnicates the input. +pub fn frobnicate(mut bytes: Vec) -> Vec { + bytes.reverse(); + bytes +} diff --git a/examples/hello_lib/src/greeter.rs b/examples/hello_lib/src/greeter.rs index 4a9041546e..f6cba79e9f 100644 --- a/examples/hello_lib/src/greeter.rs +++ b/examples/hello_lib/src/greeter.rs @@ -13,6 +13,17 @@ // limitations under the License. /// Object that displays a greeting. +/// +/// # Examples +/// +/// ``` +/// use hello_lib::greeter::Greeter; +/// use frobnicate::frobnicate; +/// +/// let greeter = Greeter::new("Some men interpret"); +/// let greeting = greeter.greeting("nine memos"); +/// assert_eq!(frobnicate(greeting.into_bytes()).as_slice(), b"somem enin terpretni nem emoS"); +/// ``` pub struct Greeter { greeting: String, } diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 148e8eab06..d784a30c27 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -16,7 +16,7 @@ load("//rust/private:common.bzl", "rust_common") load("//rust/private:rustdoc.bzl", "rustdoc_compile_action") -load("//rust/private:utils.bzl", "dedent", "find_toolchain") +load("//rust/private:utils.bzl", "dedent", "find_toolchain", "transform_deps") def _construct_writer_arguments(ctx, test_runner, action, crate_info): """Construct arguments and environment variables specific to `rustdoc_test_writer`. @@ -90,8 +90,25 @@ def _rust_doc_test_impl(ctx): toolchain = find_toolchain(ctx) - crate = ctx.attr.crate - crate_info = crate[rust_common.crate_info] + crate = ctx.attr.crate[rust_common.crate_info] + deps = transform_deps(ctx.attr.deps) + + crate_info = rust_common.create_crate_info( + name = crate.name, + type = crate.type, + root = crate.root, + srcs = crate.srcs, + deps = depset(deps, transitive = [crate.deps]), + proc_macro_deps = crate.proc_macro_deps, + aliases = {}, + output = crate.output, + edition = crate.edition, + rustc_env = crate.rustc_env, + is_test = True, + compile_data = crate.compile_data, + wrapped_crate_type = crate.type, + owner = ctx.label, + ) if toolchain.os == "windows": test_runner = ctx.actions.declare_file(ctx.label.name + ".rustdoc_test.bat") @@ -127,7 +144,7 @@ def _rust_doc_test_impl(ctx): ctx.actions.run( mnemonic = "RustdocTestWriter", - progress_message = "Generating Rustdoc test runner for {}".format(crate.label), + progress_message = "Generating Rustdoc test runner for {}".format(ctx.attr.crate.label), executable = ctx.executable._test_writer, inputs = action.inputs, tools = tools, @@ -163,6 +180,14 @@ rust_doc_test = rule( """), default = False, ), + "deps": attr.label_list( + doc = dedent("""\ + 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. + """), + ), "_cc_toolchain": attr.label( doc = ( "In order to use find_cc_toolchain, your rule has to depend " + From ce391ee9c681fd98711bf9098600fbd4b7155eed Mon Sep 17 00:00:00 2001 From: Roman Kashitsyn Date: Fri, 22 Apr 2022 13:58:07 +0200 Subject: [PATCH 2/5] sort dictionary items I'm getting unnecessarily proficient in this. --- rust/private/rustdoc_test.bzl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index d784a30c27..a94f3b8e78 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -171,6 +171,14 @@ rust_doc_test = rule( providers = [rust_common.crate_info], mandatory = True, ), + "deps": attr.label_list( + doc = dedent("""\ + 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. + """), + ), "experimental_use_whole_archive_for_native_deps": attr.bool( doc = dedent("""\ Whether to use +whole-archive linking modifier for native dependencies. @@ -180,14 +188,6 @@ rust_doc_test = rule( """), default = False, ), - "deps": attr.label_list( - doc = dedent("""\ - 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. - """), - ), "_cc_toolchain": attr.label( doc = ( "In order to use find_cc_toolchain, your rule has to depend " + From dec96670aa2f92d8d7e8779f783064364b7f7b16 Mon Sep 17 00:00:00 2001 From: Roman Kashitsyn Date: Fri, 22 Apr 2022 14:54:26 +0200 Subject: [PATCH 3/5] Regenerate documentation --- docs/flatten.md | 3 ++- docs/rust_doc.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/flatten.md b/docs/flatten.md index 2edd97d931..e92d2509a2 100644 --- a/docs/flatten.md +++ b/docs/flatten.md @@ -465,7 +465,7 @@ Running `bazel build //hello_lib:hello_lib_doc` will build a zip file containing ## rust_doc_test
-rust_doc_test(name, crate, experimental_use_whole_archive_for_native_deps)
+rust_doc_test(name, crate, deps, experimental_use_whole_archive_for_native_deps)
 
Runs Rust documentation tests. @@ -513,6 +513,7 @@ Running `bazel test //hello_lib:hello_lib_doc_test` will run all documentation t | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | crate | The label of the target to generate code documentation for. rust_doc_test can generate HTML code documentation for the source files of rust_library or rust_binary targets. | Label | required | | +| 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 | [] | | experimental_use_whole_archive_for_native_deps | Whether to use +whole-archive linking modifier for native dependencies.

TODO: This is a stopgap feature and will be removed, see https://github.com/bazelbuild/rules_rust/issues/1268. | Boolean | optional | False | diff --git a/docs/rust_doc.md b/docs/rust_doc.md index b8b5e71a9a..c43d6b69ae 100644 --- a/docs/rust_doc.md +++ b/docs/rust_doc.md @@ -69,7 +69,7 @@ Running `bazel build //hello_lib:hello_lib_doc` will build a zip file containing ## rust_doc_test
-rust_doc_test(name, crate, experimental_use_whole_archive_for_native_deps)
+rust_doc_test(name, crate, deps, experimental_use_whole_archive_for_native_deps)
 
Runs Rust documentation tests. @@ -117,6 +117,7 @@ Running `bazel test //hello_lib:hello_lib_doc_test` will run all documentation t | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | crate | The label of the target to generate code documentation for. rust_doc_test can generate HTML code documentation for the source files of rust_library or rust_binary targets. | Label | required | | +| 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 | [] | | experimental_use_whole_archive_for_native_deps | Whether to use +whole-archive linking modifier for native dependencies.

TODO: This is a stopgap feature and will be removed, see https://github.com/bazelbuild/rules_rust/issues/1268. | Boolean | optional | False | From 49767bb97ce902cae005c3fd94404d35dbc254c0 Mon Sep 17 00:00:00 2001 From: Roman Kashitsyn Date: Fri, 22 Apr 2022 23:15:24 +0200 Subject: [PATCH 4/5] apply review feedback --- examples/hello_lib/BUILD.bazel | 8 -------- examples/hello_lib/src/greeter.rs | 11 ----------- rust/private/rustdoc_test.bzl | 2 ++ .../src/frobnicate.rs => test/unit/rustdoc/adder.rs | 7 +++---- test/unit/rustdoc/rustdoc_lib.rs | 5 +++++ test/unit/rustdoc/rustdoc_unit_test.bzl | 8 +++++++- 6 files changed, 17 insertions(+), 24 deletions(-) rename examples/hello_lib/src/frobnicate.rs => test/unit/rustdoc/adder.rs (83%) diff --git a/examples/hello_lib/BUILD.bazel b/examples/hello_lib/BUILD.bazel index bf80280a5c..e8fb6f6023 100644 --- a/examples/hello_lib/BUILD.bazel +++ b/examples/hello_lib/BUILD.bazel @@ -28,13 +28,6 @@ rust_static_library( ], ) -# A helper library used only in doc tests. -# We use it to check that the doc tests can use test-only dependencies. -rust_library( - name = "frobnicate", - srcs = ["src/frobnicate.rs"], -) - # Regression test for #368: static lib with dependencies fail. rust_static_library( name = "hello_test_staticlib", @@ -72,7 +65,6 @@ rust_doc( rust_doc_test( name = "hello_lib_doc_test", crate = ":hello_lib", - deps = [":frobnicate"], ) rust_analyzer( diff --git a/examples/hello_lib/src/greeter.rs b/examples/hello_lib/src/greeter.rs index f6cba79e9f..4a9041546e 100644 --- a/examples/hello_lib/src/greeter.rs +++ b/examples/hello_lib/src/greeter.rs @@ -13,17 +13,6 @@ // limitations under the License. /// Object that displays a greeting. -/// -/// # Examples -/// -/// ``` -/// use hello_lib::greeter::Greeter; -/// use frobnicate::frobnicate; -/// -/// let greeter = Greeter::new("Some men interpret"); -/// let greeting = greeter.greeting("nine memos"); -/// assert_eq!(frobnicate(greeting.into_bytes()).as_slice(), b"somem enin terpretni nem emoS"); -/// ``` pub struct Greeter { greeting: String, } diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index a94f3b8e78..5ec8ab0181 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -17,6 +17,7 @@ load("//rust/private:common.bzl", "rust_common") load("//rust/private:rustdoc.bzl", "rustdoc_compile_action") load("//rust/private:utils.bzl", "dedent", "find_toolchain", "transform_deps") +load("//rust/private:providers.bzl", "CrateInfo") def _construct_writer_arguments(ctx, test_runner, action, crate_info): """Construct arguments and environment variables specific to `rustdoc_test_writer`. @@ -178,6 +179,7 @@ rust_doc_test = rule( These can be either other `rust_library` targets or `cc_library` targets if linking a native library. """), + providers = [CrateInfo, CcInfo], ), "experimental_use_whole_archive_for_native_deps": attr.bool( doc = dedent("""\ diff --git a/examples/hello_lib/src/frobnicate.rs b/test/unit/rustdoc/adder.rs similarity index 83% rename from examples/hello_lib/src/frobnicate.rs rename to test/unit/rustdoc/adder.rs index af753ac58c..7211f1a094 100644 --- a/examples/hello_lib/src/frobnicate.rs +++ b/test/unit/rustdoc/adder.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// Properly frobnicates the input. -pub fn frobnicate(mut bytes: Vec) -> Vec { - bytes.reverse(); - bytes +/// Increments the input. +pub fn inc(n: u32) -> u32 { + n + 1 } diff --git a/test/unit/rustdoc/rustdoc_lib.rs b/test/unit/rustdoc/rustdoc_lib.rs index f7b46525d9..6ab32347ba 100644 --- a/test/unit/rustdoc/rustdoc_lib.rs +++ b/test/unit/rustdoc/rustdoc_lib.rs @@ -9,6 +9,11 @@ make_answer!(); /// fn answer() -> u32 { 42 } /// assert_eq!(answer(), 42); /// ``` +/// +/// ``` +/// use adder::inc; +/// assert_eq!(inc(41), 42); +/// ``` #[cfg(not(feature = "with_proc_macro"))] pub fn answer() -> u32 { 42 diff --git a/test/unit/rustdoc/rustdoc_unit_test.bzl b/test/unit/rustdoc/rustdoc_unit_test.bzl index 6d7a6edb37..874a16bd17 100644 --- a/test/unit/rustdoc/rustdoc_unit_test.bzl +++ b/test/unit/rustdoc/rustdoc_unit_test.bzl @@ -74,7 +74,7 @@ rustdoc_for_lib_with_proc_macro_test = analysistest.make(_rustdoc_for_lib_with_p rustdoc_for_bin_with_transitive_proc_macro_test = analysistest.make(_rustdoc_for_bin_with_transitive_proc_macro_test_impl) rustdoc_for_lib_with_cc_lib_test = analysistest.make(_rustdoc_for_lib_with_cc_lib_test_impl) -def _target_maker(rule_fn, name, **kwargs): +def _target_maker(rule_fn, name, rustdoc_deps = [], **kwargs): rule_fn( name = name, **kwargs @@ -93,9 +93,12 @@ def _target_maker(rule_fn, name, **kwargs): rust_doc_test( name = "{}_doctest".format(name), crate = ":{}".format(name), + deps = rustdoc_deps, ) def _define_targets(): + rust_library(name = "adder", srcs = ["adder.rs"]) + _target_maker( rust_binary, name = "bin", @@ -106,6 +109,7 @@ def _define_targets(): rust_library, name = "lib", srcs = ["rustdoc_lib.rs"], + rustdoc_deps = [":adder"], ) _target_maker( @@ -119,6 +123,7 @@ def _define_targets(): rust_library, name = "lib_with_proc_macro", srcs = ["rustdoc_lib.rs"], + rustdoc_deps = [":adder"], proc_macro_deps = [":rustdoc_proc_macro"], crate_features = ["with_proc_macro"], ) @@ -142,6 +147,7 @@ def _define_targets(): rust_library, name = "lib_with_cc", srcs = ["rustdoc_lib.rs"], + rustdoc_deps = [":adder"], crate_features = ["with_cc"], deps = [":cc_lib"], ) From 32576dd361d1a84383e672de192cb00fd8e62921 Mon Sep 17 00:00:00 2001 From: Roman Kashitsyn Date: Sat, 23 Apr 2022 10:02:28 +0200 Subject: [PATCH 5/5] sort load statements --- rust/private/rustdoc_test.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 5ec8ab0181..ce3c5ace79 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -15,9 +15,9 @@ """Rules for performing `rustdoc --test` on Bazel built crates""" load("//rust/private:common.bzl", "rust_common") +load("//rust/private:providers.bzl", "CrateInfo") load("//rust/private:rustdoc.bzl", "rustdoc_compile_action") load("//rust/private:utils.bzl", "dedent", "find_toolchain", "transform_deps") -load("//rust/private:providers.bzl", "CrateInfo") def _construct_writer_arguments(ctx, test_runner, action, crate_info): """Construct arguments and environment variables specific to `rustdoc_test_writer`.