This package defines tools for working with protocol buffers version 3 in Haskell.
This library provides a higher-level API to
the proto3-wire
library that supports:
- Type classes for encoding and decoding messages, and instances for all wire formats identified in the specification
- A higher-level approach to encoding and decoding, based on
GHC.Generics
- A way of creating
.proto
files from Haskell types.
See the Proto3.Suite.Tutorial
module for more details.
We test inter-language interop using protoc's built-in Python code generation. In order to successfully run these tests, you'll need to install the google protobuf Python library. It's best to create a virtualenv and then use pip to install the right version (virtualenv is a python utility which can be installed with pip).
$ virtualenv pyenv
$ source pyenv/bin/activate
$ pip install protobuf==3.0.0b3 # Need the latest version for the newest protoc
brew install python
may also work.
Alternately, the nix-shell
environment provides an incremental build
environment (but see below for testing). From the root of this repository:
$ nix-shell release.nix -A proto3-suite-no-tests.env
[nix-shell]$ cabal configure
[nix-shell]$ cabal build
Once your source code compiles and you want to test, do this instead:
$ nix-shell release.nix -A proto3-suite.env
[nix-shell]$ cabal configure --enable-tests
[nix-shell]$ cabal build
[nix-shell]$ cabal test
The above steps will work only if your Haskell source compiles, because
some of the tests require the current compile-proto-file
executable.
Run the following commmand from the root of this repository to install
the compile-proto-file
and canonicalize-proto-file
executables:
$ nix-env --install --attr proto3-suite -f release.nix
To remove it from your nix user profile path, use:
$ nix-env --uninstall proto3-suite
$ compile-proto-file --help
Compiles a .proto file to a Haskell module
Usage: compile-proto-file --out FILEPATH [--includeDir FILEPATH]...
--proto FILEPATH
Available options:
-h,--help Show this help text
--out FILEPATH Output directory path where generated Haskell modules
will be written (directory is created if it does not
exist; note that files in the output directory may be
overwritten!)
--includeDir FILEPATH... Path to search for included .proto files (can be
repeated, and paths will be searched in order; the
current directory is used if this option is not
provided)
--proto FILEPATH Path to input .proto file
compile-proto-file
bases the name (and hence, path) of the generated Haskell
module on the filename of the input .proto
file, relative to the include
path where it was found, snake-to-cameling as needed.
As an example, let's assume this is our current directory structure before performing any code generation:
.
├── my_protos
│ └── my_package.proto
└── other_protos
└── google
└── protobuf
├── duration.proto
└── timestamp.proto
where my_package.proto
is:
syntax = "proto3";
package some_package_name;
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
message MyMessage {
Timestamp timestamp = 1;
Duration duration = 2;
}
Then, after the following commands:
$ compile-proto-file --out gen --includeDir my_protos --includeDir other_protos --proto google/protobuf/duration.proto
$ compile-proto-file --out gen --includeDir my_protos --includeDir other_protos --proto google/protobuf/timestamp.proto
$ compile-proto-file --out gen --includeDir my_protos --includeDir other_protos --proto my_package.proto
the directory tree will look like this:
.
├── gen
│ ├── Google
│ │ └── Protobuf
│ │ ├── Duration.hs
│ │ └── Timestamp.hs
│ └── MyPackage.hs
├── my_protos
│ └── my_package.proto
└── other_protos
└── google
└── protobuf
├── duration.proto
└── timestamp.proto
Finally, note that delimiting .
characters in the input .proto
basename are
treated as /
characters, so the input filenames
google.protobuf.timestamp.proto
and google/protobuf/timestamp.proto
would
produce the same generated Haskell module name and path.
This is essentially the same module naming scheme as the protoc
Python plugin
uses when compiling .proto
files.