CMake: Revamp CMake build

- Define CMake cache variables (similar to gn args) for facade backends.
- Create simple initial toolchain files for GCC and Clang.
- Misc updates to pigweed.cmake and pw_build/CMakeLists.txt.
- Add or expand various CMakeLists.txt files.
- Watch CMake files in watch.py to support using CMake in pw watch.

Change-Id: I490d157485d02811a11f6a3589a0508ea1851f58
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/22840
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Reviewed-by: Keir Mierle <keir@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f75c53..18d47db 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,14 +14,14 @@
 
 project(Pigweed)
 
-cmake_minimum_required(VERSION 3.14)
-
-include(pw_build/pigweed.cmake)
+cmake_minimum_required(VERSION 3.16)
 
 add_subdirectory(pw_assert)
 add_subdirectory(pw_assert_basic)
+add_subdirectory(pw_assert_log)
 add_subdirectory(pw_base64)
 add_subdirectory(pw_blob_store)
+add_subdirectory(pw_build)
 add_subdirectory(pw_bytes)
 add_subdirectory(pw_checksum)
 add_subdirectory(pw_containers)
diff --git a/pw_assert/CMakeLists.txt b/pw_assert/CMakeLists.txt
index 508393f..9d9a259 100644
--- a/pw_assert/CMakeLists.txt
+++ b/pw_assert/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_add_facade(pw_assert
   PUBLIC_DEPS
     pw_preprocessor
diff --git a/pw_assert_basic/CMakeLists.txt b/pw_assert_basic/CMakeLists.txt
index 7e6c46a..ec2121e 100644
--- a/pw_assert_basic/CMakeLists.txt
+++ b/pw_assert_basic/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_assert_basic
   IMPLEMENTS_FACADE
     pw_assert
@@ -20,9 +22,3 @@
     pw_string
     pw_sys_io
 )
-
-target_include_directories(pw_assert_basic PUBLIC public_overrides)
-
-# TODO(hepler): Declare pw_assert_basic as the pw_assert backend for now.
-add_library(pw_assert.backend INTERFACE)
-target_link_libraries(pw_assert.backend INTERFACE pw_assert_basic)
diff --git a/pw_assert_log/CMakeLists.txt b/pw_assert_log/CMakeLists.txt
index d8f7312..96776e0 100644
--- a/pw_assert_log/CMakeLists.txt
+++ b/pw_assert_log/CMakeLists.txt
@@ -12,15 +12,13 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_assert_log
   IMPLEMENTS_FACADE
     pw_assert
+  PUBLIC_DEPS
+    pw_log
   PRIVATE_DEPS
     pw_preprocessor
 )
-
-target_include_directories(pw_assert_log PUBLIC public_overrides)
-
-# TODO(hepler): Declare pw_assert_log as the pw_assert backend for now.
-add_library(pw_assert.backend INTERFACE)
-target_link_libraries(pw_assert.backend INTERFACE pw_assert_log)
diff --git a/pw_base64/CMakeLists.txt b/pw_base64/CMakeLists.txt
index 95e63a9..69f99f8 100644
--- a/pw_base64/CMakeLists.txt
+++ b/pw_base64/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_base64
   PUBLIC_DEPS
     pw_span
diff --git a/pw_blob_store/CMakeLists.txt b/pw_blob_store/CMakeLists.txt
index a61888e..8041124 100644
--- a/pw_blob_store/CMakeLists.txt
+++ b/pw_blob_store/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_blob_store
   PUBLIC_DEPS
     pw_containers
diff --git a/pw_build/BUILD.gn b/pw_build/BUILD.gn
index 6044286..d30bbc9 100644
--- a/pw_build/BUILD.gn
+++ b/pw_build/BUILD.gn
@@ -16,6 +16,9 @@
 
 import("$dir_pw_docgen/docs.gni")
 
