Expand description
Β§Protoweld
Protoweld is a powerful command-line tool designed to automate the compilation of Protocol Buffer (.proto) files into language-specific code for multiple projects. It simplifies the process of managing and generating protobuf code across different programming languages and projects, making it ideal for microservices architectures and multi-language codebases.
Β§Features
- π Multi-language Support: Compile
.protofiles to Go, .NET (C#), and Rust - π Multi-project Management: Handle multiple projects with different configurations in a single YAML file
- π§ Automatic Dependency Checking: Verifies required tools are installed before compilation
- π― Flexible Configuration: Customize compilation options per project
- π Plugin Support: Configure custom gRPC plugins (e.g., for .NET)
- π¦ Smart File Organization: Automatically organizes generated code into specified folders
- π οΈ Rust-specific Optimizations: Special handling for Rust projects with Tonic and Prost
Β§Installation
Β§Standard Installation
Protoweld is available on crates.io and can be installed using Cargo:
cargo install protoweldAfter installation, the protoweld binary will be available in your $HOME/.cargo/bin directory (make sure itβs in your PATH).
Β§Prerequisites
Protoweld requires the following tools to be installed on your system:
- Rust and Cargo - Required for installation via
cargo install. Install Rust - Protocol Buffers Compiler (
protoc) - Required for compiling proto files. Installation Guide
Β§Building from Source
If you prefer to build from source or want to use the latest development version:
- Clone the repository:
git clone https://github.com/XACMJudge/protoweld.git
cd protoweld- Build the project:
cargo build --release- The binary will be available at
target/release/protoweld
Β§Installing Dependencies for Each Language
Β§Go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latestΒ§.NET
- Install the .NET SDK
- Install gRPC Tools NuGet package (the plugin path will be in your NuGet packages folder)
Β§Rust
cargo install protoc-gen-tonic
cargo install protoc-gen-prostΒ§Configuration
Protoweld uses a YAML configuration file to define projects and their compilation settings. The configuration file structure is as follows:
active_projects:
- path: <project-name>
lang: <GoLang|DotNet|Rust>
associated_proto_files:
- <path-to-proto-file-1>
- <path-to-proto-file-2>
compiled_proto_folder: "<output-folder-path>"
plugin_path: "<optional-plugin-path>"
compile_options:
"<option-key>": "<option-value>"
"<option-key>": ""Β§Configuration Fields
Β§Required Fields
path(string): A unique identifier for the projectlang(string): Target programming language. Must be one of:GoLang,DotNet, orRustassociated_proto_files(array of strings): List of paths to.protofiles to compilecompiled_proto_folder(string): Output directory where generated code will be placed
Β§Optional Fields
plugin_path(string): Path to a custom gRPC plugin (required for .NET projects)compile_options(map): Additional compilation options passed toprotoc
Β§Compile Options
The compile_options field allows you to pass custom flags to the Protocol Buffers compiler. Common options include:
-Ior--proto_path: Specify import paths for proto files--descriptor_set_out: Generate a descriptor set file--include_imports: Include all imported files in the descriptor set--experimental_allow_proto3_optional: Enable proto3 optional fields
Note: The output flags (--go_out, --csharp_out, --prost_out, etc.) are automatically handled by Protoweld and should not be specified in compile_options.
Β§Usage
Run Protoweld with the path to your configuration file:
protoweld -f <path-to-config.yaml>Or using the short form:
protoweld -f config.yamlΒ§Example
protoweld -f input/example.yamlΒ§Example Configuration
Hereβs a complete example configuration file (input/example.yaml):
active_projects:
- path: database-server
associated_proto_files:
- ./entities/protos/database-server/operations.proto
compiled_proto_folder: "./database-server/"
lang: GoLang
compile_options:
"-I": entities
- path: security
lang: DotNet
associated_proto_files:
- ./entities/protos/security/users.proto
- ./entities/protos/security/auth.proto
- ./entities/protos/schemas/security.proto
- ./entities/protos/database-server/operations.proto
compiled_proto_folder: "./security/Protos"
plugin_path: /home/user/.nuget/packages/grpc.tools/2.72.0/tools/linux_x64/grpc_csharp_plugin
compile_options:
"-I": entities
"--descriptor_set_out": ./security/descriptors.pb
"--include_imports": ""
"--experimental_allow_proto3_optional": ""
- path: judge-server
lang: Rust
associated_proto_files:
- ./entities/protos/database-server/operations.proto
compiled_proto_folder: "./judge-server/protos"
compile_options:
"-I": entitiesΒ§Supported Languages
Β§Go (GoLang)
Protoweld compiles .proto files to Go code using:
protoc-gen-gofor message typesprotoc-gen-go-grpcfor gRPC service definitions
Generated Output: Go source files in the specified compiled_proto_folder
Β§.NET (DotNet)
Protoweld compiles .proto files to C# code using:
protocwith--csharp_outfor message typesgrpc_csharp_pluginfor gRPC service definitions
Requirements:
- Must specify
plugin_pathpointing to thegrpc_csharp_pluginexecutable - Typically located in:
~/.nuget/packages/grpc.tools/<version>/tools/<platform>/grpc_csharp_plugin
Generated Output: C# source files in the specified compiled_proto_folder
Β§Rust
Protoweld compiles .proto files to Rust code using:
protoc-gen-prostfor message types (Prost)protoc-gen-tonicfor gRPC service definitions (Tonic)
Special Features:
- Automatically organizes generated files into proper Rust module structure
- Creates
mod.rsfiles for each package - Handles file renaming and module imports automatically
Generated Output:
- Rust source files organized by package in the specified
compiled_proto_folder - Each package gets its own module with proper
mod.rsstructure
Β§How It Works
- Parsing: Protoweld reads and parses the YAML configuration file
- Validation: For each project, it validates that:
- Required dependencies are installed
- Proto files exist and contain valid
packagedeclarations - Output directories can be created
- Compilation: For each project, it:
- Assembles the appropriate
protoccommand with language-specific flags - Executes the compilation
- Handles language-specific post-processing (especially for Rust)
- Assembles the appropriate
- Output: Generated code is placed in the specified
compiled_proto_folderfor each project
Β§Why reorganize the Rust generated files?
Protoweld applies extensive transformations to the Rust-generated files mainly to ensure a smooth developer experience with tools like rust-analyzer and to make the generated code ready for ongoing development, not just for one-off code generation.
By default, when the gRPC plugins (protoc-gen-prost for message types and protoc-gen-tonic for services) generate Rust code from .proto files, they output raw .rs files that closely mirror the original proto package and file structure. However, these raw files often lack a module structure compatible with how Rust and its tooling (such as rust-analyzer and cargo) expect code to be organized. For example, there may be missing mod.rs files, incorrect or missing module imports, and file names that donβt align with idiomatic Rust conventions.
Why does Protoweld reorganize these files?
- Rust Tooling Compatibility: Tools like rust-analyzer, and even cargo itself, expect Rust code to be organized into modules using either
mod.rsfiles or the new directory-as-module conventions. The flat file structure output by the plugins does not provide this, making IDE navigation, auto-completion, and refactoring much less effective. - Correct Imports and Modules: The generated files may refer to each other using flat paths, or miss Rust-specific
moddeclarations entirely, which can break module imports or make it difficult to include generated code in your own crate. - Development-Ready Code: Instead of just dumping generated code, Protoweld restructures it so that you can immediately use the generated modules in your own Rust project without manual adjustments. This includes creating
mod.rsfiles, renaming files to valid Rust identifiers, and setting up imports and visibility declarations.
Summary: Protoweldβs file transformations are primarily driven by the needs of real-world Rust development, ensuring that generated Protobuf code is both compiler- and IDE-friendly, resulting in a much smoother workflow for developers.
Β§Project Structure
protoweld/
βββ Cargo.toml # Rust project configuration
βββ README.md # This file
βββ LICENSE # License file
βββ input/ # Example configuration files
β βββ example.yaml # Example YAML configuration
βββ src/ # Source code
βββ main.rs # Entry point
βββ lib.rs # Library root
βββ types/ # Type definitions
β βββ mod.rs
β βββ cli.rs # CLI argument parsing
βββ parser/ # YAML configuration parser
β βββ mod.rs
β βββ protoweld_parser.rs
β βββ types.rs # Parser types and structures
βββ executor/ # Code generation executor
β βββ mod.rs
β βββ protoweld_executor.rs
βββ compilers/ # Language-specific compilers
β βββ mod.rs
β βββ protobuf_compiler.rs # Base compiler trait
β βββ shared.rs # Compiler factory
β βββ langs_compilers/
β βββ mod.rs
β βββ compiler_types.rs
β βββ go_compiler.rs
β βββ dotnet_compiler.rs
β βββ rust_compiler.rs
βββ os/ # OS abstraction layer
βββ mod.rs
βββ types.rs # OS manager trait
βββ shared.rs # OS manager factory
βββ unix_manager.rsΒ§Error Handling
Protoweld provides clear error messages for common issues:
- Missing dependencies: Lists which required tools are not installed
- Invalid proto files: Reports proto files missing
packagedeclarations - Configuration errors: Validates YAML structure and required fields
- Compilation failures: Passes through
protocerror messages
Β§Troubleshooting
Β§βFailed to check installation of dependenciesβ
Ensure all required tools for your target language are installed and available in your PATH:
- For Go:
protoc-gen-goandprotoc-gen-go-grpc - For .NET:
dotnetandprotoc - For Rust:
protoc-gen-tonicandprotoc-gen-prost
Β§βPackage keyword missing in [proto-file]β
Your .proto file must include a package declaration. Example:
syntax = "proto3";
package mypackage;
message MyMessage {
// ...
}This is specially required for Rust projects.
Β§βThe plugin [plugin-name] must have a path in plugin_path optionβ
For .NET projects, you must specify the plugin_path to the grpc_csharp_plugin executable. Find it in your NuGet packages folder or install gRPC Tools.
Β§Path Issues
- Use relative paths from the configuration fileβs location
- Ensure proto file paths are correct and files exist
- Output folders will be created if they donβt exist
Β§Future Plans
Protoweld is actively being developed with the following features planned:
Β§High Priority
- Wildcard Support in File Lists: Support glob patterns in
associated_proto_filesto automatically discover and include proto files (e.g.,./protos/**/*.protoor./entities/**/*.proto) - Windows Platform Support: Investigate whether Windows-specific code is needed or if Rustβs high-level cross-platform APIs are sufficient. Currently, Protoweld uses Unix-specific implementations, but Rustβs standard library may provide adequate cross-platform abstractions
- Additional Language Support: Expand support to more programming languages, including:
- Python (using
grpcio-tools) - Java (using
protoc-gen-javaandprotoc-gen-grpc-java) - TypeScript/JavaScript (using
protoc-gen-tsand@grpc/proto-loader) - C++ (using
protoc-gen-cpp) - PHP (using
protoc-gen-php) - Ruby (using
grpc-tools) - Swift (using
protoc-gen-swift)
- Python (using
- Automatic Plugin Discovery: Automatically search for and locate gRPC plugins in common installation locations (e.g.,
$HOME/.cargo/bin,$HOME/.local/bin, NuGet packages, npm global packages) to reduce manual configuration
Β§Additional Proposals
- Incremental Compilation: Only recompile proto files that have changed since the last run, improving performance for large projects
- Watch Mode: Automatically recompile proto files when source files change, similar to
cargo watchor file system watchers - Enhanced Error Messages: Provide actionable error messages with suggestions for fixing common issues (e.g., βDid you mean to install protoc-gen-go?β)
- Configuration Validation: Validate configuration files before compilation starts, catching errors early
- Parallel Compilation: Compile multiple projects in parallel to reduce total build time
- Dry-Run Mode: Preview what would be compiled without actually executing the compilation
- Verbose/Debug Output: Add detailed logging modes to help debug compilation issues
- Configuration Templates: Generate example configuration files for common project structures
- Proto Dependency Graph: Analyze and visualize dependencies between proto files
- Version Pinning: Support pinning specific versions of protoc and language plugins
- CI/CD Integration: Add features specifically for continuous integration environments (e.g., caching, artifact management)
- Configuration Inheritance: Allow projects to inherit common settings from a base configuration
- Multi-version Support: Support compiling the same proto files to multiple language versions (e.g., Go 1.18 and 1.19)
Β§Contributing
Contributions are welcome! If youβd like to help implement any of these features or have other ideas, please feel free to submit a Pull Request or open an issue to discuss.
Β§License
See the LICENSE file for details.
Β§Acknowledgments
Protoweld is built to simplify Protocol Buffer compilation workflows in multi-language projects, particularly useful for microservices architectures and distributed systems.
ModulesΒ§
- compilers
- Compiler module for language-specific Protocol Buffer code generation.
- executor
- Executor module for orchestrating proto file compilation across projects.
- os
- Operating system abstraction layer for cross-platform operations.
- parser
- Parser module for reading and deserializing Protoweld configuration files.
- types
- Types module containing CLI argument definitions and related types.