From 7b731c2eebf7cbefc89ce6f627a2826d3d79aa28 Mon Sep 17 00:00:00 2001 From: Troy Benson Date: Mon, 16 Jun 2025 03:45:54 +0000 Subject: [PATCH 1/5] add rustdoc feature support --- rust/private/providers.bzl | 1 + rust/private/rust.bzl | 1 + rust/private/rustdoc.bzl | 7 +++++++ rust/private/rustdoc_test.bzl | 8 ++++++++ 4 files changed, 17 insertions(+) diff --git a/rust/private/providers.bzl b/rust/private/providers.bzl index 746370bc70..143ec0ad3a 100644 --- a/rust/private/providers.bzl +++ b/rust/private/providers.bzl @@ -36,6 +36,7 @@ CrateInfo = provider( "rustc_rmeta_output": "File: The rmeta file produced for this crate. It is optional.", "srcs": "depset[File]: All source Files that are part of the crate.", "std_dylib": "File: libstd.so file", + "crate_features": "[str]: A list of feature enabled for this crate.", "type": ( "str: The type of this crate " + "(see [rustc --crate-type](https://doc.rust-lang.org/rustc/command-line-arguments.html#--crate-type-a-list-of-types-of-crates-for-the-compiler-to-emit))." diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index 74d458eef9..700f49e908 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -206,6 +206,7 @@ def _rust_library_common(ctx, crate_type): compile_data = depset(compile_data), compile_data_targets = depset(ctx.attr.compile_data), owner = ctx.label, + crate_features = ctx.attr.crate_features, ), ) diff --git a/rust/private/rustdoc.bzl b/rust/private/rustdoc.bzl index 67845c34ca..bf1ffb5805 100644 --- a/rust/private/rustdoc.bzl +++ b/rust/private/rustdoc.bzl @@ -236,6 +236,9 @@ def _rust_doc_impl(ctx): rustdoc_flags.extend(ctx.attr.rustdoc_flags) + if ctx.attr.include_features: + rustdoc_flags.extend(["--cfg=feature=\"{}\"".format(feature) for feature in crate_info.crate_features]) + action = rustdoc_compile_action( ctx = ctx, toolchain = find_toolchain(ctx), @@ -350,6 +353,10 @@ rust_doc = rule( file of arguments to rustc: `@$(location //package:target)`. """), ), + "include_features": attr.bool( + doc = "Include the features defined by `crate_features` when building the doc tests.", + default = True, + ), "_dir_zipper": attr.label( doc = "A tool that orchestrates the creation of zip archives for rustdoc outputs.", default = Label("//rust/private/rustdoc/dir_zipper"), diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index a338518038..6b724103fa 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -129,6 +129,7 @@ def _rust_doc_test_impl(ctx): compile_data = crate.compile_data, compile_data_targets = crate.compile_data_targets, wrapped_crate_type = crate.type, + crate_features = crate.crate_features, owner = ctx.label, ) @@ -150,6 +151,9 @@ def _rust_doc_test_impl(ctx): "--test", ] + if ctx.attr.include_features: + rustdoc_flags.extend(["--cfg=feature=\"{}\"".format(feature) for feature in crate_info.crate_features]) + action = rustdoc_compile_action( ctx = ctx, toolchain = toolchain, @@ -228,6 +232,10 @@ rust_doc_test = rule( default = Label("//rust/private/rustdoc:rustdoc_test_writer"), executable = True, ), + "include_features": attr.bool( + doc = "Include the features defined by `crate_features` when building the doc tests.", + default = True, + ), }, test = True, fragments = ["cpp"], From 91543baa70feff6ec5b4492a33dc8fbce9cec0bf Mon Sep 17 00:00:00 2001 From: Troy Benson Date: Mon, 16 Jun 2025 03:59:10 +0000 Subject: [PATCH 2/5] add features for binaries too --- rust/private/rust.bzl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index 700f49e908..2596630ba1 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -259,6 +259,7 @@ def _rust_binary_impl(ctx): compile_data = depset(compile_data), compile_data_targets = depset(ctx.attr.compile_data), owner = ctx.label, + crate_features = ctx.attr.crate_features, ), ) @@ -423,6 +424,7 @@ def _rust_test_impl(ctx): compile_data = depset(compile_data), compile_data_targets = depset(ctx.attr.compile_data), owner = ctx.label, + crate_features = [], ) providers = rustc_compile_action( From e9eb65382cf7d12fda373b53064efd1268fd1965 Mon Sep 17 00:00:00 2001 From: Troy Benson Date: Mon, 23 Jun 2025 14:17:29 +0000 Subject: [PATCH 3/5] add unit test for rustdoc --- test/unit/rustdoc/rustdoc_features.rs | 23 ++++++++++++++++++ test/unit/rustdoc/rustdoc_unit_test.bzl | 31 +++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 test/unit/rustdoc/rustdoc_features.rs diff --git a/test/unit/rustdoc/rustdoc_features.rs b/test/unit/rustdoc/rustdoc_features.rs new file mode 100644 index 0000000000..df7e60a6db --- /dev/null +++ b/test/unit/rustdoc/rustdoc_features.rs @@ -0,0 +1,23 @@ +// 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. + +//! +//! Checkout [inc] +//! + +/// Increments the input. +#[cfg(feature = "docs")] +pub fn inc(n: u32) -> u32 { + n + 1 +} diff --git a/test/unit/rustdoc/rustdoc_unit_test.bzl b/test/unit/rustdoc/rustdoc_unit_test.bzl index aa1f9b2f02..059d9a6817 100644 --- a/test/unit/rustdoc/rustdoc_unit_test.bzl +++ b/test/unit/rustdoc/rustdoc_unit_test.bzl @@ -97,6 +97,18 @@ def _rustdoc_for_bin_with_transitive_proc_macro_test_impl(ctx): return analysistest.end(env) +def _rustdoc_for_lib_with_features_test_impl(ctx): + env = analysistest.begin(ctx) + tut = analysistest.target_under_test(env) + + _common_rustdoc_checks(env, tut) + + action = _get_rustdoc_action(env, tut) + + assert_argv_contains(env, action, "--cfg=feature=\"docs\"") + + return analysistest.end(env) + def _rustdoc_for_lib_with_cc_lib_test_impl(ctx): env = analysistest.begin(ctx) tut = analysistest.target_under_test(env) @@ -164,6 +176,7 @@ rustdoc_for_lib_with_proc_macro_in_docs_test = analysistest.make(_rustdoc_for_li 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) rustdoc_with_args_test = analysistest.make(_rustdoc_with_args_test_impl) +rustdoc_for_lib_with_features_test = analysistest.make(_rustdoc_for_lib_with_features_test_impl) rustdoc_zip_output_test = analysistest.make(_rustdoc_zip_output_test_impl) rustdoc_with_json_error_format_test = analysistest.make(_rustdoc_with_json_error_format_test_impl, config_settings = { str(Label("//rust/settings:error_format")): "json", @@ -283,6 +296,18 @@ def _define_targets(): crate_features = ["with_proc_macro"], ) + _target_maker( + rust_library, + name = "lib_with_features", + srcs = ["rustdoc_features.rs"], + crate_features = ["docs"], + ) + + rust_doc( + name = "rustdoc_lib_with_features", + crate = ":lib_with_features", + ) + cc_library( name = "cc_lib", hdrs = ["rustdoc.h"], @@ -424,6 +449,11 @@ def rustdoc_test_suite(name): target_under_test = ":lib_with_cc_doc", ) + rustdoc_for_lib_with_features_test( + name = "rustdoc_for_lib_with_features_test", + target_under_test = ":rustdoc_lib_with_features", + ) + rustdoc_with_args_test( name = "rustdoc_with_args_test", target_under_test = ":rustdoc_with_args", @@ -455,6 +485,7 @@ def rustdoc_test_suite(name): ":rustdoc_for_lib_with_proc_macro_in_docs_test", ":rustdoc_for_lib_with_proc_macro_test", ":rustdoc_for_lib_with_cc_lib_test", + ":rustdoc_for_lib_with_features_test", ":rustdoc_with_args_test", ":rustdoc_with_json_error_format_test", ":rustdoc_zip_output_test", From b2a5ed206f32f5bad034f368ed6e0a03e1df2d33 Mon Sep 17 00:00:00 2001 From: Troy Benson Date: Mon, 23 Jun 2025 14:20:36 +0000 Subject: [PATCH 4/5] add disable test --- test/unit/rustdoc/rustdoc_features.rs | 4 +++- test/unit/rustdoc/rustdoc_unit_test.bzl | 32 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/test/unit/rustdoc/rustdoc_features.rs b/test/unit/rustdoc/rustdoc_features.rs index df7e60a6db..68174c02f9 100644 --- a/test/unit/rustdoc/rustdoc_features.rs +++ b/test/unit/rustdoc/rustdoc_features.rs @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![deny(rustdoc::broken_intra_doc_links)] + //! //! Checkout [inc] -//! +//! /// Increments the input. #[cfg(feature = "docs")] diff --git a/test/unit/rustdoc/rustdoc_unit_test.bzl b/test/unit/rustdoc/rustdoc_unit_test.bzl index 059d9a6817..abb94d29c8 100644 --- a/test/unit/rustdoc/rustdoc_unit_test.bzl +++ b/test/unit/rustdoc/rustdoc_unit_test.bzl @@ -109,6 +109,18 @@ def _rustdoc_for_lib_with_features_test_impl(ctx): return analysistest.end(env) +def _rustdoc_for_lib_without_features_test_impl(ctx): + env = analysistest.begin(ctx) + tut = analysistest.target_under_test(env) + + _common_rustdoc_checks(env, tut) + + action = _get_rustdoc_action(env, tut) + + assert_argv_contains_prefix_not(env, action, "--cfg=feature") + + return analysistest.end(env) + def _rustdoc_for_lib_with_cc_lib_test_impl(ctx): env = analysistest.begin(ctx) tut = analysistest.target_under_test(env) @@ -177,6 +189,7 @@ rustdoc_for_bin_with_transitive_proc_macro_test = analysistest.make(_rustdoc_for rustdoc_for_lib_with_cc_lib_test = analysistest.make(_rustdoc_for_lib_with_cc_lib_test_impl) rustdoc_with_args_test = analysistest.make(_rustdoc_with_args_test_impl) rustdoc_for_lib_with_features_test = analysistest.make(_rustdoc_for_lib_with_features_test_impl) +rustdoc_for_lib_without_features_test = analysistest.make(_rustdoc_for_lib_without_features_test_impl) rustdoc_zip_output_test = analysistest.make(_rustdoc_zip_output_test_impl) rustdoc_with_json_error_format_test = analysistest.make(_rustdoc_with_json_error_format_test_impl, config_settings = { str(Label("//rust/settings:error_format")): "json", @@ -308,6 +321,19 @@ def _define_targets(): crate = ":lib_with_features", ) + _target_maker( + rust_library, + name = "lib_without_features", + srcs = ["rustdoc_features.rs"], + crate_features = ["docs"], + ) + + rust_doc( + name = "rustdoc_lib_without_features", + crate = ":lib_with_features", + include_features = False, + ) + cc_library( name = "cc_lib", hdrs = ["rustdoc.h"], @@ -454,6 +480,11 @@ def rustdoc_test_suite(name): target_under_test = ":rustdoc_lib_with_features", ) + rustdoc_for_lib_without_features_test( + name = "rustdoc_for_lib_without_features_test", + target_under_test = ":rustdoc_lib_without_features", + ) + rustdoc_with_args_test( name = "rustdoc_with_args_test", target_under_test = ":rustdoc_with_args", @@ -486,6 +517,7 @@ def rustdoc_test_suite(name): ":rustdoc_for_lib_with_proc_macro_test", ":rustdoc_for_lib_with_cc_lib_test", ":rustdoc_for_lib_with_features_test", + ":rustdoc_for_lib_without_features_test", ":rustdoc_with_args_test", ":rustdoc_with_json_error_format_test", ":rustdoc_zip_output_test", From 49da2b30abd63db433d2ade397648dc957ac08e8 Mon Sep 17 00:00:00 2001 From: Troy Benson Date: Thu, 3 Jul 2025 12:24:55 +0000 Subject: [PATCH 5/5] add a cfg to control no_feature test --- test/unit/rustdoc/rustdoc_features.rs | 6 +++++- test/unit/rustdoc/rustdoc_unit_test.bzl | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/unit/rustdoc/rustdoc_features.rs b/test/unit/rustdoc/rustdoc_features.rs index 68174c02f9..c99361c73a 100644 --- a/test/unit/rustdoc/rustdoc_features.rs +++ b/test/unit/rustdoc/rustdoc_features.rs @@ -12,12 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![deny(rustdoc::broken_intra_doc_links)] +#![cfg_attr(not(no_feature_test), deny(rustdoc::broken_intra_doc_links))] +#![cfg_attr(no_feature_test, allow(rustdoc::broken_intra_doc_links))] //! //! Checkout [inc] //! +#[cfg(all(no_feature_test, feature = "docs"))] +compiler_error!("cannot have both no_feature_test and feature=\"docs\" enabled"); + /// Increments the input. #[cfg(feature = "docs")] pub fn inc(n: u32) -> u32 { diff --git a/test/unit/rustdoc/rustdoc_unit_test.bzl b/test/unit/rustdoc/rustdoc_unit_test.bzl index abb94d29c8..27e4ed8986 100644 --- a/test/unit/rustdoc/rustdoc_unit_test.bzl +++ b/test/unit/rustdoc/rustdoc_unit_test.bzl @@ -332,6 +332,9 @@ def _define_targets(): name = "rustdoc_lib_without_features", crate = ":lib_with_features", include_features = False, + rustdoc_flags = [ + "--cfg=no_feature_test" + ] ) cc_library(