Split proto zero/lite/full generation

Different targets require different proto variants. Specifically:
- Writers of trace data (e.g., the code that reads the raw ftrace
  buffer and generates proto) require protozero, for fast writing.
- Readers of trace data (e.g., the tracing service) require
  protobuf lite, for safe decoding.
- Tests occasionally require protobuf full, for introspection.

This CL separates the output directory of these proto targets into
out/gen/protos_{zero,lite,full} so different targets can include
different proto variants.

Also it makes it so that the protozero_library doesn't implicitly
generate also the lite .pb.{cc,h} protos, in order to avoid mixing
different proto variants in different folders.

Furthermore, from now on, proto_out_dir must be explicitly set to
either "protos_full", "protos_lite" or "protos_zero" for each
proto target.

Change-Id: Ieb51f36bb3f7c42b6ebc1f2feb29c6247de1e070
diff --git a/BUILD.gn b/BUILD.gn
index cb92679..280f760 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -16,11 +16,8 @@
   testonly = true  # allow to build also test targets
   deps = [
     ":tests",
-    "//buildtools:protobuf_lite",
-    "//buildtools:protoc($host_toolchain)",
     "//ftrace_reader:ftrace_reader_demo",
     "//ipc/src/protoc_plugin:ipc_plugin($host_toolchain)",
-    "//protos/ftrace",
     "//protozero/src/protoc_plugin($host_toolchain)",
     "//tools/ftrace_proto_gen:ftrace_proto_gen",
   ]
diff --git a/build/proto_library.gni b/build/proto_library.gni
index 82964c7..5317379 100644
--- a/build/proto_library.gni
+++ b/build/proto_library.gni
@@ -21,7 +21,12 @@
   if (defined(invoker.proto_in_dir)) {
     proto_in_dir = invoker.proto_in_dir
   }
-  proto_out_dir = "//"
+  assert(defined(invoker.proto_out_dir),
+         "proto_out_dir must be explicitly defined")
+  proto_out_dir = invoker.proto_out_dir
+  assert(proto_out_dir == "protos_zero" || proto_out_dir == "protos_lite" ||
+             proto_out_dir == "protos_full",
+         "proto_out must be either 'proto_zero', 'proto_lite' or 'proto_full'")
 
   # If false will not generate the default .pb.{cc,h} files. Used for custom
   # codegen plugins.
@@ -171,9 +176,18 @@
       ":$config_name",
     ]
 
-    deps = [
-      "//buildtools:protobuf_lite",
-    ]
+    # Use protobuf_full only for tests.
+    if (defined(invoker.use_protobuf_full) &&
+        invoker.use_protobuf_full == true) {
+      deps = [
+        "//buildtools:protobuf_full",
+      ]
+    } else {
+      deps = [
+        "//buildtools:protobuf_lite",
+      ]
+    }
+
     deps += [ ":$action_name" ]
     if (defined(invoker.deps)) {
       deps += invoker.deps
diff --git a/ftrace_reader/BUILD.gn b/ftrace_reader/BUILD.gn
index 42108e1..faf25cb 100644
--- a/ftrace_reader/BUILD.gn
+++ b/ftrace_reader/BUILD.gn
@@ -23,8 +23,7 @@
     "//buildtools:gmock",
     "//buildtools:gtest",
     "//buildtools:gtest_main",
-    "//buildtools:protobuf_full",
-    "//protos/ftrace:ftrace_full_protos",
+    "//protos/ftrace:full",
   ]
   sources = [
     "src/cpu_reader_unittest.cc",
@@ -47,7 +46,7 @@
     "//buildtools:gtest",
     "//buildtools:gtest_main",
     "//buildtools:protobuf_full",
-    "//protos/ftrace:ftrace_full_protos",
+    "//protos/ftrace:full",
   ]
   sources = [
     "src/end_to_end_integrationtest.cc",
@@ -71,12 +70,9 @@
     ":ftrace_reader_config",
     "//buildtools:googletest_prod_config",
   ]
