Skip to content

Conversation

@willstranton
Copy link
Contributor

@willstranton willstranton commented Oct 29, 2025

Adapts the proposal:
#24043 (comment) by mattyclarkson@ to add support for bazel version variables when doing import or try-import of additional .bazelrc files. The 2 variables added are:

  • %bazel.version.major% - evaluates to 8 when build label is 8.4.2
  • %bazel.version.major.minor% - evaluates to 8.4 when build label is 8.4.2

Eg. If your bazel version was 8.4.2 and your .bazelrc had the following:

try-import %bazel.version.major%.bazelrc
import %bazel.version.major.minor%.bazelrc

It would be evaluated to:

try-import 8.bazelrc
import 8.4.bazelrc

Implementation details:

Build label extraction:

Before: The build label was extracted out only when calling bazel --version and when running in client server mode.

After: Now we always extract the the build label out early in the start of main

Piping of build label:

The build label is stored in the OptionProcessor so that it can be passed to RcFile when parsing occurs.

Parsing and mapping of variables:

The build label is parsed into a new SemVer struct before RcFile::ParseFile. Only if the build label is a proper semantic version, are the specific major and minor values of a semantic version extracted, otherwise, the SemVer struct will contain no_version for each SemVer value. Interpolation of the build label variables (%bazel.version.major% and %bazel.version.major.minor%) happens first, followed by the existing %workspace% variable.

Fixes: #24043

@github-actions github-actions bot added team-Rules-CPP Issues for C++ rules awaiting-review PR is awaiting review from an assigned reviewer labels Oct 29, 2025
@meisterT meisterT requested a review from lberki October 29, 2025 08:12
@brentleyjones
Copy link
Contributor

Does %bazel.version.minor% returning 4 instead of 8.4 make sense? Would anyone ever need that over just having these four?

  • %bazel.version.major%: 8
  • %bazel.version.minor%: 8.4
  • %bazel.version.patch%: 8.4.3
  • %bazel.version%: 8.4.3rc2

@willstranton
Copy link
Contributor Author

willstranton commented Oct 29, 2025

Re: %bazel.version.minor% returning 4 instead of 8.4

Note: Even though I put out a patch for this, I have little stake in this since I don't plan on using this feature. I'm happy to go with whatever the community decides (or what the official bazel maintainers decide). Here are some thoughts:

I put a small example in the commit message for just returning the individual number with the import 8.4-2.bazelrc filename. This doesn't follow the standard #.#.# format and has a dash for the last number instead. Having each part be its own value provides more flexibility in how they want to name the .bazelrc. They could have 8-4-2.bazelrc, 8_4_2.bazelrc. Is that a realistic use case? Maybe - I don't know.

I do see your point on how unlikely it is to need just the patch number by itself. To update your naming:

  • %bazel.version.major%: 8 (unchanged)
  • %bazel.version.minor% -> %bazel.version.major.minor% -> 8.4
  • %bazel.version.patch% -> %bazel.version.major.minor.patch% -> 8.4.3
  • %bazel.version%: 8.4.3rc2

So in total, still only 4 variables, but more verbose names to be clearer what it evaluates to.


Also, wanted to clarify in your example, because you have %bazel.version% evaluate to 8.4.3rc2, but the %bazel.version.patch% was only 8.4.3 - it should be 8.4.3rc2 right? The current patch treats everything after the second dot as the patch number. If we're going to try to go full semantic versioning, then I should fix that and follow https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions and treat the rc2 as the <prerelease> or <build> number.

@willstranton
Copy link
Contributor Author

Sorry, I feel like I'm bikeshedding when talking about <prerelease>/<build> numbers. Let's ignore that and focus on getting variables for what semver.org refers to as <version core>, which are just the major minor and patch numbers and <valid semver>, the full build label. For 8.4.3rc2, the rc2 should not be a part of any of the current patch variable name candidates: %bazel.version.patch%, %bazel.version.major.minor.patch%.

@willstranton
Copy link
Contributor Author

Updated the code. This now does proper semantic version processing instead of the naive split by dots I was doing earlier.

