Skip to content

Add docs and test for rendering stardoc without a C++ toolchain#313

Open
jjmaestro wants to merge 1 commit into
bazelbuild:masterfrom
jjmaestro:no-cc-toolchain-test
Open

Add docs and test for rendering stardoc without a C++ toolchain#313
jjmaestro wants to merge 1 commit into
bazelbuild:masterfrom
jjmaestro:no-cc-toolchain-test

Conversation

@jjmaestro

Copy link
Copy Markdown

Building Stardoc's renderer from source compiles protoc, which forces a C/C++ toolchain onto doc builds. Add:

  • docs/rendering_without_cc_toolchain.md: why it happens and the per-consumer setup that avoids it, linked from getting_started.
  • test/no_cc_toolchain: a standalone module (wired into CI like test/bzlmod) that renders Stardoc's own rule doc with no CC toolchain and diff-tests the checked-in Markdown.

Fixes #305

Building Stardoc's renderer from source compiles protoc, which forces a
C/C++ toolchain onto doc builds. Add:

- docs/rendering_without_cc_toolchain.md: why it happens and the
  per-consumer setup that avoids it, linked from getting_started.
- test/no_cc_toolchain: a standalone module (wired into CI like
  test/bzlmod) that renders Stardoc's own rule doc with no CC toolchain
  and diff-tests the checked-in Markdown.

Fixes bazelbuild#305
(`@bazel_tools//tools/cpp:toolchain_type`) for its *optional* native
launcher: rules_java adds
[`use_cc_toolchain(mandatory = False)`][rules-java-cc] to the rule's
`toolchains`, so toolchain *resolution* must still succeed even though

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused - doesn't the fact that the toolchain requirement is optional mean that resolution doesn't have to succeed?

exactly why `toolchains_protoc` (now archived) is unnecessary here.
2. **`java_binary` needs CC toolchain *resolution* to succeed.** Even with
nothing C++ left to compile, `java_binary` pulls in the C++ toolchain type
(`@bazel_tools//tools/cpp:toolchain_type`) for its *optional* native

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really true? The launcher should come from a separate toolchain, so unless you are cross-compiling for Windows on a non-Windows host, the launcher shouldn't introduce a C++ toolchain requirement.

@jjmaestro

Copy link
Copy Markdown
Author

I'm confused - doesn't the fact that the toolchain requirement is optional mean that resolution doesn't have to succeed?

Is this really true? The launcher should come from a separate toolchain, so unless you are cross-compiling for Windows on a non-Windows host, the launcher shouldn't introduce a C++ toolchain requirement.

@fmeum you are right that it's confusing, and also what I wrote is probably wrong and/or have the wrong wording.

I'd like to dig deeper into this to really understand what's happening and then fix the wording and the example, because I'm not cross-compiling or anything, without the empty CC toolchain it just fails doing a regular build in Linux for Bazel 7, 8 and 9.

Here's some debugging I've done, running the /test/no_cc_toolchain example, with the empty toolchain in place:

Debugging 7.1.0
$ USE_BAZEL_VERSION=7.1.0 \
bazel cquery 'kind("cc_binary rule", deps(//:stardoc_doc))'

Starting local Bazel server and connecting to it...
INFO: Analyzed target //:stardoc_doc (176 packages loaded, 3440 targets configured).
INFO: Found 1 target...
@bazel_tools//src/tools/launcher:launcher_maker (8f31475)
@bazel_tools//src/tools/launcher:launcher (8f31475)
INFO: Elapsed time: 2.943s, Critical Path: 0.00s
INFO: 0 processes.
INFO: Build completed successfully, 0 total actions

$ USE_BAZEL_VERSION=7.1.0 \
bazel query "somepath(//:stardoc_doc, @bazel_tools//tools/cpp:current_cc_toolchain)"

//:stardoc_doc
@stardoc//stardoc:renderer
@stardoc//src/main/java/com/google/devtools/build/stardoc/renderer:renderer
@bazel_tools//tools/launcher:launcher
@bazel_tools//src/tools/launcher:launcher
@bazel_tools//tools/cpp:current_cc_toolchain

From https://github.com/bazelbuild/rules_java/blob/02f488de/java/bazel/rules/bazel_java_binary.bzl#L320 when I saw

def make_binary_rule(..., attrs, ...):
    return rule(
        ...,
        attrs,
        toolchains = \
          [semantics.JAVA_TOOLCHAIN] + \
          use_cc_toolchain(mandatory = False) + \
          ... + \
          [_LAUNCHER_MAKER_TOOLCHAIN] if bazel_features.rules._has_launcher_maker_toolchain else []
        ),
        exec_groups = {
            "cpp_link": exec_group(toolchains = use_cc_toolchain(mandatory = False)),
        },

I thought the toolchain was optional because of use_cc_toolchain(mandatory = False) but I think the issue is probably due to the attrs.

