Skip to content

Commit

Permalink
Add bazel support for examples.
Browse files Browse the repository at this point in the history
The example utilizes native bazel rules (proto_library, cc_proto_library,
java_proto_library, java_lite_proto_library) to show how easy it is to
build protobuf with bazel's native support. It also makes use of well
known types which was not possible until the latest bazel 0.5.4 release
and protocolbuffers#3594 .
  • Loading branch information
xfxyjwf committed Sep 8, 2017
1 parent 2ad5c0a commit 74bf45f
Show file tree
Hide file tree
Showing 10 changed files with 298 additions and 66 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,19 @@ how to install protobuf runtime for that specific language:
| PHP | [php](php) |
| Dart | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) |

Quick Start
-----------

Usage
-----
The best way to learn how to use protobuf is to follow the tutorials in our
developer guide:

https://developers.google.com/protocol-buffers/docs/tutorials

If you want to learn from code examples, take a look at the examples in the
[examples](examples) directory.

Documentation
-------------

The complete documentation for Protocol Buffers is available via the
web at:
Expand Down
101 changes: 101 additions & 0 deletions examples/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# This BUILD file shows how to use protobuf with bazel. Before you can use
# proto_library/<lang>_proto_library rules in a BUILD file, you need to
# include protobuf repo as remote repositories in your WORKSPACE file. See
# the WORKSPACE file in the same directory with this BUILD file for an
# example.

# For each .proto file, a proto_library target should be defined. This target
# is not bound to any particular language. Instead, it defines the dependency
# graph of the .proto files (i.e., proto imports) and serves as the provider
# of .proto source files to the protocol compiler.
#
# Remote repository "com_google_protobuf" must be defined to use this rule.
proto_library(
name = "addressbook_proto",
srcs = ["addressbook.proto"],
deps = ["@com_google_protobuf//:timestamp_proto"],
)

# The cc_proto_library rule generates C++ code for a proto_library rule. It
# must have exactly one proto_library dependency. If you want to use multiple
# proto_library targets, create a separate cc_proto_library target for each
# of them.
#
# Remote repository "com_google_protobuf_cc" must be defined to use this rule.
cc_proto_library(
name = "addressbook_cc_proto",
deps = [":addressbook_proto"],
)

# cc_library/cc_binary targets can depend on cc_proto_library targets.
cc_binary(
name = "add_person_cpp",
srcs = ["add_person.cc"],
deps = [":addressbook_cc_proto"],
)

cc_binary(
name = "list_people_cpp",
srcs = ["list_people.cc"],
deps = [":addressbook_cc_proto"],
)

# Similar to cc_proto_library but for Java.
#
# Remote repository "com_google_protobuf_java" must be defined to use this rule.
java_proto_library(
name = "addressbook_java_proto",
deps = [":addressbook_proto"],
)

java_binary(
name = "add_person_java",
srcs = ["AddPerson.java"],
main_class = "AddPerson",
deps = [":addressbook_java_proto"],
)

java_binary(
name = "list_people_java",
srcs = ["ListPeople.java"],
main_class = "ListPeople",
deps = [":addressbook_java_proto"],
)

# Java lite.
#
# Remote repository "com_google_protobuf_javalite" must be defined to use this
# rule.
java_lite_proto_library(
name = "addressbook_java_lite_proto",
deps = [":addressbook_proto"],
)

# Java lite API is a subset of the regular Java API so if you only uses this
# subset in your code, you can actually compile your code against both (i.e.,
# share code between server build and Android build).
#
# The lite version has a smaller code size, and you can see that by comparing
# the resulted .jar file:
#
# $ bazel build :add_person_java_deploy.jar :add_person_java_lite_deploy.jar
# $ ls -l bazel-bin/*_deploy.jar
# -r-xr-xr-x 1 xiaofeng eng 1230797 Sep 8 12:24 bazel-bin/add_person_java_deploy.jar
# -r-xr-xr-x 1 xiaofeng eng 236166 Sep 8 12:24 bazel-bin/add_person_java_lite_deploy.jar
#
# In the above example, the lite .jar file is 6 times smaller. With proper
# proguard inlining/stripping, the difference can be much more larger than
# that.
java_binary(
name = "add_person_java_lite",
srcs = ["AddPerson.java"],
main_class = "AddPerson",
deps = [":addressbook_java_lite_proto"],
)

java_binary(
name = "list_people_java_lite",
srcs = ["ListPeople.java"],
main_class = "ListPeople",
deps = [":addressbook_java_lite_proto"],
)
3 changes: 3 additions & 0 deletions examples/ListPeople.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ static void Print(AddressBook addressBook) {
case WORK:
System.out.print(" Work phone #: ");
break;
default:
System.out.println(" Unknown phone #: ");
break;
}
System.out.println(phoneNumber.getNumber());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ list_people_gotest: list_people.go list_people_go
go test list_people.go list_people_test.go