+# IMPORTANT: The compilation flags in this file must be kept in sync with
+#            the CMake flags pw_build/CMakeLists.txt.
+
 config("colorize_output") {
   cflags = [
     # Colorize output. Ninja's Clang invocation disables color by default.
diff --git a/pw_build/CMakeLists.txt b/pw_build/CMakeLists.txt
new file mode 100644
index 0000000..518879e
--- /dev/null
+++ b/pw_build/CMakeLists.txt
@@ -0,0 +1,88 @@
+# Copyright 2020 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.
+
+# IMPORTANT: The compilation flags in this file must be kept in sync with
+#            the GN flags //pw_build/BUILD.gn.
+
+# Target that specifies the standard Pigweed build options.
+add_library(pw_build INTERFACE)
+target_compile_options(pw_build INTERFACE "-g")
+target_link_libraries(pw_build
+  INTERFACE
+    pw_build.reduced_size
+    pw_build.strict_warnings
+    pw_build.extra_strict_warnings
+    pw_build.cpp17
+)
+target_compile_options(pw_build
+  INTERFACE
+    # Force the compiler use colorized output. This is required for Ninja.
+    $<$<CXX_COMPILER_ID:Clang>:-fcolor-diagnostics>
+    $<$<CXX_COMPILER_ID:GNU>:-fdiagnostics-color=always>
+)
+
+# Declare top-level targets for tests.
+add_custom_target(pw_tests.default)
+add_custom_target(pw_run_tests.default)
+
+add_custom_target(pw_tests DEPENDS pw_tests.default)
+add_custom_target(pw_run_tests DEPENDS pw_run_tests.default)
+
+# Define the standard Pigweed compile options.
+add_library(pw_build.reduced_size INTERFACE)
+target_compile_options(pw_build.reduced_size
+  INTERFACE
+    "-fno-common"
+    "-fno-exceptions"
+    "-ffunction-sections"
+    "-fdata-sections"
+    $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
+)
+
+add_library(pw_build.strict_warnings INTERFACE)
+target_compile_options(pw_build.strict_warnings
+  INTERFACE
+    "-Wall"
+    "-Wextra"
+    "-Wimplicit-fallthrough"
+    "-Wcast-qual"
+    "-Wundef"
+    "-Wpointer-arith"
+
+    # Make all warnings errors, except for the exemptions below.
+    "-Werror"
+    "-Wno-error=cpp"  # preprocessor #warning statement
+    "-Wno-error=deprecated-declarations"  # [[deprecated]] attribute
+
+    $<$<COMPILE_LANGUAGE:CXX>:-Wnon-virtual-dtor>
+)
+
+add_library(pw_build.extra_strict_warnings INTERFACE)
+target_compile_options(pw_build.extra_strict_warnings
+  INTERFACE
+    "-Wshadow"
+    "-Wredundant-decls"
+)
+
+add_library(pw_build.cpp17 INTERFACE)
+target_compile_options(pw_build.cpp17
+  INTERFACE
+    $<$<COMPILE_LANGUAGE:CXX>:-std=c++17>
+    # Allow uses of the register keyword, which may appear in C headers.
+    $<$<COMPILE_LANGUAGE:CXX>:-Wno-register>
+)
+
+# Create an empty source file and library for general use.
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/empty_file.c" "")
+add_library(pw_build.empty OBJECT "${CMAKE_CURRENT_BINARY_DIR}/empty_file.c" "")
diff --git a/pw_build/pigweed.cmake b/pw_build/pigweed.cmake
index f5a4a7b..efffd43 100644
--- a/pw_build/pigweed.cmake
+++ b/pw_build/pigweed.cmake
@@ -13,11 +13,6 @@
 # the License.
 include_guard(GLOBAL)
 
-# Create an empty, dummy source file for use by non-INTERFACE libraries, which
-# require at least one source file.
-set(_pw_empty_source_file "${CMAKE_BINARY_DIR}/pw_empty_source_file.cc")
-file(WRITE "${_pw_empty_source_file}" "")
-
 # Automatically creates a library and test targets for the files in a module.
 # This function is only suitable for simple modules that meet the following
 # requirements:
@@ -43,25 +38,27 @@
 #   3. Declare a test for each source file that ends with _test.cc.
 #
 # Args:
-#   IMPLEMENTS_FACADE: this module implements the specified facade
-#   PUBLIC_DEPS: public target_link_libraries arguments
-#   PRIVATE_DEPS: private target_link_libraries arguments
+#
+#   IMPLEMENTS_FACADE - this module implements the specified facade
+#   PUBLIC_DEPS - public target_link_libraries arguments
+#   PRIVATE_DEPS - private target_link_libraries arguments
 #
 function(pw_auto_add_simple_module MODULE)
-  set(multi PUBLIC_DEPS PRIVATE_DEPS)
+  set(multi PUBLIC_DEPS PRIVATE_DEPS TEST_DEPS)
   cmake_parse_arguments(PARSE_ARGV 1 arg "" "IMPLEMENTS_FACADE" "${multi}")
 
   file(GLOB all_sources *.cc *.c)
 
   # Create a library with all source files not ending in _test.
   set(sources "${all_sources}")
-  list(FILTER sources EXCLUDE REGEX "_test.cc$")
+  list(FILTER sources EXCLUDE REGEX "_test(\\.cc|(_c)?\\.c)$")
+  list(FILTER sources EXCLUDE REGEX "_fuzzer\\.cc$")
 
   file(GLOB_RECURSE headers *.h)
 
   if(arg_IMPLEMENTS_FACADE)
     set(groups backends)
-    set(deps PUBLIC_DEPS "${arg_IMPLEMENTS_FACADE}.facade")
+    set(facade_dep "${arg_IMPLEMENTS_FACADE}.facade")
   else()
     set(groups modules "${MODULE}")
   endif()
@@ -69,48 +66,72 @@
   pw_add_module_library("${MODULE}"
     PUBLIC_DEPS
       ${arg_PUBLIC_DEPS}
+      ${facade_dep}
     PRIVATE_DEPS
       ${arg_PRIVATE_DEPS}
     SOURCES
       ${sources}
     HEADERS
       ${headers}
-    ${deps}
   )
 
-  # Create a test for each source file ending in _test. Tests with mutliple .cc
-  # files or different dependencies than the module will not work correctly.
-  set(tests "${all_sources}")
-  list(FILTER tests INCLUDE REGEX "_test.cc$")
+  if(arg_IMPLEMENTS_FACADE)
+    target_include_directories("${MODULE}" PUBLIC public_overrides)
+  endif()
 
-  foreach(test IN LISTS tests)
+  pw_auto_add_module_tests("${MODULE}"
+    PRIVATE_DEPS
+      ${arg_PUBLIC_DEPS}
+      ${arg_PRIVATE_DEPS}
+      ${arg_TEST_DEPS}
+    GROUPS
+      ${groups}
+  )
+endfunction(pw_auto_add_simple_module)
+
+# Creates a test for each source file ending in _test. Tests with mutliple .cc
+# files or different dependencies than the module will not work correctly.
+#
+# Args:
+#
+#  PRIVATE_DEPS - dependencies to apply to all tests
+#  GROUPS - groups in addition to MODULE to which to add these tests
+#
+function(pw_auto_add_module_tests MODULE)
+  cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "PRIVATE_DEPS;GROUPS")
+
+  file(GLOB cc_tests *_test.cc)
+
+  foreach(test IN LISTS cc_tests)
     get_filename_component(test_name "${test}" NAME_WE)
 
     # Find a .c test corresponding with the test .cc file, if any.
-    list(FILTER c_test INCLUDE REGEX "^${test_name}.c$")
+    file(GLOB c_test "${test_name}.c" "${test_name}_c.c")
 
     pw_add_test("${MODULE}.${test_name}"
       SOURCES
         "${test}"
         ${c_test}
       DEPS
-        "${MODULE}"
-        ${arg_PUBLIC_DEPS}
+        "$<TARGET_NAME_IF_EXISTS:${MODULE}>"
         ${arg_PRIVATE_DEPS}
       GROUPS
-        "${groups}"
+        "${MODULE}"
+        ${arg_GROUPS}
     )
   endforeach()
-endfunction(pw_auto_add_simple_module)
+endfunction(pw_auto_add_module_tests)
 
 # Creates a library in a module. The library has access to the public/ include
 # directory.
 #
 # Args:
-#   SOURCES: source files for this library
-#   HEADERS: header files for this library
-#   PUBLIC_DEPS: public target_link_libraries arguments
-#   PRIVATE_DEPS: private target_link_libraries arguments
+#
+#   SOURCES - source files for this library
+#   HEADERS - header files for this library
+#   PUBLIC_DEPS - public target_link_libraries arguments
+#   PRIVATE_DEPS - private target_link_libraries arguments
+#
 function(pw_add_module_library NAME)
   set(list_args SOURCES HEADERS PUBLIC_DEPS PRIVATE_DEPS)
   cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "${list_args}")