A few lines below in L339-L338 we have BASE_BINARY_ATTRS with the :launcher and :launcher_maker target that the bazel cquery showed:

BASE_BINARY_ATTRS = merge_attrs(
    BASIC_JAVA_BINARY_ATTRIBUTES,
    {
        "resource_strip_prefix": attr.string(...),
        "_test_support": attr.label(default = _compute_test_support),
        "_launcher": attr.label(
            cfg = "target",
            executable = True,
            default = "@bazel_tools//tools/launcher:launcher",
        ),
    },
    {
        "_windows_launcher_maker": attr.label(
            default = "@bazel_tools//tools/launcher:launcher_maker",
            cfg = "exec",
            executable = True,
        ),
    } if not bazel_features.rules._has_launcher_maker_toolchain else {},
)
Debugging 8.3+ I've also tried with Bazel 8.2 and I get the same trace as with 7.1.0. But with >= 8.3 the query for the `current_cc_toolchain` is empty:
$ USE_BAZEL_VERSION=8.3.0 \
bazel query "somepath(//:stardoc_doc, @bazel_tools//tools/cpp:current_cc_toolchain)"
INFO: Empty results

However, I still get an error if I don't have a CC toolchain:

#  MODULES.bazel: commenting register_toolchains("//toolchains:empty_cc")

$ USE_BAZEL_VERSION=8.3.0 bazel build //:stardoc_doc
ERROR: /home/jjmaestro/.cache/bazel/_bazel_jjmaestro/a868db51c74c9c26abae9ac39c36c609/external/rules_cc+/cc/BUILD:103:19: in cc_toolchain_alias rule @@rules_cc+//cc:current_cc_toolchain:
Traceback (most recent call last):
	File "/virtual_builtins_bzl/common/cc/cc_toolchain_alias.bzl", line 26, column 48, in _impl
	File "/virtual_builtins_bzl/common/cc/cc_helper.bzl", line 163, column 13, in _find_cpp_toolchain
Error in fail: Unable to find a CC toolchain using toolchain resolution. Target: @@rules_cc+//cc:current_cc_toolchain, Platform: @@platforms//host:host, Exec platform: @@bazel_tools//tools:host_platform
ERROR: /home/jjmaestro/.cache/bazel/_bazel_jjmaestro/a868db51c74c9c26abae9ac39c36c609/external/rules_cc+/cc/BUILD:103:19: Analysis of target '@@rules_cc+//cc:current_cc_toolchain' failed
ERROR: Analysis of target '//:stardoc_doc' failed; build aborted: Analysis failed
INFO: Elapsed time: 1.200s, Critical Path: 0.02s
INFO: 1 process: 1 internal.
ERROR: Build did NOT complete successfully
FAILED:
    Fetching repository @@rules_java++toolchains+remotejdk21_linux; starting
    Fetching repository @@rules_java++toolchains+remote_java_tools; starting
    Fetching repository @@rules_java++toolchains+remote_java_tools_linux; starting
    Fetching repository @@protobuf++protoc+prebuilt_protoc.linux_x86_64; starting
    Fetching repository @@rules_python++python+python_3_11_x86_64-unknown-linux-gnu; starting
    Fetching /home/jjmaestro/.cache/bazel/_bazel_jjmaestro/a868db51c74c9c26abae9ac39c36c609/external/protobuf++protoc+prebuilt_protoc.linux_x86_64; Extracting protoc-33.4-linux-x86_64.zip

And, adding back the register_toolchains("//toolchains:empty_cc"):

$ USE_BAZEL_VERSION=8.3.0 \
bazel query "somepath(//:stardoc_doc, @bazel_tools//tools/cpp:current_cc_toolchain)"

INFO: Empty results

$ USE_BAZEL_VERSION=8.3.0 \
bazel cquery "somepath(//:stardoc_doc, @bazel_tools//tools/cpp:current_cc_toolchain)"

WARNING: /home/jjmaestro/.cache/bazel/_bazel_jjmaestro/a868db51c74c9c26abae9ac39c36c609/external/bazel_tools/tools/cpp/BUILD:27:10: target '@@bazel_tools//tools/cpp:current_cc_toolchain' is deprecated: Please use @rules_cc//cc:current_cc_toolchain instead.
INFO: Analyzed 2 targets (0 packages loaded, 349 targets configured).
INFO: Found 2 targets...
//:stardoc_doc (0e16bf0)
@stardoc//stardoc:renderer (2284148)
@stardoc//src/main/java/com/google/devtools/build/stardoc/renderer:renderer (2284148)
@rules_java//toolchains:toolchain_java11 (2284148)
@bazel_tools//tools/jdk:proguard_whitelister (2284148)
@bazel_tools//tools/launcher:launcher_maker (2284148)
@bazel_tools//src/tools/launcher:launcher_maker (2284148)
@bazel_tools//tools/cpp:current_cc_toolchain (2284148)
INFO: Elapsed time: 0.114s, Critical Path: 0.00s
INFO: 0 processes.
INFO: Build completed successfully, 0 total actions

