pw_protobuf_compiler: Handle deps on nanopb.proto

- Add a pw_proto_library for nanopb.proto to the CMake build.
- Skip recompiling nanopb.proto when running protoc for Nanopb.
- Add the pw_protobuf_compiler Nanopb test to CMake.

Change-Id: I3469f35524b18efd3d484b17609e9de0f160e73a
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/46961
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Reviewed-by: Alexei Frolov <frolv@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 17ce39b..0b707ca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,6 +46,7 @@
 add_subdirectory(pw_minimal_cpp_stdlib EXCLUDE_FROM_ALL)
 add_subdirectory(pw_polyfill EXCLUDE_FROM_ALL)
 add_subdirectory(pw_protobuf EXCLUDE_FROM_ALL)
+add_subdirectory(pw_protobuf_compiler EXCLUDE_FROM_ALL)
 add_subdirectory(pw_preprocessor EXCLUDE_FROM_ALL)
 add_subdirectory(pw_random EXCLUDE_FROM_ALL)
 add_subdirectory(pw_result EXCLUDE_FROM_ALL)
diff --git a/pw_protobuf_compiler/CMakeLists.txt b/pw_protobuf_compiler/CMakeLists.txt
new file mode 100644
index 0000000..4b5a3b6
--- /dev/null
+++ b/pw_protobuf_compiler/CMakeLists.txt
@@ -0,0 +1,34 @@
+# Copyright 2021 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+include($ENV{PW_ROOT}/pw_protobuf_compiler/proto.cmake)
+
+if(NOT "${dir_pw_third_party_nanopb}" STREQUAL "")
+  pw_proto_library(pw_protobuf_compiler.nanopb_test_protos
+    SOURCES
+      pw_protobuf_compiler_nanopb_protos/nanopb_test.proto
+    DEPS
+      pw_third_party.nanopb.proto
+  )
+
+  pw_add_test(pw_protobuf_compiler.nanopb_test
+    SOURCES
+      nanopb_test.cc
+    DEPS
+      pw_protobuf_compiler.nanopb_test_protos.nanopb
+    GROUPS
+      pw_protobuf_compiler
+  )
+endif()
diff --git a/pw_protobuf_compiler/proto.cmake b/pw_protobuf_compiler/proto.cmake
index b7a4643..b7a466b 100644
--- a/pw_protobuf_compiler/proto.cmake
+++ b/pw_protobuf_compiler/proto.cmake
@@ -33,7 +33,7 @@
 #   PREFIX - prefix add to the proto files
 #   STRIP_PREFIX - prefix to remove from the proto files
 #   INPUTS - files to include along with the .proto files (such as Nanopb
-#       .options files
+#       .options files)
 #
 function(pw_proto_library NAME)
   cmake_parse_arguments(PARSE_ARGV 1 arg "" "STRIP_PREFIX;PREFIX"
@@ -236,28 +236,37 @@
     )
     set(generated_outputs $<TARGET_PROPERTY:pw_build.empty,SOURCES>)
   else()
-    _pw_generate_protos("${NAME}._generate.nanopb"
-        nanopb
-        "${dir_pw_third_party_nanopb}/generator/protoc-gen-nanopb"
-        ".pb.h;.pb.c"
-        "${INCLUDE_FILE}"
-        "${OUT_DIR}"
-        "${SOURCES}"
-        "${INPUTS}"
-        "${DEPS}"
-    )
+    # When compiling with the Nanopb plugin, the nanopb.proto file is already
+    # compiled internally, so skip recompiling it with protoc.
+    if("${SOURCES}" MATCHES "nanopb\\.proto")
+      add_custom_target("${NAME}._generate.nanopb")  # Nothing to do
+      add_library("${NAME}.nanopb" INTERFACE)
+      target_link_libraries("${NAME}.nanopb" INTERFACE pw_third_party.nanopb ${DEPS})
+    else()
+      _pw_generate_protos("${NAME}._generate.nanopb"
+          nanopb
+          "${dir_pw_third_party_nanopb}/generator/protoc-gen-nanopb"
+          ".pb.h;.pb.c"
+          "${INCLUDE_FILE}"
+          "${OUT_DIR}"
+          "${SOURCES}"
+          "${INPUTS}"
+          "${DEPS}"
+      )
+
+      # Create the library with the generated source files.
+      add_library("${NAME}.nanopb" EXCLUDE_FROM_ALL ${generated_outputs})
+      target_include_directories("${NAME}.nanopb" PUBLIC "${OUT_DIR}/nanopb")
+      target_link_libraries("${NAME}.nanopb" PUBLIC pw_third_party.nanopb ${DEPS})
+    endif()
+
+    add_dependencies("${NAME}.nanopb" "${NAME}._generate.nanopb")
 
     # Ensure that nanopb_pb2.py is generated to avoid race conditions.
     add_dependencies("${NAME}._generate.nanopb"
         pw_third_party.nanopb.generate_proto
     )
   endif()
-
-  # Create the library with the generated source files.
-  add_library("${NAME}.nanopb" EXCLUDE_FROM_ALL ${generated_outputs})
-  target_include_directories("${NAME}.nanopb" PUBLIC "${OUT_DIR}/nanopb")
-  target_link_libraries("${NAME}.nanopb" PUBLIC pw_third_party.nanopb ${DEPS})
-  add_dependencies("${NAME}.nanopb" "${NAME}._generate.nanopb")
 endfunction(_pw_nanopb_library)
 
 # Internal function that creates a nanopb_rpc library.
diff --git a/third_party/nanopb/CMakeLists.txt b/third_party/nanopb/CMakeLists.txt
index 3c2927b..5f2c9aa 100644
--- a/third_party/nanopb/CMakeLists.txt
+++ b/third_party/nanopb/CMakeLists.txt
@@ -12,6 +12,9 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+include($ENV{PW_ROOT}/pw_protobuf_compiler/proto.cmake)
+
 set(dir_pw_third_party_nanopb "" CACHE PATH "Path to the Nanopb installation.")
 option(pw_third_party_nanopb_ADD_SUBDIRECTORY
     "Whether to add the dir_pw_third_party_nanopb subdirectory" OFF)
@@ -32,6 +35,13 @@
     "${dir_pw_third_party_nanopb}"
 )
 
+pw_proto_library(pw_third_party.nanopb.proto
+  SOURCES
+    "${dir_pw_third_party_nanopb}/generator/proto/nanopb.proto"
+  STRIP_PREFIX
+    "${dir_pw_third_party_nanopb}/generator/proto"
+)
+
 # Generates nanopb_pb2.py, which is needed to compile protobufs with Nanopb.
 add_custom_command(
   COMMAND