@@ -118,7 +139,7 @@
   # Check that the library's name is prefixed by the module name.
   get_filename_component(module "${CMAKE_CURRENT_SOURCE_DIR}" NAME)
 
-  if(NOT "${NAME}" MATCHES "^${module}(\\.[^\\.]+)?(\\.facade|\\.backend)?$")
+  if(NOT "${NAME}" MATCHES "${module}(\\.[^\\.]+)?(\\.facade)?$")
     message(FATAL_ERROR
         "Module libraries must match the module name or be in the form "
         "'MODULE_NAME.LIBRARY_NAME'. The library '${NAME}' does not match."
@@ -137,7 +158,7 @@
 
   # Libraries require at least one source file.
   if(NOT arg_SOURCES)
-    target_sources("${NAME}" PRIVATE "${_pw_empty_source_file}")
+    target_sources("${NAME}" PRIVATE $<TARGET_PROPERTY:pw_build.empty,SOURCES>)
   endif()
 endfunction(pw_add_module_library)
 
@@ -148,31 +169,64 @@
 # module that implements the facade depends on a library named
 # MODULE_NAME.facade.
 #
-# pw_add_facade accepts the same arguments as pw_add_module_library.
+# pw_add_facade accepts the same arguments as pw_add_module_library, with the
+# following additions:
+#
+#  DEFAULT_BACKEND - which backend to use by default
+#
 function(pw_add_facade NAME)
-  pw_add_module_library("${NAME}.facade" ${ARGN})
+  cmake_parse_arguments(PARSE_ARGV 1 arg "" "DEFAULT_BACKEND" "")
 
-  # Use a library with an empty source instead of an INTERFACE library so that
-  # the library can have a private dependency on the backend.
-  add_library("${NAME}" OBJECT EXCLUDE_FROM_ALL "${_pw_empty_source_file}")
+  # If no backend is set, a script that displays an error message is used
+  # instead. If the facade is used in the build, it fails with this error.
+  add_custom_target("${NAME}._no_backend_set_message"
+    COMMAND
+      python "$ENV{PW_ROOT}/pw_build/py/pw_build/null_backend.py" "${NAME}"
+  )
+  add_library("${NAME}.NO_BACKEND_SET" INTERFACE)
+  add_dependencies("${NAME}.NO_BACKEND_SET" "${NAME}._no_backend_set_message")
+
+  # Set the default backend to the error message if no default is specified.
+  if("${arg_DEFAULT_BACKEND}" STREQUAL "")
+    set(arg_DEFAULT_BACKEND "${NAME}.NO_BACKEND_SET")
+  endif()
+
+  # Declare the backend variable for this facade.
+  set("${NAME}_BACKEND" "${arg_DEFAULT_BACKEND}" CACHE STRING
+      "Backend for ${NAME}")
+
+  # Define the facade library, which is used by the backend to avoid circular
+  # dependencies.
+  pw_add_module_library("${NAME}.facade" ${arg_UNPARSED_ARGUMENTS})
+
+  # Define the public-facing library for this facade, which depends on the
+  # header files in .facade target and exposes the dependency on the backend.
+  add_library("${NAME}" INTERFACE)
   target_link_libraries("${NAME}"
-    PUBLIC
+    INTERFACE
       "${NAME}.facade"
-      "${NAME}.backend"
+      "${${NAME}_BACKEND}"
   )
 endfunction(pw_add_facade)
 
+# Sets which backend to use for the given facade.
+function(pw_set_backend FACADE BACKEND)
+  set("${FACADE}_BACKEND" "${BACKEND}" CACHE STRING "Backend for ${NAME}" FORCE)
+endfunction(pw_set_backend)
+
 # Declares a unit test. Creates two targets:
 #
-#  - <TEST_NAME>: the test executable
-#  - <TEST_NAME>_run: builds and runs the test
+#  * <TEST_NAME> - the test executable
+#  * <TEST_NAME>_run - builds and runs the test
 #
 # Args:
+#
 #   NAME: name to use for the target
 #   SOURCES: source files for this test
 #   DEPS: libraries on which this test depends
 #   GROUPS: groups to which to add this test; if none are specified, the test is
-#       added to the default and all groups
+#       added to the 'default' and 'all' groups
+#
 function(pw_add_test NAME)
   cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "SOURCES;DEPS;GROUPS")
 
