CMake build: Change how third party libraries are included

- Always use dir_pw_third_party_nanopb as a path.
- Improve error messages when building Nanopb protos without
  dir_pw_third_party_nanopb set.
- Specify python3 instead of python in case the build isn't run in a
  Python 3 virtual environment.

Change-Id: Id8ca6f7f944348803c0275883fc7125c465235fd
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/38400
Reviewed-by: Keir Mierle <keir@google.com>
Reviewed-by: Alexei Frolov <frolv@google.com>
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
diff --git a/pw_build/docs.rst b/pw_build/docs.rst
index 96e7a37..6fff0e4 100644
--- a/pw_build/docs.rst
+++ b/pw_build/docs.rst
@@ -461,17 +461,14 @@
 ---------------------
 The CMake build includes third-party libraries similarly to the GN build. A
 ``dir_pw_third_party_<library>`` cache variable is defined for each third-party
-dependency. This variable can have one of three values:
+dependency. The variable must be set to the absolute path of the library in
+order to use it. If the variable is empty
+(``if("${dir_pw_third_party_<library>}" STREQUAL "")``), the dependency is not
+available.
 
-* ``""`` (empty) -- the dependency is not available
-* ``PRESENT`` -- the dependency is available and is already included in the
-  build
-* ``</path/to/the/dependency>`` -- the dependency is available and will be
-  automatically imported from this path using ``add_subdirectory``.
-
-If the variable is empty (``if("${dir_pw_third_party_<library>}" STREQUAL
-"")``), the dependency is not available. Otherwise, it is available and
-libraries declared by it can be referenced.
+Third-party dependencies are not automatically added to the build. They can be
+manually added with ``add_subdirectory`` or by setting the
+``pw_third_party_<library>_ADD_SUBDIRECTORY`` option to ``ON``.
 
 Third party variables are set like any other cache global variable in CMake. It
 is recommended to set these in one of the following ways:
@@ -481,7 +478,7 @@
 
   .. code-block:: cmake
 
-    set(dir_pw_third_party_nanopb PRESENT CACHE STRING "" FORCE)
+    set(dir_pw_third_party_nanopb ${CMAKE_CURRENT_SOURCE_DIR}/external/nanopb CACHE PATH "" FORCE)
 
 * Set the variable at the command line with the ``-D`` option.
 
diff --git a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
index a0ec61f..989711c 100755
--- a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
+++ b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
@@ -200,6 +200,7 @@
                 f'-DCMAKE_TOOLCHAIN_FILE={toolchain}',
                 '-DCMAKE_EXPORT_COMPILE_COMMANDS=1',
                 f'-Ddir_pw_third_party_nanopb={ctx.package_root / "nanopb"}',
+                '-Dpw_third_party_nanopb_ADD_SUBDIRECTORY=ON',
                 env=build.env_with_clang_vars())
 
 
diff --git a/pw_protobuf_compiler/proto.cmake b/pw_protobuf_compiler/proto.cmake
index 60b146b..6d39633 100644
--- a/pw_protobuf_compiler/proto.cmake
+++ b/pw_protobuf_compiler/proto.cmake
@@ -79,7 +79,7 @@
 
   add_custom_command(
     COMMAND
-      python
+      python3
       "$ENV{PW_ROOT}/pw_build/py/pw_build/mirror_tree.py"
       --source-root "${arg_STRIP_PREFIX}"
       --directory "${out_dir}/sources/${arg_PREFIX}"
@@ -141,7 +141,7 @@
   set(script "$ENV{PW_ROOT}/pw_protobuf_compiler/py/pw_protobuf_compiler/generate_protos.py")
   add_custom_command(
     COMMAND
-      python
+      python3
       "${script}"
       --language "${LANGUAGE}"
       --plugin-path "${PLUGIN}"
@@ -213,20 +213,32 @@
 function(_pw_nanopb_library NAME SOURCES INPUTS DEPS INCLUDE_FILE OUT_DIR)
   list(TRANSFORM DEPS APPEND .nanopb)
 
-  set(nanopb_dir "$<TARGET_PROPERTY:$<IF:$<TARGET_EXISTS:protobuf-nanopb-static>,protobuf-nanopb-static,pw_build.empty>,SOURCE_DIR>")
-  set(nanopb_plugin
-      "$<IF:$<TARGET_EXISTS:protobuf-nanopb-static>,${nanopb_dir}/generator/protoc-gen-nanopb,COULD_NOT_FIND_protobuf-nanopb-static_TARGET_PLEASE_SET_UP_NANOPB>")
-
-  _pw_generate_protos("${NAME}.generate.nanopb"
-      nanopb
-      "${nanopb_plugin}"
-      ".pb.h;.pb.c"
-      "${INCLUDE_FILE}"
-      "${OUT_DIR}"
-      "${SOURCES}"
-      "${INPUTS}"
-      "${DEPS}"
-  )
+  if("${dir_pw_third_party_nanopb}" STREQUAL "")
+    add_custom_target("${NAME}.generate.nanopb"
+        cmake -E echo
+            ERROR: Attempting to use pw_proto_library, but
+            dir_pw_third_party_nanopb is not set. Set dir_pw_third_party_nanopb
+            to the path to the Nanopb repository.
+      COMMAND
+        cmake -E false
+      DEPENDS
+        ${DEPS}
+      SOURCES
+        ${SOURCES}
+    )
+    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}"
+    )
+  endif()
 
   # Create the library with the generated source files.
   add_library("${NAME}.nanopb" EXCLUDE_FROM_ALL ${generated_outputs})
diff --git a/third_party/nanopb/CMakeLists.txt b/third_party/nanopb/CMakeLists.txt
index 1341403..7b5745e 100644
--- a/third_party/nanopb/CMakeLists.txt
+++ b/third_party/nanopb/CMakeLists.txt
@@ -12,19 +12,22 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-set(dir_pw_third_party_nanopb "" CACHE PATH
-    "Path to a Nanopb installation to import. Set to PRESENT if Nanopb is already present in the build."
-)
+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)
 
 if("${dir_pw_third_party_nanopb}" STREQUAL "")
   return()
-elseif(NOT "${dir_pw_third_party_nanopb}" STREQUAL PRESENT)
+elseif(pw_third_party_nanopb_ADD_SUBDIRECTORY)
   add_subdirectory("${dir_pw_third_party_nanopb}" third_party/nanopb)
 endif()
 
+set(nanopb_main_library
+    $<IF:$<TARGET_EXISTS:protobuf-nanopb-static>,protobuf-nanopb-static,protobuf-nanopb>)
+
 add_library(pw_third_party.nanopb INTERFACE)
-target_link_libraries(pw_third_party.nanopb INTERFACE protobuf-nanopb-static)
+target_link_libraries(pw_third_party.nanopb INTERFACE "${nanopb_main_library}")
 target_include_directories(pw_third_party.nanopb
   INTERFACE
-    $<TARGET_PROPERTY:protobuf-nanopb-static,SOURCE_DIR>
+    "${dir_pw_third_party_nanopb}"
 )