|
| 1 | +# C++ GAPIC Generator Design Review # |
| 2 | + |
| 3 | +*Authors: michaelbausor@google.com, vam@google.com, dovs@google.com* |
| 4 | + |
| 5 | +Objective |
| 6 | +========= |
| 7 | + |
| 8 | +Describe the design of a C++ client library generator. This document covers the design of the **generator**; the [generated surface](SURFACE.md) and GAX-owned primitives are discussed in other docs. |
| 9 | + |
| 10 | + |
| 11 | +Compatibility |
| 12 | +------------- |
| 13 | + |
| 14 | +We will support the google-cloud-cpp repository as our first and primary customer. Because we intend to support users building and running the |
| 15 | +GAPIC generator themselves (possibly as part of compiling a project that consumes the generated surface), we will aim to support the [*same set*](https://github.com/googleapis/google-cloud-cpp/tree/master#requirements) of compilers, build tools, dependency versions, and platforms with our generator as are supported by google-cloud-cpp (and by our generated code). |
| 16 | + |
| 17 | +The generator will **\*not\* throw exceptions**, making it compatible with code that is compiled without exception support. |
| 18 | + |
| 19 | +Dependencies |
| 20 | +------------ |
| 21 | + |
| 22 | +We will attempt to minimize the number of external dependencies taken by the generator. Because the generator will implement the protobuf [*CodeGenerator*](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/compiler/code_generator.h#L66) interface, we have a dependency on protobuf. We will also take an \*internal only\* dependency on the [*abseil*](https://abseil.io/) library. |
| 23 | + |
| 24 | +Versioning and Publishing |
| 25 | +------------------------- |
| 26 | + |
| 27 | +The GAPIC generator will follow semantic versioning. Once the generator is declared GA, we are committing to not breaking users of the generator, **and** not making any breaking changes in the generated surface. We will use Github releases to tag and publish generator versions. Initially we will not support any C++ package managers. However, we will facilitate community contributions so that package manager support is possible in future. |
| 28 | + |
| 29 | +Building the Generator |
| 30 | +---------------------- |
| 31 | + |
| 32 | +The generator will be buildable via bazel and cmake, similar to the existing google-cloud-cpp repository. We will use bazel as the source of truth, and generate cmake files from bazel. Example of building using bazel: |
| 33 | + |
| 34 | +```bash |
| 35 | +$ git clone https://github.com/googleapis/gapic-generator-cpp |
| 36 | +$ cd gapic-generator-cpp |
| 37 | +$ bazel build ... |
| 38 | +$ bazel test ... |
| 39 | +``` |
| 40 | + |
| 41 | +Consuming the Generator |
| 42 | +----------------------- |
| 43 | + |
| 44 | +### Via bazel |
| 45 | + |
| 46 | +We will provide a `cpp_gapic_library` build rule that will depend on the annotated proto files and output a generated gapic library. This will be similar to the rule that exists for gapic-generator in Java [*here*](https://github.com/googleapis/gapic-generator/blob/master/rules_gapic/java/java_gapic.bzl#L139) or Go [*here*](https://github.com/googleapis/gapic-generator/blob/master/rules_gapic/go/go_gapic.bzl#L98). |
| 47 | +See [*go/gapic-bazel-extensions*](https://goto.google.com/gapic-bazel-extensions) for more detail about exposing generation (as well as testing generated libraries and generating packaging) as bazel rules. |
| 48 | + |
| 49 | +### Via protoc plugin |
| 50 | + |
| 51 | +Users can call protoc directly and specify a built gapic-generator-cpp plugin binary. We will defer publishing built binaries that users can download until the generator reaches a post-alpha state, at which time we will re-review. |
| 52 | + |
| 53 | +Implementation |
| 54 | +-------------- |
| 55 | + |
| 56 | +The GAPIC generator will implement the protobuf [*CodeGenerator*](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/compiler/code_generator.h#L66) interface. Where possible, all logic will be implemented as part of the [*Generate*](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/compiler/code_generator.h#L82) method. |
| 57 | + |
| 58 | +The only exception to this is processing metadata annotation information, which may be stored in another protobuf file from the one currently being generated. This will be preprocessed in the [*GenerateAll*](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/compiler/code_generator.h#L98) method, and made available to the Generate method. If metadata annotation information is inconsistent across files, the generator will exit with an error. |
| 59 | + |
| 60 | +### Generate Method |
| 61 | + |
| 62 | +The generator will make use of the protobuf [*io::Printer*](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/io/printer.h#L181) object to write files. The printer provides simple templating functionality by accepting a `std::string` template and a set of variables, performs variable substitution on the template, and outputs the result. Unlike more advanced templating languages such as Jinja2, it does not support complex [*control structures*](http://jinja.pocoo.org/docs/2.10/templates/#list-of-control-structures) such as looping. Where loops are necessary (such as over the RPCs in a service) they must be implemented in code. This makes separating the templates from the data model much more difficult than in (for example) gapic-generator-python. |
| 63 | + |
| 64 | +We extract information from the file descriptor and store it in a `std::map<std::string, std::string>` object suitable for use with `io::Printer`. This map is mutable and is passed to methods that iterate over elements of the descriptor, update the map with data from the descriptor, and render templates. |
| 65 | + |
| 66 | +Sample Generation |
| 67 | +----------------- |
| 68 | + |
| 69 | +The generator will support in-code method samples as a GA requirement, but we will delay their implementation until post-alpha. The generator will also support standalone samples, implementation timeline TBD but likely prioritized after in-code samples. We will work with the Samplegen team to ensure we can support both use cases, and cover the full range of sample specification. |
| 70 | + |
| 71 | +The google-cloud-cpp repository contains [*standalone samples*](https://github.com/googleapis/google-cloud-cpp/tree/master/google/cloud/bigtable/examples) that are compilable and testable, and that also contain annotations that allow them to be [*linked in to documentation*](https://googleapis.github.io/google-cloud-cpp/0.6.0/bigtable/bigtable-hello-world.html). We can follow this model to support documentation and testing of samples. |
| 72 | + |
| 73 | +Testing and CI |
| 74 | +-------------- |
| 75 | + |
| 76 | +We will use Kokoro as our CI system. We will integrate with [*GAPIC Showcase*](https://github.com/googleapis/gapic-showcase) to test feature coverage. For example, to use GAPIC Showcase to test paginated methods, we can generate a Showcase API Echo service client and call the [*PagedExpand*](https://github.com/googleapis/gapic-showcase/blob/master/schema/echo.proto#L82) method to verify that our pagination code works as expected. Calls will be made against a local in-memory Showcase API server. |
| 77 | + |
| 78 | +Documentation |
| 79 | +------------- |
| 80 | + |
| 81 | +We will use doxygen, [*similar to google-cloud-cpp*](https://googleapis.github.io/google-cloud-cpp/0.6.0/bigtable/index.html), hosted at https://googleapis.github.io/gapic-generator-cpp. |
| 82 | + |
| 83 | +References |
| 84 | +========== |
| 85 | +- [*https://github.com/googleapis/google-cloud-cpp*](https://github.com/googleapis/google-cloud-cpp) |
0 commit comments