@@ -227,57 +281,3 @@
     add_dependencies("pw_run_tests.${group}" "${TEST_NAME}_run")
   endforeach()
 endfunction(pw_add_test_to_groups)
-
-# Declare top-level targets for tests.
-add_custom_target(pw_tests.default)
-add_custom_target(pw_run_tests.default)
-
-add_custom_target(pw_tests DEPENDS pw_tests.default)
-add_custom_target(pw_run_tests DEPENDS pw_run_tests.default)
-
-# Define the standard Pigweed compile options.
-add_library(_pw_reduced_size_copts INTERFACE)
-target_compile_options(_pw_reduced_size_copts
-  INTERFACE
-    "-fno-common"
-    "-fno-exceptions"
-    "-ffunction-sections"
-    "-fdata-sections"
-    $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
-)
-
-add_library(_pw_strict_warnings_copts INTERFACE)
-target_compile_options(_pw_strict_warnings_copts
-  INTERFACE
-    "-Wall"
-    "-Wextra"
-    # Make all warnings errors, except for the exemptions below.
-    "-Werror"
-    "-Wno-error=cpp"  # preprocessor #warning statement
-    "-Wno-error=deprecated-declarations"  # [[deprecated]] attribute
-    $<$<COMPILE_LANGUAGE:CXX>:-Wnon-virtual-dtor>
-)
-
-add_library(_pw_cpp17_copts INTERFACE)
-target_compile_options(_pw_cpp17_copts
-  INTERFACE
-    $<$<COMPILE_LANGUAGE:CXX>:-std=c++17>
-    # Allow uses of the register keyword, which may appear in C headers.
-    $<$<COMPILE_LANGUAGE:CXX>:-Wno-register>
-)
-
-# Target that specifies the standard Pigweed build options.
-add_library(pw_build INTERFACE)
-target_compile_options(pw_build INTERFACE "-g")
-target_link_libraries(pw_build
-  INTERFACE
-    _pw_reduced_size_copts
-    _pw_strict_warnings_copts
-    _pw_cpp17_copts
-)
-target_compile_options(pw_build
-  INTERFACE
-    # Force the compiler use colorized output. This is required for Ninja.
-    $<$<CXX_COMPILER_ID:Clang>:-fcolor-diagnostics>
-    $<$<CXX_COMPILER_ID:GNU>:-fdiagnostics-color=always>
-)
diff --git a/pw_bytes/CMakeLists.txt b/pw_bytes/CMakeLists.txt
index e392d42..33f48b7 100644
--- a/pw_bytes/CMakeLists.txt
+++ b/pw_bytes/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_bytes
   PUBLIC_DEPS
     pw_polyfill.overrides
