Skip to content

codegen: add file_per_package option for BSR cargo-SDK compatibility#73

Merged
iainmcgin merged 4 commits intomainfrom
feat/file-per-package
Apr 29, 2026
Merged

codegen: add file_per_package option for BSR cargo-SDK compatibility#73
iainmcgin merged 4 commits intomainfrom
feat/file-per-package

Conversation

@iainmcgin
Copy link
Copy Markdown
Collaborator

Adds a file_per_package option to CodeGenConfig (and the protoc-gen-buffa CLI) that emits one <dotted.package>.rs per proto package instead of the default per-proto-file split. The single file inlines what the <pkg>.mod.rs stitcher would otherwise include!, producing the identical __buffa:: module structure.

Why

BSR's cargo-SDK pipeline assembles lib.rs server-side by splitting each output filename on . and building a nested pub mod tree — the same convention prost's per-package output follows. Our default per-file output (pet.v1.pet.rs, pet.v1.pet.__view.rs, pet.v1.mod.rs, ...) would synthesize to garbage under that algorithm. With file_per_package=true set in the BSR plugin manifest's registry.opts, our output slots into the existing synthesis with no special-casing on Buf's side. See bufbuild/plugins#2333.

This mode is correct under strategy: directory for PACKAGE_DIRECTORY_MATCH-clean modules (one directory == one package, so each invocation sees a complete package), so it does not introduce a strategy: all requirement.

Implementation

  • PackageSections intermediate holds per-section Vec<TokenStream>s; generate_package_mod now consumes it uniformly. The per-file path builds sections from include! token streams; the per-package path inlines the content directly. Module structure is identical between modes.
  • package_to_filename() helper for <pkg>.rs naming.
  • GeneratedFileKind::PackageMod is reused for the single-file output.

Deferred (Low review findings)

  • OutputLayout enum instead of bool — only one alternate layout exists; revisit if more emerge.
  • Unnamed-package output is __buffa.rs, which under BSR's synthesis would double-nest. Buf's PACKAGE_DEFINED lint (MINIMAL group) makes this a near-zero case for SDK gen, and it mirrors the existing per-file path's behavior.

Inlines what the per-file stitcher would include!, producing the same
__buffa:: module structure in a single file per package. Intended for
BSR generated SDKs whose lib.rs synthesis builds the module tree from
<dotted.package>.rs filenames.
- Richer parity test: fixture now has a oneof + nested type; the
  stitcher's include!s are spliced with content-file bodies and the
  brace-depth-tracked pub mod sequence is compared against the
  per-package output.
- Doc updates: GeneratedFile/GeneratedFileKind note the per-package
  mode; field doc states the silent-partial-output failure mode under
  strategy:directory with split packages.
- Rename package_filename -> package_to_filename for consistency with
  package_to_mod_filename.
- Cross-feature test: file_per_package + generate_text + nested type,
  asserting register_types paths resolve.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@iainmcgin iainmcgin marked this pull request as ready for review April 29, 2026 15:37
@iainmcgin iainmcgin requested a review from kollektiv April 29, 2026 15:37
@iainmcgin iainmcgin merged commit 6002043 into main Apr 29, 2026
7 checks passed
@iainmcgin iainmcgin deleted the feat/file-per-package branch April 29, 2026 19:44
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants