# Bootstrap for the protoc plugin

## Installing protobuf (on Ubuntu)

You can use the Ubuntu package `protobuf-compiler`, but it's dated
Jul 31, 2018.  Instead, you can clone from
https://github.com/protocolbuffers/protobuf and build using the
instructions in `protobuf/src/README.md`. For the `./configure`
command you may wish to use `./configure --prefix=$HOME/.local` and
`make -j4` (where "4" should be replaced by the number of cores on
your machine).

There are some additional notes on this in the `Makefile`.

TODO: These notes reflect an older stage of the bootstrap process.
Both the notes and the Makefile need to be cleaned up, to remove
stuff that's no longer needed.

## Overview of the original bootstrap process

The original bootstrap was done by using `protoc --decode` to get the
".wiredump" files (in `gen_pb/google/protobuf/**`).
These were then parsed by a simple DCG in
`parse_descriptor_proto_dump.pl` to produce the ".proto.parse"
files. The term expansion logic is in `descriptor_proto_expand.pl`,
which was then copied to `protoc-gen-swipl`.  At this point,
`gen_pb/google/protobuf/descriptor_pb.pl` and
`gen_pb/google/protobuf/compiler/plugin_pb.pl` could be
generated, and the original bootstrap code no longer needed.

The tests are fairly minimal. For proper testing, see directory `interop`.


## descriptor.proto and friends

Naming conventions:

| x.proto      | protobuf definition: used as input to protoc                         |
| x.wire       | wire-format encoding of data (e.g., produced by SerializeToString()) |
| x.proto.wire | `protoc --descriptor_set_out=x.proto.wire`                  |
| x_pb2.py     | generated by protoc from x.proto (for Python)                        |
| x.pb.{h,cc}  | generated by protoc from x.proto (for C++)                           |
| x.wiredump   | readable form of x.wire, using `protoc --decode` and the appropriate .proto file |
| x.wirerawdump | readable from of x.wire, using `protoc --decode_raw` (no .proto file) |
| x.segment    | Prolog term that contains a segmentation of the data in a .wire file (see also x.wiredump) |
| descriptor.proto.parse | Output from `parse_descriptor_proto_dump.pl`, which is hand-edited into `descriptor_proto.pl` (`descriptor_proto/1`).  |

`plugin.proto` and `descriptor.proto`  encode all `.proto` files created by
the protobuf compiler (`protoc`). Their meta-data have been bootstrapped into
`gen_pb/plugin_pb.pl` and
`gen_pb/descriptor_pb.pl`.

* `descriptor.proto.wire` contains a protobuf encoding of
  `descriptor.proto`; it was generated by
  `protoc --descriptor_set_out=descriptor.proto.wire`
* `descriptor.proto.wiredump` is generated by `protoc
  --decode=FileDescriptorSet descriptor.proto.wire`
  It is included here, to avoid a submodule dependency on
  git@github.com:protocolbuffers/protobuf.git
* `parse_descriptor_proto_dump.pl` is used to process `descriptor.proto.wiredump`
  into a Prolog term.
* `descriptor_proto.pl` is the term created by `parse_descriptor_proto_dump.pl`,
  in the clause `descriptor_proto/1`.
* `descriptor.proto.segment` is the "golden" output from rule `descriptor.segment`.
  TODO: delete this file.

TODO: use `protobuf\_segment\_message/2` to process
`descriptor.proto.wire` and any other `descriptor\_set\_out`, and then
generate Prolog code for easy handling of protobufs.

## protoc plugin

We can create a plugin by having an executable named `protoc-gen-swipl`
that is in the `PATH`, which reads a `CodeGeneratorRequest` from stdin
(defined in `src/protobuf/src/google/protobuf/compiler/plugin.proto`)
and outputs to stdout a `CodeGeneratorResponse` ... to get this
plugin, use `protoc --swipl_out=DIR`.

If you make an incompatible change to `protoc-gen-swipl`, you should
increment the version and also `protobufs:verify_version/0`.  (Also
`descriptor_proto.pl`, which is mostly obsolete.)

See also
[https://chromium.googlesource.com/external/github.com/protocolbuffers/protobuf/+/refs/heads/master/docs/implementing_proto3_presence.md](How To Implement Field Presence for Proto3).