diff --git a/pw_checksum/CMakeLists.txt b/pw_checksum/CMakeLists.txt
index 1f2be28..94fe371 100644
--- a/pw_checksum/CMakeLists.txt
+++ b/pw_checksum/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_checksum
   PUBLIC_DEPS
     pw_span
diff --git a/pw_containers/CMakeLists.txt b/pw_containers/CMakeLists.txt
index 4d9ee9a..3936249 100644
--- a/pw_containers/CMakeLists.txt
+++ b/pw_containers/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_containers
   PUBLIC_DEPS
     pw_assert
diff --git a/pw_cpu_exception/CMakeLists.txt b/pw_cpu_exception/CMakeLists.txt
index c30ab81..1e134c6 100644
--- a/pw_cpu_exception/CMakeLists.txt
+++ b/pw_cpu_exception/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_add_facade(pw_cpu_exception
   PUBLIC_DEPS
     pw_preprocessor
diff --git a/pw_cpu_exception_armv7m/CMakeLists.txt b/pw_cpu_exception_armv7m/CMakeLists.txt
index 7f1bf23..55d3a01 100644
--- a/pw_cpu_exception_armv7m/CMakeLists.txt
+++ b/pw_cpu_exception_armv7m/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_cpu_exception_armv7m
   IMPLEMENTS_FACADE
     pw_cpu_exception
diff --git a/pw_kvs/CMakeLists.txt b/pw_kvs/CMakeLists.txt
index a52e9d6..3d48927 100644
--- a/pw_kvs/CMakeLists.txt
+++ b/pw_kvs/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_kvs
   PUBLIC_DEPS
     pw_containers
diff --git a/pw_log/CMakeLists.txt b/pw_log/CMakeLists.txt
index 4928c2f..4b77940 100644
--- a/pw_log/CMakeLists.txt
+++ b/pw_log/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_add_facade(pw_log
   PUBLIC_DEPS
     pw_preprocessor
diff --git a/pw_log_basic/CMakeLists.txt b/pw_log_basic/CMakeLists.txt
index 5c66fe0..3cf0f74 100644
--- a/pw_log_basic/CMakeLists.txt
+++ b/pw_log_basic/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_log_basic
   IMPLEMENTS_FACADE
     pw_log
@@ -19,9 +21,3 @@
     pw_string
     pw_sys_io
 )
-
-target_include_directories(pw_log_basic PUBLIC public_overrides)
-
-# TODO(hepler): Declare pw_log_basic as the pw_log backend for now.
-add_library(pw_log.backend INTERFACE)
-target_link_libraries(pw_log.backend INTERFACE pw_log_basic)
diff --git a/pw_log_null/CMakeLists.txt b/pw_log_null/CMakeLists.txt
index 0d86701..1f74b8d 100644
--- a/pw_log_null/CMakeLists.txt
+++ b/pw_log_null/CMakeLists.txt
@@ -12,11 +12,11 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_log_null
   IMPLEMENTS_FACADE
     pw_log
   PUBLIC_DEPS
     pw_preprocessor
 )