javac_middleman: AddPerson.java ListPeople.java protoc_middleman
javac -cp ../java/core/target/*.jar AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java
javac -cp $$CLASSPATH AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java
@touch javac_middleman

add_person_java: javac_middleman
Expand Down
124 changes: 124 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Protocol Buffers - Code Example

This directory contains example code that uses Protocol Buffers to manage an
address book. Two programs are provided for each supported language. The
add_person example adds a new person to an address book, prompting the user to
input the person's information. The list_people example lists people already in
the address book. The examples use the exact same format in all three languages,
so you can, for example, use add_person_java to create an address book and then
use list_people_python to read it.

These examples are part of the Protocol Buffers tutorial, located at:
https://developers.google.com/protocol-buffers/docs/tutorials

## Build the example using bazel

The example requires bazel 0.5.4 or newer to build. You can download/install
the latest version of bazel from bazel's release page:

https://github.com/bazelbuild/bazel/releases

Once you have bazel installed, simply run the following command in this examples
directory to build the code:

$ bazel build :all

Then you can run the built binary:

$ bazel-bin/add_person_cpp addressbook.data

To use protobuf in your own bazel project, please follow instructions in the
[BUILD](BUILD) file and [WORKSPACE](WORKSPACE) file.

## Build the example using make

You must install the protobuf package before you can build it using make. The
minimum requirement is to install protocol compiler (i.e., the protoc binary)
and the protobuf runtime for the language you want to build.

You can simply run "make" to build the example for all languages (except for
Go). However, since different language has different installation requirement,
it will likely fail. It's better to follow individual instrutions below to
build only the language you are interested in.

### C++

You can follow instructions in [../src/README.md](../src/README.md) to install
protoc and protobuf C++ runtime from source.

Then run "make cpp" in this examples directory to build the C++ example. It
will create two executables: add_person_cpp and list_people_cpp. These programs
simply take an address book file as their parameter. The add_person_cpp
programs will create the file if it doesn't already exist.

To run the examples:

$ ./add_person_cpp addressbook.data
$ ./list_people_cpp addressbook.data

Note that on some platforms you may have to edit the Makefile and remove
"-lpthread" from the linker commands (perhaps replacing it with something else).
We didn't do this automatically because we wanted to keep the example simple.

### Python

Follow instructions in [../README.md](../README.md) to install protoc and then
follow [../python/README.md](../python/README.md) to install protobuf python
runtime from source. You can also install python runtime using pip:

$ pip install protobuf

Make sure the runtime version is the same as protoc binary, or it may not work.

After you have install both protoc and python runtime, run "make python" to
build two executables (shell scripts actually): add_person_python and
list_people_python. They work the same way as the C++ executables.

### Java

Follow instructions in [../README.md](../README.md) to install protoc and then
download protobuf Java runtime .jar file from maven:

https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java

Then run the following:

$ export CLASSPATH=/path/to/protobuf-java-[version].jar
$ make java

This will create the add_person_java/list_people_java executables (shell
scripts) and can be used to create/display an address book data file.

### Go

The Go example requires a plugin to the protocol buffer compiler, so it is not
build with all the other examples. See:

https://github.com/golang/protobuf

for more information about Go protocol buffer support.

First, install the Protocol Buffers compiler (protoc).

Then, install the Go Protocol Buffers plugin ($GOPATH/bin must be in your $PATH
for protoc to find it):

go get github.com/golang/protobuf/protoc-gen-go

Build the Go samples in this directory with "make go". This creates the
following executable files in the current directory:

add_person_go list_people_go

To run the example:

./add_person_go addressbook.data

to add a person to the protocol buffer encoded file addressbook.data. The file
is created if it does not exist. To view the data, run:

./list_people_go addressbook.data

Observe that the C++, Python, and Java examples in this directory run in a
similar way and can view/modify files created by the Go example and vice
versa.
61 changes: 0 additions & 61 deletions examples/README.txt

This file was deleted.

33 changes: 33 additions & 0 deletions examples/WORKSPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This com_google_protobuf repository is required for proto_library rule.
# It provides the protocol compiler binary (i.e., protoc).
http_archive(
name = "com_google_protobuf",
strip_prefix = "protobuf-master",
urls = ["https://github.com/google/protobuf/archive/master.zip"],
)

# This com_google_protobuf_cc repository is required for cc_proto_library
# rule. It provides protobuf C++ runtime. Note that it actually is the same
# repo as com_google_protobuf but has to be given a different name as
# required by bazel.
http_archive(
name = "com_google_protobuf_cc",
strip_prefix = "protobuf-master",
urls = ["https://github.com/google/protobuf/archive/master.zip"],
)

# Similar to com_google_protobuf_cc but for Java (i.e., java_proto_library).
http_archive(
name = "com_google_protobuf_java",
strip_prefix = "protobuf-master",
urls = ["https://github.com/google/protobuf/archive/master.zip"],
)

# Similar to com_google_protobuf_cc but for Java lite. If you are building
# for Android, the lite version should be prefered because it has a much
# smaller code size.
http_archive(
name = "com_google_protobuf_javalite",
strip_prefix = "protobuf-javalite",
urls = ["https://github.com/google/protobuf/archive/javalite.zip"],
)
9 changes: 8 additions & 1 deletion examples/add_person.cc
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
// See README.txt for information and build instructions.

#include <iostream>
#include <ctime>
#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>

#include "addressbook.pb.h"

using namespace std;

using google::protobuf::util::TimeUtil;

// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
cout << "Enter person ID number: ";
Expand Down Expand Up @@ -48,6 +54,7 @@ void PromptForAddress(tutorial::Person* person) {
cout << "Unknown phone type. Using default." << endl;
}
}
*person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
}

// Main function: Reads the entire address book from a file,
Expand Down
Loading

0 comments on commit 74bf45f

Please sign in to comment.