bazel icon indicating copy to clipboard operation
bazel copied to clipboard

[9.0.0] Add support for multiple module interfaces per `cc_library`

Open fmeum opened this issue 2 weeks ago • 1 comments

When multiple module_interfaces are specified on a single cc_library, the individual compilation actions form a DAG based on imports between these modules. Consider the following situation:

  • a.cppm imports b.cppm, both of which are in the module_interfaces of a single cc_library.
  • Building the target populates the action cache with an entry for a.pcm that stores b.pcm as a discovered input.
  • Now edit a.cppm and b.cppm so that b.cppm imports a.cppm and a.cppm no longer imports b.cppm.
  • Build again (optionally after a shutdown).

Before this commit, this resulted in an action cycle since during action cache checking, Bazel would reuse or look up the inputs discovered in the previous build, thus introducing an edge from a.pcm to b.pcm. Together with the newly discovered edge from b.pcm to a.pcm, this resulted in a cycle.

This is fixed by not requesting the previously discovered inputs (either retained in memory or in the action cache) if the mandatory inputs changed. In the case of C++20 modules, this is sufficient since the modmap file, which lists all transitive .pcm files required for compilation, is a mandatory input.

As part of this change, MetadataDigestUtils.fromMetadata had to be modified to always return a byte array of proper digest length, even if called with an empty map, to match the assumptions of the action cache.

This change is pretty much Fabian's PR https://github.com/bazelbuild/bazel/pull/27492 with a tiny fix added on top (not returning from computeMandatoryInputsDigest() early on valuesMissing() if inErrorBubbling() is true)

Closes #27492.

PiperOrigin-RevId: 842733471 Change-Id: I48fa2c0bceb888dcb58db29d50c30719b2122c5d (cherry picked from commit cb9bd8615210dda2104f79d281938e47187dc2de)

Closes #27544

fmeum avatar Dec 10 '25 16:12 fmeum

Summary of Changes

Hello @fmeum, I'm Gemini Code Assist[^1]! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue in Bazel's action caching system that could lead to action cycles when working with C++20 modules, particularly when the import relationships between module_interfaces within a cc_library change. The core of the solution involves enhancing the action cache to track and validate a 'mandatory inputs digest'. This ensures that if the essential inputs of an action, such as the C++20 module map, change, the action is re-executed rather than relying on potentially stale discovered inputs, thereby preventing erroneous build cycles.

Highlights

  • Action Cycle Prevention: Introduced a mechanism to prevent action cycles in Bazel's action cache when C++20 module import dependencies change. This is achieved by not reusing previously discovered inputs if the mandatory inputs for an action have been altered.
  • Mandatory Inputs Digest: Added a new concept of 'mandatory inputs digest' to the action cache. This digest is computed for an action's essential inputs and is used to determine if a re-execution is necessary, even if previously discovered inputs are available.
  • Action Cache Updates: Modified the ActionCacheChecker and ActionCache to store and check this new mandatory inputs digest, ensuring that the cache correctly invalidates entries when module dependencies shift.
  • Metadata Handling: Updated MetadataDigestUtils.fromMetadata to consistently return a byte array of the correct digest length, even for empty metadata maps, to align with action cache assumptions.
  • C++20 Module Integration Tests: Added new integration tests specifically designed to validate the fix for action cycles when C++20 module import graphs change (e.g., a imports b changing to b imports a).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with :thumbsup: and :thumbsdown: on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

[^1]: Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

gemini-code-assist[bot] avatar Dec 10 '25 16:12 gemini-code-assist[bot]

@fmeum Could you please resolve the conflicts?

iancha1992 avatar Dec 10 '25 19:12 iancha1992

@iancha1992 Should be fixed

fmeum avatar Dec 10 '25 20:12 fmeum