-
-target_include_directories(pw_log_null PUBLIC public_overrides)
diff --git a/pw_log_tokenized/CMakeLists.txt b/pw_log_tokenized/CMakeLists.txt
index 35aaf65..1c91a64 100644
--- a/pw_log_tokenized/CMakeLists.txt
+++ b/pw_log_tokenized/CMakeLists.txt
@@ -12,11 +12,11 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_log_tokenized
   IMPLEMENTS_FACADE
     pw_log
   PUBLIC_DEPS
     pw_tokenizer
 )
-
-target_include_directories(pw_log_tokenized PUBLIC public_overrides)
diff --git a/pw_polyfill/language_features.h b/pw_polyfill/language_features.h
index 2fc7a2a..9527935 100644
--- a/pw_polyfill/language_features.h
+++ b/pw_polyfill/language_features.h
@@ -22,7 +22,7 @@
 #pragma once
 
 // C++11 is required for the features in this header.
-#if __cplusplus >= 201103L
+#if defined(__cplusplus) && __cplusplus >= 201103L
 
 // If consteval is not supported, use constexpr. This does not guarantee
 // compile-time execution, but works equivalently in constant expressions.
@@ -68,4 +68,4 @@
 }  // namespace pw
 
 #endif  // __cpp_static_assert < 201411L
-#endif  // __cplusplus >= 201103L
+#endif  // defined(__cplusplus) && __cplusplus >= 201103L
diff --git a/pw_preprocessor/CMakeLists.txt b/pw_preprocessor/CMakeLists.txt
index 75dd616..3e893a0 100644
--- a/pw_preprocessor/CMakeLists.txt
+++ b/pw_preprocessor/CMakeLists.txt
@@ -12,4 +12,6 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_preprocessor)
diff --git a/pw_presubmit/py/pw_presubmit/build.py b/pw_presubmit/py/pw_presubmit/build.py
index ffb86ab..4a370e3 100644
--- a/pw_presubmit/py/pw_presubmit/build.py
+++ b/pw_presubmit/py/pw_presubmit/build.py
@@ -88,9 +88,18 @@
 
 def cmake(source_dir: Path,
           output_dir: Path,
+          *args: str,
           env: Mapping['str', 'str'] = None) -> None:
     """Runs CMake for Ninja on the given source and output directories."""
-    call('cmake', '-B', output_dir, '-S', source_dir, '-G', 'Ninja', env=env)
+    call('cmake',
+         '-B',
+         output_dir,
+         '-S',
+         source_dir,
+         '-G',
+         'Ninja',
+         *args,
+         env=env)
 
 
 def env_with_clang_vars() -> Mapping[str, str]:
diff --git a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
index 2cfc8c3..6c81db0 100755
--- a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
+++ b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
@@ -150,7 +150,12 @@
 @filter_paths(endswith=(*format_code.C_FORMAT.extensions, '.cmake',
                         'CMakeLists.txt'))
 def cmake_tests(ctx: PresubmitContext):
