Skip to content

Support running Go generator as go tool protoc-gen-go #23509

@igor-sirotin

Description

@igor-sirotin

What language does this apply to?

C++

Describe the problem you are trying to solve

Go 1.24 introduced Tool dependencies feature. This allows Go projects to refer to protoc-gen-go like this:

module github.com/example/project

go 1.24.0

tool (
    google.golang.org/protobuf/cmd/protoc-gen-go
)

require (
    google.golang.org/protobuf v1.36.4
)

Why is this better?

  1. Automatic installation of protoc-gen-go
  2. Version control the version of required protoc-gen-go
  3. Utilize Go vendoring feature for the protoc-gen-go

Describe the solution you'd like

TLDR; Before the fallback to Subprocess::SEARCH_PATH, also check if go tool protoc-gen-go is available.

Subprocess selection logic

flowchart TD
    A[Looking for protoc-gen-go] --> B{Is protoc-gen-go defined with --plugin option?}
    
    B -->|Yes| C[Use the plugin defined with --plugin option]
    
    B -->|No| D[Run 'go tool' in current working directory]
    
    D --> E[Check go tool output for protoc-gen-go]
    
    E --> F{Is protoc-gen-go found in go tool output?}
    
    F -->|Yes| G[Run: go tool protoc-gen-go]
    
    %% Style the ADDED STAGE nodes
    style D stroke:#ff9800,stroke-width:3px,stroke-dasharray: 5 5
    style E stroke:#ff9800,stroke-width:3px,stroke-dasharray: 5 5
    style F stroke:#ff9800,stroke-width:3px,stroke-dasharray: 5 5
    style G stroke:#ff9800,stroke-width:3px,stroke-dasharray: 5 5
    
    F -->|No| H[Look for protoc-gen-go in PATH]
    
    C --> I[Complete]
    G --> I
    H --> I
Loading

Note that go tool will list google.golang.org/protobuf/cmd/protoc-gen-go if it's available:

> go tool
addr2line
asm
cgo
compile
...
google.golang.org/protobuf/cmd/protoc-gen-go
...

Currently devs of Go projects have to go install google.golang.org/protobuf/cmd/protoc-gen-go.
This has a few disadvantages:

  1. Manual installation for each developer and CI
  2. Manual version tracking of the protoc-gen-go, instead of just defining it in go.mod

Describe alternatives you've considered

There is a workaround.

  1. Create a protoc-gen-go wrapper binary/script
    #!/bin/bash
    exec go tool protoc-gen-go "$@"
  2. Use protoc --plugin=<path-to-wrapper>

Pros:

  • No protoc modifications

Cons:

  • Not a cross-platform solution — Windows needs an actual Win32 binary rather than a .bat script
  • Each user will have to re-implement this solution on their side. While I anticipate wide usage of go tool soon(ish).

Implementation

I can prepare a PR myself. But I would like to agree on the solution in advance.

I see that logic of looking for the language generator in CommandLineInterface::GeneratePluginOutput is very neat. I like it and don't want to pollute it with custom GoLang conditions.

The idea I have on my mind is to implement a common way to add custom way(s) of looking for the generator.
I'm not sure if it's useful for any other languages than Go, but at least it will not be a hack.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions