Phase 6: consumer Bazel rules + hermetic in-build generation - #14
Merged
Merged
Conversation
Consumers now write smithy_cpp_client_library / smithy_cpp_server_library / smithy_cpp_types_library (bazel/defs.bzl) in their own Bazel 8/9 module and get ordinary cc_library targets - generation runs inside the build graph as a hermetic Java action, never as a run-this-script-first step: - //codegen:generator compiles the generator from the same sources the Gradle build uses (rules_java + rules_jvm_external, Maven lockfile pinned in-repo); Gradle stays the dev workflow. - New runner/settings knobs make output sets predictable per target: --mode types|client|server|both gates client/server emission and --emit-build-file false suppresses the generated BUILD.bazel; --model is now repeatable for multi-file models. - The rules declare exact outputs from the namespace + mode, split hdrs/srcs via output groups, and wire include paths so dependents just #include "<ns>/client.h". Testing, both flavors: - Rule unit tests: rules_testing analysis tests pin the generated file sets per mode, the SmithyCppGenerate action's arguments, and the cc_library include wiring; the rule instances they inspect also compile as an in-tree build test (//bazel/tests). - Out-of-tree integration: examples/bazel-consumer is a standalone module (local_path_override) with its own model, client + server libraries, and a loopback+socket integration test - the quick-start acceptance test, built standalone by a new CI job and .bazelignore'd from this workspace's target graph. Also: googletest bumped to 1.17.0.bcr.2 and the cc-rules autoload flag dropped everywhere; docs/quickstart.md walks the consumer path start to finish; PLAN records the deferrals and follow-ups (BCR/Maven publishing deferred until production validation, @requestCompression gzip slotted into Phase 7, JSON-RPC 2.0 recorded as a candidate future protocol on the existing ProtocolGenerator seam). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
Two one-line root causes from the Phase 6 CI run:
- The root .gitignore's 'bazel-*' pattern (meant for the convenience
symlinks) also matched examples/bazel-consumer, so the whole consumer
module was silently left out of the commit and its CI job found no
directory. Both .gitignore patterns are now anchored ('/bazel-*').
- Dropping the cc-rules autoload flag exposed that nlohmann_json 3.12.0's
BCR BUILD file doesn't load() its cc rules (masked locally by a sandbox
override); 3.12.0.bcr.1 adds the rules_cc dependency. The boost and
googletest modules already load correctly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
The consumer module's .bazelrc deliberately contains only what a real consumer needs; the ci config lives in the main repo's .bazelrc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
boost.container (transitive via boost.beast 1.87) calls native.cc_test without a load(), which fails now that the cc-rules autoload flag is gone. The 1.90.0.bcr.1 module family's overlays load from @rules_cc properly (verified against the registry), so bump boost.asio and boost.beast; MVS lifts the transitive boost graph with them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
The 1.90 boost family fixes the load() statements but boost.asio 1.90 adds a boringssl dependency whose toolchain graph (rules_perl, pybind11_bazel) is heavy and unavailable in restricted environments. An audit of all 58 modules in the boost 1.87 dependency graph found exactly one file calling removed native cc rules — boost.container's gen_test_targets.bzl — so a one-file single_version_override patch adds the missing load() and keeps the dependency graph unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 6: first-class Bazel consumption (BCR publishing deferred)
Consumers now write
smithy_cpp_client_library/smithy_cpp_server_library/smithy_cpp_types_libraryin their own Bazel 8/9 module and get ordinarycc_librarytargets — generation runs inside the build graph as a hermetic Java action (correct caching, remote-execution compatible), never as a "run this script first" step. No Gradle anywhere in the consumer path.How it works
//codegen:generator: the generator compiled from the same sources the Gradle build uses, viarules_java+rules_jvm_externalwith a pinned Maven lockfile (maven_install.json). Gradle remains the dev workflow (unit tests, fixture regeneration); this target exists for consumers and doubles as the CLI (bazel run //codegen:generator -- --model … --mode both --out …).--mode types|client|server|bothgates client/server emission,--emit-build-file falsesuppresses the generatedBUILD.bazel, and--modelis now repeatable for multi-file models.bazel/defs.bzl: the rules declare exact outputs fromnamespace+ mode, split headers/sources via output groups, and wire include paths so dependents just#include "<ns>/client.h". The service's protocol comes from the model itself.Tests, both flavors (as requested)
//bazel/tests,rules_testinganalysis tests): pin the generated file set per mode, theSmithyCppGenerateaction's arguments (--mode,--emit-build-file false,--service), and the cc_library include wiring. The rule instances they inspect also compile as an in-tree build test.examples/bazel-consumer): a standalone module (local_path_override) with its own model, client + server libraries, and a loopback+socket integration test covering round-trips, typed modeled errors, and framework-side constraint validation. A new CI job builds it standalone — the quick-start acceptance test — and.bazelignorekeeps it out of this workspace's target graph.Also in this PR
1.17.0.bcr.2and the cc-rules autoload flag dropped from both.bazelrcs (per review feedback).rules_jvm_externalpinned at 6.7: 7.0 exists but isn't onmirror.bazel.build, which the dev sandbox needs; bumping later is a one-line change + lockfile repin.git_override/local_path_overridemeanwhile);@requestCompression(gzip) slotted into Phase 7; JSON-RPC 2.0 recorded as a candidate future protocol on the existingProtocolGeneratorseam.Deferred from Phase 6 scope (beyond BCR): the docs site and a
smithy-cpp inittemplate command — the consumer example serves as the copyable template for now.Validation
bazel test //...: 41/41 green (gcc and clang--config=asan --config=ubsan), plus the standalone consumer modulegradle buildgreen; goldens regenerated with zero drift🤖 Generated with Claude Code
https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
Generated by Claude Code