-    build.cmake(ctx.root, ctx.output_dir, env=build.env_with_clang_vars())
+    toolchain = ctx.root / 'pw_toolchain' / 'host_clang' / 'toolchain.cmake'
+
+    build.cmake(ctx.root,
+                ctx.output_dir,
+                f'-DCMAKE_TOOLCHAIN_FILE={toolchain}',
+                env=build.env_with_clang_vars())
     build.ninja(ctx.output_dir, 'pw_run_tests.modules')
 
 
diff --git a/pw_random/CMakeLists.txt b/pw_random/CMakeLists.txt
index b297f32..aabdd23 100644
--- a/pw_random/CMakeLists.txt
+++ b/pw_random/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_random
   PUBLIC_DEPS
     pw_bytes
diff --git a/pw_result/CMakeLists.txt b/pw_result/CMakeLists.txt
index 9bf8f5f..20b5db0 100644
--- a/pw_result/CMakeLists.txt
+++ b/pw_result/CMakeLists.txt
@@ -12,9 +12,10 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_result
   PUBLIC_DEPS
-    pw_status
-  PRIVATE_DEPS
     pw_assert
+    pw_status
 )
diff --git a/pw_rpc/CMakeLists.txt b/pw_rpc/CMakeLists.txt
index 2d62392..b4687ef 100644
--- a/pw_rpc/CMakeLists.txt
+++ b/pw_rpc/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_rpc
   PUBLIC_DEPS
     pw_assert
diff --git a/pw_span/CMakeLists.txt b/pw_span/CMakeLists.txt
index 65644a1..9b22950 100644
--- a/pw_span/CMakeLists.txt
+++ b/pw_span/CMakeLists.txt
@@ -12,5 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_span PUBLIC_DEPS pw_polyfill)
 target_include_directories(pw_span PUBLIC public_overrides)
diff --git a/pw_status/CMakeLists.txt b/pw_status/CMakeLists.txt
index 132c41e..3c5a0f0 100644
--- a/pw_status/CMakeLists.txt
+++ b/pw_status/CMakeLists.txt
@@ -12,4 +12,6 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_status)
diff --git a/pw_stream/CMakeLists.txt b/pw_stream/CMakeLists.txt
index 1d17437..27e58f6 100644
--- a/pw_stream/CMakeLists.txt
+++ b/pw_stream/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_stream
   PUBLIC_DEPS
     pw_bytes
diff --git a/pw_string/CMakeLists.txt b/pw_string/CMakeLists.txt
index 24c48aa..92a14a4 100644
--- a/pw_string/CMakeLists.txt
+++ b/pw_string/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_string
   PUBLIC_DEPS
     pw_preprocessor
diff --git a/pw_sys_io/CMakeLists.txt b/pw_sys_io/CMakeLists.txt
index 7ca3860..ee69592 100644
--- a/pw_sys_io/CMakeLists.txt
+++ b/pw_sys_io/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_add_facade(pw_sys_io
   SOURCES
     sys_io.cc
diff --git a/pw_sys_io_stdio/CMakeLists.txt b/pw_sys_io_stdio/CMakeLists.txt
index 5b76f64..1493cf7 100644
--- a/pw_sys_io_stdio/CMakeLists.txt
+++ b/pw_sys_io_stdio/CMakeLists.txt
@@ -12,11 +12,9 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_sys_io_stdio
   IMPLEMENTS_FACADE
     pw_sys_io
 )
-
-# TODO(hepler): Declare pw_sys_io_stdio as the pw_sys_io backend for now.
-add_library(pw_sys_io.backend INTERFACE)
-target_link_libraries(pw_sys_io.backend INTERFACE pw_sys_io_stdio)
diff --git a/pw_tokenizer/CMakeLists.txt b/pw_tokenizer/CMakeLists.txt
index 05b713a..b96104a 100644
--- a/pw_tokenizer/CMakeLists.txt
+++ b/pw_tokenizer/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_add_module_library(pw_tokenizer
   SOURCES
     encode_args.cc
@@ -53,6 +55,8 @@
     tokenize_to_global_handler.cc
   PUBLIC_DEPS
     pw_tokenizer
+  DEFAULT_BACKEND
+    pw_build.empty  # Default to an empty backend so the tests can run.
 )
 
 pw_add_facade(pw_tokenizer.global_handler_with_payload
@@ -60,21 +64,10 @@
     tokenize_to_global_handler_with_payload.cc
   PUBLIC_DEPS
     pw_tokenizer
+  DEFAULT_BACKEND
+    pw_build.empty  # Default to an empty backend so the tests can run.
 )
 