re: variables available - In the spirit of why not both, I just implemented the original proposal and the variant of your new proposal that I mentioned in the previous comment. So for the build label: 9.4.2-pre.20251022.1 the variables available and their values are:

  • %bazel.version%: 9.4.2-pre.20251022.1
  • %bazel.version.major%: 9
  • %bazel.version.minor%: 4
  • %bazel.version.patch%: 2
  • %bazel.version.prerelease%: pre.20251022.1
  • %bazel.version.buildmetadata%: (empty)
  • %bazel.version.major.minor%: 9.4
  • %bazel.version.major.minor.patch%: 9.4.2

I think this should handle all cases that a user would want with enough flexibility, clarity, and convenience baked in.

Follows the proposal:
bazelbuild#24043 (comment) by
mattyclarkson@ to add support for the following variables when importing
additional bazelrc files.  Variables are followed by their values for the
hypothetical build label 9.4.2-pre.20251022.1:

- %bazel.version% - 9.4.2-pre.20251022.1
- %bazel.version.major% - 9
- %bazel.version.minor% - 4
- %bazel.version.patch% - 2
- %bazel.version.prerelease% - pre.20251022.1
- %bazel.version.buildmetadata% - (empty)
- %bazel.version.major.minor% - 9.4
- %bazel.version.major.minor.patch% - 9.4.2

Eg. If your bazel version was 8.4.2-pre.20251022.1 and your .bazelrc had the
following:

> try-import %bazel.version%.bazelrc
> import %bazel.version.major%.%bazel.version.minor%-%bazel.version.patch%.bazelrc
> try-import %bazel.version.major%.bazelrc

It would be evaluated to:

> try-import 8.4.2.bazelrc
> import 8.4-2.bazelrc
> try-import 8.bazelrc

# Implementation details:

## Build label extraction:

Before: The build label was extracted out only when calling `bazel --version`
and when running in client server mode.

After: Now we always extract the the build label out early in the start of main

## Piping of build label:

The build label is stored in the OptionProcessor so that it can be passed to
`RcFile` when parsing occurs.

## Parsing and mapping of variables:

The build label is parsed during `RcFile::ParseFile` into its constituent parts
(major, minor, patch).  This occurs EACH TIME an import statement is found in a
.rc file. This is wasteful, but the logic is simple enough that it shouldn't
matter. Interpolation of the build label happens first, followed by
`%workspace%`.

Fixes: bazelbuild#24043
@fmeum
Copy link
Collaborator

fmeum commented Oct 30, 2025

I would suggest limiting this to just two variables, returning 8 and 8.4 respectively for Bazel version 8.4.2rc2. There's pretty much never a reason to use anything but the latest patch version for a given minor version anyway.

Every new variable becomes a public API surface that users will end up (possibly inadvertently) depending on, so there should be at least some potential use case for each variable we add.

@meisterT meisterT added team-Core Skyframe, bazel query, BEP, options parsing, bazelrc and removed team-Rules-CPP Issues for C++ rules labels Oct 30, 2025
The current use case/feature requested just requires these two.
Per fmeum in bazelbuild#27447 (comment)

> There's pretty much never a reason to use anything but the latest patch
> version for a given minor version anyway.
>
> Every new variable becomes a public API surface that users will end up
> (possibly inadvertently) depending on, so there should be at least some
> potential use case for each variable we add.
@willstranton
Copy link
Contributor Author

Ok, reduce the possible variables to just two:

  • %bazel.version.major% - 8 in 8.4.2
  • %bazel.version.major.minor% - 8.4 in 8.4.2

@brentleyjones
Copy link
Contributor

Can you also update the PR description with this change?

@willstranton
Copy link
Contributor Author

Can you also update the PR description with this change?

Done

Instead of evaluating the semantic version from the build_label for each import
call, the build_label is parsed once, before being used in rc_file reading.
@willstranton
Copy link
Contributor Author

Added a minor change to stop reparsing build_label multiple times, and instead parse once and store in a SemVer struct.

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

Labels

awaiting-review PR is awaiting review from an assigned reviewer team-Core Skyframe, bazel query, BEP, options parsing, bazelrc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support bazel-version specific flags in bazelrc

4 participants