So, it seems for 8.3+ the CC toolchain is also pulled in by the launcher_marker but by another dependency this time: the proguard_whitelister which is a py_binary,

And, in https://github.com/bazel-contrib/rules_python/blob/1.6.0/python/private/py_executable.bzl#L231-L235

    "_windows_launcher_maker": lambda: attrb.Label(
        default = "@bazel_tools//tools/launcher:launcher_maker",
        cfg = "exec",
        executable = True,
    ),

It seems that < 8.3 lead to @bazel_tools//tools/launcher:launcher_marker and >=8.3 lead to @bazel_tools//src/tools/launcher:launcher_maker.

With Bazel 9.1.0 and aspect_bazel_lib 2.19.2 (seems to the the floor for Bazel 9 compatibility) and a more modern rules_python (1.8.0, with your fix c2ff89f for the _windows_launcher_maker if not rp_config.bazel_9_or_later , things work without the empty CC toolchain.

So I guess it has to be that, right? The launcher marker forcing the CC toolchain resolution, and empty works because it resolves even if it's not used?

I'm going to see if I can play a bit more with the internals in rules_java / rules_python and see if I can find a fix that proves this conclusively, but in the meantime, I'd love to know what you think of this! 🙏 Thanks!

@jjmaestro

Copy link
Copy Markdown
Author

I've also tried this patch porting your rules_python fix to 1.6.0 and changing the Bazel version check to 8.3.0 and the /test/no_cc_toolchain example works :)

So, I think the issue is pre-8.3.0 there's no launcher_maker toolchain, and the java_binary rule pulls the CC toolchain with that _launcher/_windows_launcher_maker attributes (@bazel_tools//tools/launcher:{launcher,launcher_marker}).

Then, at 8.3.0, rules_java would work on that path, but there's another path, proguard_whitelister which is a py_binary, and pulls a rules_python that has the fix but it's gated on Bazel 9. With the patch gating the fix to 8.3.0, everything works.

@fmeum

fmeum commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Perhaps all it takes would be a bazel_features version bump? bazel-contrib/bazel_features@1a86fd6

@jjmaestro

Copy link
Copy Markdown
Author

Perhaps all it takes would be a bazel_features version bump? bazel-contrib/bazel_features@1a86fd6

I was hopeful! But, I've just tried with:

diff --git a/test/no_cc_toolchain/MODULE.bazel b/test/no_cc_toolchain/MODULE.bazel
index f1d7c25..3f8be66 100644
--- a/test/no_cc_toolchain/MODULE.bazel
+++ b/test/no_cc_toolchain/MODULE.bazel
@@ -16,6 +16,9 @@ local_path_override(
 bazel_dep(name = "aspect_bazel_lib", version = "2.16.0")
 bazel_dep(name = "rules_java", version = "8.14.0")
 
+bazel_dep(name = "rules_python", version = "1.8.0")
+bazel_dep(name = "bazel_features", version = "1.33.0")
+
 # Only for the *empty* CC toolchain stub in toolchains/BUILD.bazel (which
 # loads cc_toolchain from @rules_cc); nothing here compiles C/C++.
 bazel_dep(name = "rules_cc", version = "0.1.1")

and I still get the same "chain" to the CC toolchain:

$ USE_BAZEL_VERSION=8.3.0 bazel cquery "somepath(//:stardoc_doc, @@rules_cc+//cc:current_cc_toolchain)"
WARNING: For repository 'rules_cc', the root module requires module version rules_cc@0.1.1, but got rules_cc@0.1.5 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
INFO: Analyzed 2 targets (153 packages loaded, 3727 targets configured).
INFO: Found 2 targets...
//:stardoc_doc (0e16bf0)
@stardoc//stardoc:renderer (2284148)
@stardoc//src/main/java/com/google/devtools/build/stardoc/renderer:renderer (2284148)
@rules_java//toolchains:toolchain_java11 (2284148)
@bazel_tools//tools/jdk:proguard_whitelister (2284148)
@bazel_tools//tools/launcher:launcher_maker (2284148)
@bazel_tools//src/tools/launcher:launcher_maker (2284148)
@bazel_tools//tools/cpp:current_cc_toolchain (2284148)
@rules_cc//cc:current_cc_toolchain (2284148)
INFO: Elapsed time: 0.615s, Critical Path: 0.00s
INFO: 0 processes.
INFO: Build completed successfully, 0 total actions

And when I comment out the empty CC toolchain and try USE_BAZEL_VERSION=8.3.0 bazel build //:stardoc_doc it fails with the same "Unable to find a CC toolchain using toolchain resolution" error.

Is there something I'm missing / not doing properly?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Testing docs in a bazel module requires C++ compiler to build protobuf due to stardoc dependency

2 participants