-# TODO(hepler): Use an empty backend that makes tests possible, for now.
-add_library(pw_tokenizer.global_handler.backend INTERFACE)
-target_link_libraries(pw_tokenizer.global_handler.backend
-  INTERFACE
-    pw_tokenizer.test_backend)
-
-add_library(pw_tokenizer.global_handler_with_payload.backend INTERFACE)
-target_link_libraries(pw_tokenizer.global_handler_with_payload.backend
-  INTERFACE
-    pw_tokenizer.test_backend)
-
-add_library(pw_tokenizer.test_backend INTERFACE)
-
 # Executable for generating test data for the C++ and Python detokenizers. This
 # target should only be built for the host.
 add_executable(pw_tokenizer.generate_decoding_test_data EXCLUDE_FROM_ALL
diff --git a/pw_toolchain/host_clang/toolchain.cmake b/pw_toolchain/host_clang/toolchain.cmake
new file mode 100644
index 0000000..2628ee6
--- /dev/null
+++ b/pw_toolchain/host_clang/toolchain.cmake
@@ -0,0 +1,22 @@
+# Copyright 2020 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)
+
+pw_set_backend(pw_log pw_log_basic)
+pw_set_backend(pw_assert pw_assert_log)
+pw_set_backend(pw_sys_io pw_sys_io_stdio)
+
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_CXX_COMPILER clang++)
diff --git a/pw_toolchain/host_gcc/toolchain.cmake b/pw_toolchain/host_gcc/toolchain.cmake
new file mode 100644
index 0000000..0826543
--- /dev/null
+++ b/pw_toolchain/host_gcc/toolchain.cmake
@@ -0,0 +1,22 @@
+# Copyright 2020 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)
+
+pw_set_backend(pw_log pw_log_basic)
+pw_set_backend(pw_assert pw_assert_log)
+pw_set_backend(pw_sys_io pw_sys_io_stdio)
+
+set(CMAKE_C_COMPILER gcc)
+set(CMAKE_CXX_COMPILER g++)
diff --git a/pw_trace/CMakeLists.txt b/pw_trace/CMakeLists.txt
index 50f67ba..7a4fe84 100644
--- a/pw_trace/CMakeLists.txt
+++ b/pw_trace/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_add_facade(pw_trace
   PUBLIC_DEPS
     pw_preprocessor
diff --git a/pw_trace_tokenized/CMakeLists.txt b/pw_trace_tokenized/CMakeLists.txt
index c981dcc..e4bd46a 100644
--- a/pw_trace_tokenized/CMakeLists.txt
+++ b/pw_trace_tokenized/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_trace_tokenized
   IMPLEMENTS_FACADE
     pw_trace
@@ -24,5 +26,3 @@
     pw_trace:facade
     pw_varint
 )
-
-target_include_directories(pw_trace_tokenized PUBLIC public_overrides)
diff --git a/pw_unit_test/CMakeLists.txt b/pw_unit_test/CMakeLists.txt
index 3767b4e..983fe30 100644
--- a/pw_unit_test/CMakeLists.txt
+++ b/pw_unit_test/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_add_module_library(pw_unit_test
   SOURCES
     framework.cc
diff --git a/pw_varint/CMakeLists.txt b/pw_varint/CMakeLists.txt
index 6e66eb1..84da984 100644
--- a/pw_varint/CMakeLists.txt
+++ b/pw_varint/CMakeLists.txt
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
 pw_auto_add_simple_module(pw_varint
   PUBLIC_DEPS
     pw_preprocessor
diff --git a/pw_watch/py/pw_watch/watch.py b/pw_watch/py/pw_watch/watch.py
index f8e2e9b..7f02980 100755
--- a/pw_watch/py/pw_watch/watch.py
+++ b/pw_watch/py/pw_watch/watch.py
@@ -304,6 +304,8 @@
     '*.c',
     '*.cc',
     '*.cpp',
+    '*.cmake',
+    'CMakeLists.txt',
     '*.gn',
     '*.gni',
     '*.go',