Skip to content

Commit f461d12

Browse files
authored
feat(AIP-4210): add code gen diagram + tweaks (#1148)
1 parent 03ccf45 commit f461d12

1 file changed

Lines changed: 99 additions & 16 deletions

File tree

aip/client-libraries/4210.md

Lines changed: 99 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
id: 4210
33
state: approved
44
created: 2018-06-22
5+
js_scripts:
6+
- /assets/js/graphviz/viz.js
7+
- /assets/js/graphviz/lite.render.js
8+
- /assets/js/aip/aip-graphviz.js
59
---
610

711
# Client library generators
@@ -31,25 +35,87 @@ expectation.
3135

3236
## Guidance
3337

38+
The general flow of code generation for client libraries and supporting code in
39+
most supported languages is outlined below.
40+
41+
**Note:** Exceptions to this pattern are typically due to use of a unique stack
42+
e.g. Node.js use of `protobuf.js` and `grpc-node` which don't have code
43+
generation, or Python using a protobuf wrapper in `proto-plus-python`, but the
44+
general GAPIC flow remains the same.
45+
46+
```graphviz
47+
digraph {
48+
node [ style="filled,solid" shape=box fontname="Roboto" ];
49+
splines=ortho;
50+
nodesep=0.3;
51+
center=true;
52+
53+
proto [ label="API Protobuf\nDescriptors" shape=rectancle fillcolor=aliceblue ];
54+
55+
subgraph cluster_code_generators {
56+
rank = same;
57+
style = filled;
58+
fillcolor = lightgrey;
59+
node [ shape=oval ];
60+
61+
protobuf [ label="protobuf\ngenerator" fillcolor=deepskyblue3 ];
62+
grpc [ label="gRPC\ngenerator" fillcolor=gold3 ];
63+
gapic [ label="GAPIC\ngenerator" fillcolor=darkseagreen ];
64+
}
65+
66+
proto -> protobuf;
67+
proto -> grpc;
68+
proto -> gapic;
69+
70+
subgraph cluster_generated_code {
71+
rank = same;
72+
style = filled;
73+
fillcolor = lightgrey;
74+
node [ shape=rectangle ];
75+
76+
protobuf_output [ label="Message & Enum\nCode" fillcolor=deepskyblue3 ];
77+
grpc_output [ label="Server & Client\nStubs" fillcolor=gold3 ];
78+
gapic_output [ label="Google API\nClient" fillcolor=darkseagreen ];
79+
}
80+
81+
protobuf -> protobuf_output;
82+
grpc -> grpc_output;
83+
gapic -> gapic_output;
84+
85+
assembly [ label="Package\nassembly" shape=oval fillcolor=aliceblue ];
86+
87+
protobuf_output -> assembly
88+
grpc_output -> assembly
89+
gapic_output -> assembly
90+
91+
assembled_package [ label="Package of\ngenerated code" fillcolor=aliceblue ];
92+
93+
assembly -> assembled_package
94+
}
95+
```
96+
97+
The following sections focus on the "GAPIC generator" in the above diagram.
98+
3499
### Protobuf plugins
35100

36-
Code generators **must** be implemented as plugins to `protoc`, the protocol
37-
buffer compiler. The [plugin system][0] allows plugins to be written in any
38-
language, and plugins **should** ordinarily be written in the language being
39-
targeted, in order to take advantage of in-language tooling, and to ensure that
40-
experts in the target environment are able to meaningfully contribute.
101+
The protobuf compiler, `protoc`, supports a [plugin system][0] for code
102+
generation. The plugin system allows plugins to be written _in_ and _for_ any
103+
language.
104+
105+
Code generators **must** be implemented as `protoc` plugins. The following
106+
rules apply to the implementation of a client library generator as a `protoc`
107+
plugin:
41108

109+
- The plugin **should** be written in the language being targeted for
110+
generation.
42111
- `protoc` expects plugins to be an executable in `$PATH`, and named
43112
`protoc-gen-{plugin_name}`, corresponding to the `--{plugin_name}_out` option
44-
sent to the `protoc` executable.
45-
- For a plugin creating client libraries for a specific language, the option
46-
name **should** follow the convention `--{lang}_gapic_out` (meaning the
47-
corresponding plugin executable is named `protoc-gen-{lang}_gapic`).
48-
- Plugins **must** accept a serialized `CodeGeneratorRequest` object (defined
49-
in [`plugin.proto`][1]) on `stdin`; the bulk of this is a series of
50-
`FileDescriptorProto` messages (defined in [`descriptor.proto`][2]).
51-
- Plugins **must** emit a serialized `CodeGeneratorResponse` object (defined in
52-
[`plugin.proto`][1]) on `stdout`.
113+
sent to the `protoc` executable. As such:
114+
- the plugin executable **should** be named `protoc-gen-{lang}_gapic`
115+
- the plugin option **should** follow the convention `--{lang}_gapic_out`
116+
- The plugin **must not** leverage `protoc` "insertion points". Despite the
117+
`protoc` plugin documentation indicating the existence of insertion points,
118+
their use is unsupported and discouraged by the Protobuf team.
53119

54120
### CLI options
55121

@@ -59,6 +125,10 @@ options are required, `protoc` allows them to be passed as
59125
`--{plugin_name}_opt`, and the string provided here becomes set as the
60126
`parameter` string on the `CodeGeneratorRequest`.
61127

128+
**Important:** The `CodeGeneratorRequest.parameter` value is a comma-delimited
129+
string of _all_ associated plugin option values that appear at execution time.
130+
This means that commas cannot be used to delimit list-like plugin option values.
131+
62132
Code generators **must not** rely on environment variables for configuration.
63133

64134
## Expected behavior
@@ -68,6 +138,12 @@ client library generator (in other words: the libraries that the generators
68138
write). Client libraries **must** implement these concepts in order to be
69139
considered complete.
70140

141+
### Messages and Enums
142+
143+
Client library generators **should not** generate code for `message` or `enum`
144+
descriptors which are already generated by the Protobuf-provided code
145+
generators.
146+
71147
### Services and methods
72148

73149
Each of the `service` and `rpc` directives in the requested protos **must** be
@@ -96,10 +172,12 @@ methods for each RPC.
96172
- Finally, service classes **must** also accept credentials, which are used
97173
appropriately when requests are made. (Accepting a custom gRPC channel
98174
satisfies this requirement.)
175+
- Code generators **must not** generate client _stub_ classes, that would
176+
normally be generated by gRPC, in addition to client library classes.
99177

100178
### Long-running operations
101179

102-
<!-- TODO(b/126177694): Reference the LRO AIP once we have it. -->
180+
<!-- TODO(1145): Move to its own client library AIP. -->
103181

104182
An RPC is considered to be a "long-running" RPC if (and only if) the RPC's
105183
return type is [`google.longrunning.Operation`][3]. Any API which has one or
@@ -135,11 +213,16 @@ in the [`MethodDescriptorProto`][6] message using the `client_streaming` and
135213
`server_streaming` keys.
136214

137215
<!-- prettier-ignore-start -->
138-
[0]: https://developers.google.com/protocol-buffers/docs/reference/other
216+
[0]: https://protobuf.dev/reference/other
139217
[1]: https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/plugin.proto
140218
[2]: https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto
141219
[3]: https://github.com/googleapis/googleapis/blob/master/google/longrunning/operations.proto#L122
142220
[4]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto
143221
[5]: https://github.com/googleapis/googleapis/blob/master/google/longrunning/operations.proto#L222
144222
[6]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto#L269
145223
<!-- prettier-ignore-end -->
224+
225+
## Changelog
226+
227+
- **2023-06-22**: Added code gen diagram, message/enum guidance, and cleaned up
228+
plugin & option guidance.

0 commit comments

Comments
 (0)