Skip to content

test: verify Cargo cfgs for all supported triples - #205

Open
Geethree wants to merge 1 commit into
hermeticbuild:mainfrom
Geethree:test/cargo-cfg-all-triples
Open

test: verify Cargo cfgs for all supported triples#205
Geethree wants to merge 1 commit into
hermeticbuild:mainfrom
Geethree:test/cargo-cfg-all-triples

Conversation

@Geethree

@Geethree Geethree commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • generate baseline cfg values for every supported target with the registered Rust compiler
  • use the generated values for exact matching, including repeated keys and bare predicates
  • reject target triples outside ALL_TARGET_TRIPLES rather than approximating their cfg values
  • add a generated-source freshness test and exhaustive positive/negative parser coverage

The generated cfg_target_data.bzl file is a 14.8 KB interned target-cfg table loaded by cfg_parser.bzl during normal rule evaluation.

Performance

I profiled the same parser query against upstream main and this branch with Bazel 9.0.0:

bazel query //rs/private:cfg_parser --profile=profile.json

I extracted the sole preloadOrThrow duration from each trace with:

jq '[.traceEvents[] | select(.name == "preloadOrThrow") | .dur] | add' profile.json

Bazel reports trace durations in microseconds:

Revision Starlark preload
upstream main 11,587 us (11.6 ms)
this branch 25,391 us (25.4 ms)
difference +13,804 us (+13.8 ms)

This is a single before/after measurement rather than a benchmark distribution. The percentage increase is large because the baseline is small; the measured absolute difference was 13.8 ms.

Testing

  • bazel test //rs/private:cfg_parser_tests //rs/private:update_cfg_target_data_tests
  • bazel test //...

@dzbarsky dzbarsky left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@codex review

Comment thread tools/cfg_oracle/README.md Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a556d3ca2f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/private/cfg_parser.bzl Outdated
Comment on lines +274 to +276
atom_ids = CFG_ATOM_IDS_BY_TRIPLE.get(triple)
if atom_ids != None:
return [CFG_ATOMS[atom_id] for atom_id in atom_ids]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use cfg data from the selected Rust toolchain

When a consumer configures a nondefault compiler through toolchains.toolchain(version = ...), this lookup still unconditionally returns the checked-in Rust 1.92 cfg set. These sets vary by compiler version: for example, Rust 1.92 reports bulk-memory and nontrapping-fptoint for wasm32-wasip1, while Rust 1.86 does not, so a dependency guarded by either target_feature is selected even though the configured compiler lacks that baseline cfg. Generate or select the oracle by configured compiler version, or explicitly reject unsupported versions instead of applying the 1.92 table to every toolchain.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this is a valid find. My first thoughts are:

  • Make the data version-aware: Generate tables keyed by rust version and have each cargo closure use the table matching its selected compiler.
  • Enforce the recorded version: If the table was generated with rust 1.92, only use it when the selected compiler is 1.92. For any other version, fail clearly instead of silently calculating the wrong dependency graph.

Any thoughts here @dzbarsky?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

tbh this makes me sad, because I don't think we want to be in the business of per-rust-version data. (What about nightlies? what about someone testing a new compiler that we haven't added data for yet? Fallback to heuristics? Is that better than just using latest? ;) )

Also, what does "have each cargo closure use the table matching its selected compiler" mean? The compiler used at build time is an arbitrary toolchain and the cargo extension has no idea which one will be selected.

Overall it feels weird to me that compiler version affects these, as they should really be immutable properties of the target platform IMO. I suspect (hope?) that it's really only the case for wasm/wasi where so much of it depends on compiler support. I wonder if we can just default to a fairly old/conservative compiler's output. Probably need to do more research, but wdyt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed on the research. I'll poke around this week!

Comment thread rs/private/cfg_parser_test.bzl Outdated
Comment thread rs/private/cfg_parser.bzl Outdated
values = {}
ctx = {
"_triple": triple,
"_values": values,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why did all of these move into _values isntead of being directly on the ctx?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The extra map was intended to support repeated rustc values such as target_feature and target_has_atomic, but the nesting was unnecessary. The context now stores a set directly at each cfg key and generic equality uses membership against that set.

Comment thread rs/private/cfg_parser.bzl
"windows": fam == "windows",
"wasm": fam == "wasm",
}
def triple_to_cfg_attrs(triple):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this will run once per-cargo-closure. I wonder if its worth deduping the construciton of these contexts by lifting it higher in the graph and passing those in instead of the triples (since triples can be retrieved from them anyway?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The contexts are currently constructed once in resolve_cargo_workspace_members for each Cargo closure, then reused by the resolver and workspace dependency rendering; target-expression results are cached as well. Lifting them further would only deduplicate across closures with the same triple set, so I left that plumbing unchanged pending evidence that cross-closure construction is material.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd expect a typical bazel repo to have 5-15 closures (there are some internal ones for rules_rs, though I should probably merge to a single one...). so yeah maybe not a huge deal

@theGlenn

Copy link
Copy Markdown

Sorry for joining this late. I ran into the same question while working on #213.

IMHO, per-version tables do not fit the current resolver. The Cargo extension does not know which Rust toolchain Bazel will later select.

Using an older table is not safe either -> a newer compiler can enable a cfg missing from that table.

I lean toward separating target identity (target_arch, target_os, ABI, and so on) from compiler-dependent capabilities (target_feature, atomic support).

#213 only fixes triple-derived identity and leaves compiler-dependent cfg handling unchanged.

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.

3 participants