-  deps += [
-    "//base",
-    "//protozero",
-  ]
+  deps += [ "//base" ]
   public_deps = [
-    "//protos/ftrace",
+    "//protos/ftrace:zero",
   ]
   sources = [
     "include/ftrace_reader/format_parser.h",
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn
index ced4f07..3bfe9e8 100644
--- a/ipc/BUILD.gn
+++ b/ipc/BUILD.gn
@@ -74,6 +74,7 @@
     "src/wire_protocol.proto",
   ]
   include_dirs = [ "include" ]
+  proto_out_dir = "protos_lite"
 }
 
 ipc_library("test_messages") {
diff --git a/ipc/ipc_library.gni b/ipc/ipc_library.gni
index a91c977..f43f461 100644
--- a/ipc/ipc_library.gni
+++ b/ipc/ipc_library.gni
@@ -23,6 +23,7 @@
     deps = [
       "//ipc",
     ]
+    proto_out_dir = "protos_lite"
     forward_variables_from(invoker,
                            [
                              "defines",
diff --git a/protos/BUILD.gn b/protos/BUILD.gn
index 87b4ac3..1db4cb5 100644
--- a/protos/BUILD.gn
+++ b/protos/BUILD.gn
@@ -17,20 +17,20 @@
 
 proto_sources = [ "trace_packet.proto" ]
 
+# Protozero generated stubs, for writers.
 protozero_library("zero") {
-  generate_cc = false
   deps = [
-    "ftrace",
+    "ftrace:zero",
   ]
   sources = proto_sources
+  proto_out_dir = "protos_zero"
 }
 
-# TODO: we don't really want the _full version but just the _lite. However
-# this requires to have 3 targets (zero, full and lite) for ftrace. Need to
-# solve that problem first.
-proto_library("full") {
+# Protobuf Lite stubs, for readers.
+proto_library("lite") {
   deps = [
-    "ftrace:ftrace_full_protos",
+    "ftrace:lite",
   ]
   sources = proto_sources
+  proto_out_dir = "protos_lite"
 }
diff --git a/protos/ftrace/BUILD.gn b/protos/ftrace/BUILD.gn
index 43791f3..eae217d 100644
--- a/protos/ftrace/BUILD.gn
+++ b/protos/ftrace/BUILD.gn
@@ -18,7 +18,7 @@
 # Create a copy of all the protos listed in all_protos.gni with the
 # "option optimize_for = LITE_RUNTIME" bit removed so we can generate
 # full proto .h/.cc files.
-full_protos_base_dir = "${root_gen_dir}/full_protos"
+full_protos_base_dir = "${root_gen_dir}/protos_full"
 full_protos_target_dir =
     "$full_protos_base_dir/" + rebase_path(target_gen_dir, root_gen_dir)
 
@@ -40,19 +40,26 @@
   ]
 }
 
-proto_library("ftrace_full_protos") {
+proto_library("full") {
+  testonly = true
   deps = [
     ":generate_full_protos",
   ]
   sources = []
-
+  use_protobuf_full = true
+  proto_out_dir = "protos_full"
   proto_in_dir = full_protos_base_dir
   foreach(proto, ftrace_proto_names) {
     sources += [ "$full_protos_target_dir/$proto" ]
   }
 }
 
-protozero_library("ftrace") {
-  generate_cc = false
+proto_library("lite") {
   sources = ftrace_proto_names
+  proto_out_dir = "protos_lite"
+}
+
+protozero_library("zero") {
+  sources = ftrace_proto_names
+  proto_out_dir = "protos_zero"
 }
diff --git a/protozero/BUILD.gn b/protozero/BUILD.gn
index 0c6cf59..8bd3189 100644
--- a/protozero/BUILD.gn
+++ b/protozero/BUILD.gn
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("//build/proto_library.gni")
 import("protozero_library.gni")
 
 config("protozero_config") {
@@ -40,7 +41,8 @@
   testonly = true
   deps += [
     ":protozero",
-    ":testing_messages",
+    ":testing_messages_lite",
+    ":testing_messages_zero",
     "//base",
     "//buildtools:gmock",
     "//buildtools:gtest",
@@ -57,12 +59,22 @@
 }
 
 # Generates both xxx.pbzero.h and xxx.pb.h (official proto).
-protozero_library("testing_messages") {
-  sources = [
-    "src/test/example_proto/library.proto",
-    "src/test/example_proto/library_internals/galaxies.proto",
-    "src/test/example_proto/test_messages.proto",
-    "src/test/example_proto/upper_import.proto",
-  ]
+
+testing_proto_sources = [
+  "src/test/example_proto/library.proto",
+  "src/test/example_proto/library_internals/galaxies.proto",
+  "src/test/example_proto/test_messages.proto",
+  "src/test/example_proto/upper_import.proto",
+]
+
+protozero_library("testing_messages_zero") {
   include_dirs = [ "include" ]
+  sources = testing_proto_sources
+  proto_out_dir = "protos_zero"
+}
+
+proto_library("testing_messages_lite") {
+  include_dirs = [ "include" ]
+  sources = testing_proto_sources
+  proto_out_dir = "protos_lite"
 }
diff --git a/protozero/protozero_library.gni b/protozero/protozero_library.gni
index 8c8b04a..f65e447 100644
--- a/protozero/protozero_library.gni
+++ b/protozero/protozero_library.gni
@@ -20,15 +20,20 @@
 # .pb.{cc,h} of the official proto library.
 template("protozero_library") {
   proto_library(target_name) {
+    generate_cc = false
     generator_plugin_label = "//protozero/src/protoc_plugin"
     generator_plugin_suffix = ".pbzero"
     generator_plugin_options = "wrapper_namespace=pbzero"
     public_configs = [ "//protozero:protozero_config" ]
+    deps = []
+    if (defined(invoker.deps)) {
+      deps = invoker.deps
+    }
+    deps += [ "//protozero" ]
     forward_variables_from(invoker,
                            [
                              "defines",
-                             "deps",
-                             "generate_cc",
+                             "generator_plugin_options",
                              "include_dirs",
                              "proto_in_dir",
                              "proto_out_dir",
diff --git a/protozero/src/protoc_plugin/protozero_generator.cc b/protozero/src/protoc_plugin/protozero_generator.cc
index a511664..a3f4766 100644
--- a/protozero/src/protoc_plugin/protozero_generator.cc
+++ b/protozero/src/protoc_plugin/protozero_generator.cc
@@ -222,7 +222,7 @@
     package_ = source_->package();
     namespaces_ = Split(package_, ".");
     if (!wrapper_namespace_.empty())
-      namespaces_.insert(namespaces_.begin(), wrapper_namespace_);
+      namespaces_.push_back(wrapper_namespace_);
 
     full_namespace_prefix_ = "::";
     for (const std::string& ns : namespaces_)
diff --git a/protozero/src/test/protozero_conformance_unittest.cc b/protozero/src/test/protozero_conformance_unittest.cc
index 2e9b88e..8dc4c1d 100644
--- a/protozero/src/test/protozero_conformance_unittest.cc
+++ b/protozero/src/test/protozero_conformance_unittest.cc
@@ -27,7 +27,7 @@
 #include "protozero/src/test/example_proto/test_messages.pb.h"
 #include "protozero/src/test/example_proto/test_messages.pbzero.h"
 
-namespace pbtest = pbzero::foo::bar;  // Generated by the protozero plugin.
+namespace pbtest = foo::bar::pbzero;  // Generated by the protozero plugin.
 namespace pbgold = foo::bar;  // Generated by the official protobuf compiler.
 
 namespace protozero {