pw_build: Switch to pw_* target types

This change replaces the implicit overrides of the default GN target
types in BUILDCONFIG.gn with explicit pw_* versions. This is done to
allow Pigweed to build within larger GN projects without modifying their
BUILDCONFIG files.

Change-Id: I1d1e41d5e9bde8fe076f7031f3c2b98b9630ff70
diff --git a/BUILDCONFIG.gn b/BUILDCONFIG.gn
index 58a462f..306ce8c 100644
--- a/BUILDCONFIG.gn
+++ b/BUILDCONFIG.gn
@@ -48,66 +48,8 @@
 # set the default toolchain.
 assert(pw_target_toolchain != "",
        "Build target must provide its own toolchain.")
+
+# The default toolchain is not used in Pigweed builds, so it is set to a dummy
+# toolchain. The top-level BUILD.gn should stamp a group with all of the build
+# targets and their toolchains.
 set_default_toolchain("$dir_pw_toolchain/dummy")
-
-# Override the built-in build targets to add default compilation options.
-# TODO(pwbug/72): Move this code to a .gni file for easier reuse.
-template("_pw_override_target_with_defaults") {
-  # Set the default variables for GN targets.
-  import("$dir_pw_build/defaults.gni")
-  target(invoker._target_type, target_name) {
-    _supported_default_variables = [
-      "configs",
-      "public_deps",
-    ]
-    forward_variables_from(invoker,
-                           "*",
-                           [ "_target_type" ] + _supported_default_variables)
-
-    if (defined(pw_build_defaults.configs)) {
-      configs = pw_build_defaults.configs
-    } else {
-      configs = []
-    }
-    if (defined(remove_configs)) {
-      if (remove_configs[0] == "*") {
-        configs = []
-      } else {
-        configs -= remove_configs
-      }
-    }
-    if (defined(invoker.configs)) {
-      configs += invoker.configs
-    }
-
-    if (defined(pw_build_defaults.public_deps)) {
-      public_deps = pw_build_defaults.public_deps
-    } else {
-      public_deps = []
-    }
-    if (defined(remove_public_deps)) {
-      if (remove_public_deps[0] == "*") {
-        public_deps = []
-      } else {
-        public_deps -= remove_public_deps
-      }
-    }
-    if (defined(invoker.public_deps)) {
-      public_deps += invoker.public_deps
-    }
-  }
-}
-
-foreach(_target_type,
-        [
-          "source_set",
-          "executable",
-          "shared_library",
-          "static_library",
-        ]) {
-  template(_target_type) {
-    _pw_override_target_with_defaults(target_name) {
-      forward_variables_from(invoker, "*")
-    }
-  }
-}
diff --git a/pw_allocator/BUILD.gn b/pw_allocator/BUILD.gn
index 6c48169..18be387 100644
--- a/pw_allocator/BUILD.gn
+++ b/pw_allocator/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -27,7 +28,7 @@
   ]
 }
 
-source_set("block") {
+pw_source_set("block") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_allocator/block.h" ]
   public_deps = [
@@ -37,7 +38,7 @@
   sources = [ "block.cc" ]
 }
 
-source_set("freelist") {
+pw_source_set("freelist") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_allocator/freelist.h" ]
   public_deps = [
@@ -48,7 +49,7 @@
   sources = [ "freelist.cc" ]
 }
 
-source_set("freelist_heap") {
+pw_source_set("freelist_heap") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_allocator/freelist_heap.h" ]
   public_deps = [
diff --git a/pw_assert_basic/BUILD.gn b/pw_assert_basic/BUILD.gn
index 091a095..a77c2b9 100644
--- a/pw_assert_basic/BUILD.gn
+++ b/pw_assert_basic/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 
 config("default_config") {
@@ -23,7 +24,7 @@
 }
 
 if (dir_pw_assert_backend == dir_pw_assert_basic) {
-  source_set("pw_assert_basic") {
+  pw_source_set("pw_assert_basic") {
     public_configs = [
       ":backend_config",
       ":default_config",
@@ -34,7 +35,7 @@
   }
 }
 
-source_set("core") {
+pw_source_set("core") {
   public_configs = [ ":default_config" ]
   deps = [
     "$dir_pw_assert:facade",
diff --git a/pw_base64/BUILD.gn b/pw_base64/BUILD.gn
index 00830cc..3c9a909 100644
--- a/pw_base64/BUILD.gn
+++ b/pw_base64/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_base64") {
+pw_source_set("pw_base64") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_base64/base64.h" ]
   sources = [ "base64.cc" ]
diff --git a/pw_bloat/BUILD.gn b/pw_bloat/BUILD.gn
index 9a15a9c..480aa3e 100644
--- a/pw_bloat/BUILD.gn
+++ b/pw_bloat/BUILD.gn
@@ -12,7 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-import("$dir_pw_build/pw_executable.gni")
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("bloat.gni")
 
@@ -22,7 +22,7 @@
 
 # Library which uses standard C/C++ functions such as memcpy to prevent them
 # from showing up within bloat diff reports.
-source_set("bloat_this_binary") {
+pw_source_set("bloat_this_binary") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_bloat/bloat_this_binary.h" ]
   sources = [ "bloat_this_binary.cc" ] + public
diff --git a/pw_boot_armv7m/BUILD.gn b/pw_boot_armv7m/BUILD.gn
index 6a5b745..27a496d 100644
--- a/pw_boot_armv7m/BUILD.gn
+++ b/pw_boot_armv7m/BUILD.gn
@@ -13,6 +13,7 @@
 # the License.
 
 import("$dir_pw_build/linker_script.gni")
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 
 if (dir_pw_boot_backend == dir_pw_boot_armv7m) {
@@ -28,7 +29,7 @@
     linker_script = "basic_armv7m.ld"
   }
 
-  source_set("pw_boot_armv7m") {
+  pw_source_set("pw_boot_armv7m") {
     public_configs = [ ":default_config" ]
     deps = [
       ":armv7m_linker_script",
diff --git a/pw_build/docs.rst b/pw_build/docs.rst
index 147c691..af965f4 100644
--- a/pw_build/docs.rst
+++ b/pw_build/docs.rst
@@ -44,17 +44,30 @@
 Templates
 ---------
 
-pw_executable
-^^^^^^^^^^^^^
+Target types
+^^^^^^^^^^^^
 .. code::
 
-  import("$dir_pw_build/pw_executable.gni")
+  import("$dir_pw_build/target_types.gni")
 
-The ``pw_executable`` template is a wrapper around executable targets which
-builds for a globally-defined target type. This is controlled by the build
-variable ``pw_executable_config.target_type``. For example, setting this
-variable to ``stm32f429i_executable`` causes all executable targets to build
-using that template.
+  pw_source_set("my_library") {
+    sources = [ "lib.cc" ]
+  }
+
+Pigweed defines wrappers around the four basic GN binary types ``source_set``,
+``executable``, ``static_library``, and ``shared_library``. These wrappers apply
+default arguments to each target as specified in the ``default_configs`` and
+``default_public_deps`` build args. Additionally, they allow defaults to be
+removed on a per-target basis using ``remove_configs`` and
+``remove_public_deps`` variables, respectively.
+
+The ``pw_executable`` template provides additional functionality around building
+complete binaries. As Pigweed is a collection of libraries, it does not know how
+its final targets are built. ``pw_executable`` solves this by letting each user
+of Pigweed specify a global executable template for their target, and have
+Pigweed build against it. This is controlled by the build variable
+``pw_executable_config.target_type``, specifying the name of the executable
+template for a project.
 
 .. tip::
 
@@ -63,8 +76,8 @@
 
 **Arguments**
 
-``pw_executable`` accepts any arguments, as it simply forwards them through to
-the specified custom template.
+All of the ``pw_*`` target type overrides accept any arguments, as they simply
+forward them through to the underlying target.
 
 pw_python_script
 ^^^^^^^^^^^^^^^^
diff --git a/pw_build/facade.gni b/pw_build/facade.gni
index a232d4d..12a0fa0 100644
--- a/pw_build/facade.gni
+++ b/pw_build/facade.gni
@@ -13,6 +13,7 @@
 # the License.
 
 import("$dir_pw_build/python_script.gni")
+import("$dir_pw_build/target_types.gni")
 
 # Declare a facade.
 # A Pigweed facade is an API layer that has a single implementation it must link
@@ -57,7 +58,7 @@
   #     sources = [ "foo.cc" ]
   #   }
   #
-  #   source_set("foo_backend_bar") {
+  #   pw_source_set("foo_backend_bar") {
   #     deps = [ ":facade" ]
   #     sources = [ "bar.cc" ]
   #   }
@@ -75,7 +76,7 @@
     "public_deps",
     "public",
   ]
-  source_set(_facade_name) {
+  pw_source_set(_facade_name) {
     forward_variables_from(invoker, _facade_vars)
   }
 
@@ -97,7 +98,7 @@
   # Create a target that defines the main facade library. Always emit this
   # target, even if the backend isn't defined, so that the dependency graph is
   # correctly expressed for gn check.
-  source_set(target_name) {
+  pw_source_set(target_name) {
     # The main library contains everything else specified in the template.
     _ignore_vars = [ "backend" ] + _facade_vars
     forward_variables_from(invoker, "*", _ignore_vars)
diff --git a/pw_build/linker_script.gni b/pw_build/linker_script.gni
index 7c5abf2..4b208bf 100644
--- a/pw_build/linker_script.gni
+++ b/pw_build/linker_script.gni
@@ -13,6 +13,7 @@
 # the License.
 
 import("$dir_pw_build/exec.gni")
+import("$dir_pw_build/target_types.gni")
 
 # Preprocess a linker script and turn it into a target.
 #
@@ -111,7 +112,7 @@
 
   # The target that adds the linker script config to this library and everything
   # that depends on it.
-  source_set(target_name) {
+  pw_source_set(target_name) {
     inputs = [ _final_linker_script ]
     if (defined(invoker.inputs)) {
       inputs += invoker.inputs
diff --git a/pw_build/pw_executable.gni b/pw_build/pw_executable.gni
deleted file mode 100644
index b961803..0000000
--- a/pw_build/pw_executable.gni
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2019 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.
-
-# Wrapper for Pigweed executable build targets which uses a globally-defined,
-# configurable target type.
-template("pw_executable") {
-  target(pw_executable_config.target_type, target_name) {
-    forward_variables_from(invoker, "*")
-  }
-}
diff --git a/pw_build/target_types.gni b/pw_build/target_types.gni
new file mode 100644
index 0000000..9797763
--- /dev/null
+++ b/pw_build/target_types.gni
@@ -0,0 +1,183 @@
+# 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.
+
+# TODO(frolv): The code in all of the templates below is duplicated, with the
+# exception of the target type. This file could be auto-generated with Python.
+
+_supported_toolchain_defaults = [
+  "configs",
+  "public_deps",
+]
+
+template("pw_source_set") {
+  import("$dir_pw_build/defaults.gni")
+
+  source_set(target_name) {
+    forward_variables_from(invoker, "*", _supported_toolchain_defaults)
+
+    if (defined(pw_build_defaults.configs)) {
+      configs = pw_build_defaults.configs
+    } else {
+      configs = []
+    }
+    if (defined(remove_configs)) {
+      if (remove_configs[0] == "*") {
+        configs = []
+      } else {
+        configs -= remove_configs
+      }
+    }
+    if (defined(invoker.configs)) {
+      configs += invoker.configs
+    }
+
+    if (defined(pw_build_defaults.public_deps)) {
+      public_deps = pw_build_defaults.public_deps
+    } else {
+      public_deps = []
+    }
+    if (defined(remove_public_deps)) {
+      if (remove_public_deps[0] == "*") {
+        public_deps = []
+      } else {
+        public_deps -= remove_public_deps
+      }
+    }
+    if (defined(invoker.public_deps)) {
+      public_deps += invoker.public_deps
+    }
+  }
+}
+
+template("pw_static_library") {
+  import("$dir_pw_build/defaults.gni")
+
+  static_library(target_name) {
+    forward_variables_from(invoker, "*", _supported_toolchain_defaults)
+
+    if (defined(pw_build_defaults.configs)) {
+      configs = pw_build_defaults.configs
+    } else {
+      configs = []
+    }
+    if (defined(remove_configs)) {
+      if (remove_configs[0] == "*") {
+        configs = []
+      } else {
+        configs -= remove_configs
+      }
+    }
+    if (defined(invoker.configs)) {
+      configs += invoker.configs
+    }
+
+    if (defined(pw_build_defaults.public_deps)) {
+      public_deps = pw_build_defaults.public_deps
+    } else {
+      public_deps = []
+    }
+    if (defined(remove_public_deps)) {
+      if (remove_public_deps[0] == "*") {
+        public_deps = []
+      } else {
+        public_deps -= remove_public_deps
+      }
+    }
+    if (defined(invoker.public_deps)) {
+      public_deps += invoker.public_deps
+    }
+  }
+}
+
+template("pw_shared_library") {
+  import("$dir_pw_build/defaults.gni")
+
+  shared_library(target_name) {
+    forward_variables_from(invoker, "*", _supported_toolchain_defaults)
+
+    if (defined(pw_build_defaults.configs)) {
+      configs = pw_build_defaults.configs
+    } else {
+      configs = []
+    }
+    if (defined(remove_configs)) {
+      if (remove_configs[0] == "*") {
+        configs = []
+      } else {
+        configs -= remove_configs
+      }
+    }
+    if (defined(invoker.configs)) {
+      configs += invoker.configs
+    }
+
+    if (defined(pw_build_defaults.public_deps)) {
+      public_deps = pw_build_defaults.public_deps
+    } else {
+      public_deps = []
+    }
+    if (defined(remove_public_deps)) {
+      if (remove_public_deps[0] == "*") {
+        public_deps = []
+      } else {
+        public_deps -= remove_public_deps
+      }
+    }
+    if (defined(invoker.public_deps)) {
+      public_deps += invoker.public_deps
+    }
+  }
+}
+
+# Wrapper for Pigweed executable build targets which uses a globally-defined,
+# configurable target type.
+template("pw_executable") {
+  import("$dir_pw_build/defaults.gni")
+
+  target(pw_executable_config.target_type, target_name) {
+    forward_variables_from(invoker, "*", _supported_toolchain_defaults)
+
+    if (defined(pw_build_defaults.configs)) {
+      configs = pw_build_defaults.configs
+    } else {
+      configs = []
+    }
+    if (defined(remove_configs)) {
+      if (remove_configs[0] == "*") {
+        configs = []
+      } else {
+        configs -= remove_configs
+      }
+    }
+    if (defined(invoker.configs)) {
+      configs += invoker.configs
+    }
+
+    if (defined(pw_build_defaults.public_deps)) {
+      public_deps = pw_build_defaults.public_deps
+    } else {
+      public_deps = []
+    }
+    if (defined(remove_public_deps)) {
+      if (remove_public_deps[0] == "*") {
+        public_deps = []
+      } else {
+        public_deps -= remove_public_deps
+      }
+    }
+    if (defined(invoker.public_deps)) {
+      public_deps += invoker.public_deps
+    }
+  }
+}
diff --git a/pw_checksum/BUILD.gn b/pw_checksum/BUILD.gn
index 0a7e169..e17803b 100644
--- a/pw_checksum/BUILD.gn
+++ b/pw_checksum/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_checksum") {
+pw_source_set("pw_checksum") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_checksum/ccitt_crc16.h" ]
   sources = [ "ccitt_crc16.cc" ] + public
diff --git a/pw_containers/BUILD.gn b/pw_containers/BUILD.gn
index c5c8ae1..b1a3e49 100644
--- a/pw_containers/BUILD.gn
+++ b/pw_containers/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -26,12 +27,12 @@
   ]
 }
 
-source_set("vector") {
+pw_source_set("vector") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_containers/vector.h" ]
 }
 
-source_set("intrusive_list") {
+pw_source_set("intrusive_list") {
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_containers/internal/intrusive_list_impl.h",
diff --git a/pw_cpu_exception_armv7m/BUILD.gn b/pw_cpu_exception_armv7m/BUILD.gn
index 9bc76aa..bf79bc0 100644
--- a/pw_cpu_exception_armv7m/BUILD.gn
+++ b/pw_cpu_exception_armv7m/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -23,7 +24,7 @@
     include_dirs = [ "public" ]
   }
 
-  source_set("pw_cpu_exception_armv7m") {
+  pw_source_set("pw_cpu_exception_armv7m") {
     public_configs = [ ":default_config" ]
     deps = [
       "$dir_pw_cpu_exception:facade",
diff --git a/pw_fuzzer/BUILD.gn b/pw_fuzzer/BUILD.gn
index 9f9785a..4db5247 100644
--- a/pw_fuzzer/BUILD.gn
+++ b/pw_fuzzer/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_fuzzer/fuzzer.gni")
 import("$dir_pw_fuzzer/oss_fuzz.gni")
@@ -64,7 +65,7 @@
   ldflags = oss_fuzz_extra_ldflags
 }
 
-source_set("pw_fuzzer") {
+pw_source_set("pw_fuzzer") {
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_fuzzer/asan_interface.h",
diff --git a/pw_kvs/BUILD.gn b/pw_kvs/BUILD.gn
index 3017e5d..3656384 100644
--- a/pw_kvs/BUILD.gn
+++ b/pw_kvs/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_kvs") {
+pw_source_set("pw_kvs") {
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_kvs/alignment.h",
@@ -59,7 +60,7 @@
   friend = [ ":*" ]
 }
 
-source_set("crc16") {
+pw_source_set("crc16") {
   public = [ "public/pw_kvs/crc16_checksum.h" ]
   public_deps = [
     ":pw_kvs",
@@ -67,7 +68,7 @@
   ]
 }
 
-source_set("fake_flash") {
+pw_source_set("fake_flash") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_kvs/fake_flash_memory.h" ]
   sources = [ "fake_flash_memory.cc" ]
@@ -80,13 +81,13 @@
   deps = [ dir_pw_log ]
 }
 
-source_set("test_utils") {
+pw_source_set("test_utils") {
   public_configs = [ ":default_config" ]
   public = [ "pw_kvs_private/byte_utils.h" ]
   visibility = [ ":*" ]
 }
 
-source_set("test_partition") {
+pw_source_set("test_partition") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_kvs/flash_partition_with_stats.h" ]
   sources = [ "flash_partition_with_stats.cc" ]
diff --git a/pw_log_basic/BUILD.gn b/pw_log_basic/BUILD.gn
index 3c90005..a4f3e52 100644
--- a/pw_log_basic/BUILD.gn
+++ b/pw_log_basic/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 
 config("default_config") {
@@ -23,7 +24,7 @@
 }
 
 if (dir_pw_log_backend == dir_pw_log_basic) {
-  source_set("pw_log_basic") {
+  pw_source_set("pw_log_basic") {
     public_configs = [
       ":backend_config",
       ":default_config",
@@ -33,7 +34,7 @@
   }
 }
 
-source_set("core") {
+pw_source_set("core") {
   public_configs = [ ":default_config" ]
   public_deps = [ dir_pw_preprocessor ]
   deps = [
diff --git a/pw_log_tokenized/BUILD.gn b/pw_log_tokenized/BUILD.gn
index 2a44bae..325450f 100644
--- a/pw_log_tokenized/BUILD.gn
+++ b/pw_log_tokenized/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -23,7 +24,7 @@
   include_dirs = [ "public_overrides" ]
 }
 
-source_set("pw_log_tokenized") {
+pw_source_set("pw_log_tokenized") {
   public_configs = [
     ":backend_config",
     ":default_config",
@@ -36,7 +37,7 @@
   ]
 }
 
-source_set("core") {
+pw_source_set("core") {
   public_configs = [ ":default_config" ]
   public_deps = [
     "$dir_pw_log:facade",
diff --git a/pw_minimal_cpp_stdlib/BUILD.gn b/pw_minimal_cpp_stdlib/BUILD.gn
index 3cbe163..8e80e8f 100644
--- a/pw_minimal_cpp_stdlib/BUILD.gn
+++ b/pw_minimal_cpp_stdlib/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -23,7 +24,7 @@
   cflags = [ "-nostdinc++" ]
 }
 
-source_set("pw_minimal_cpp_stdlib") {
+pw_source_set("pw_minimal_cpp_stdlib") {
   public_configs = [ ":include_dirs" ]
   configs = [ ":no_cpp_includes" ]
   public = [
diff --git a/pw_polyfill/BUILD.gn b/pw_polyfill/BUILD.gn
index 9bcb9c9..a9d6340 100644
--- a/pw_polyfill/BUILD.gn
+++ b/pw_polyfill/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_polyfill") {
+pw_source_set("pw_polyfill") {
   public_configs = [ ":public" ]
   remove_public_deps = [ "*" ]
   public_deps = [ ":standard_library" ]
@@ -34,7 +35,7 @@
   include_dirs = [ "public_overrides" ]
 }
 
-source_set("overrides") {
+pw_source_set("overrides") {
   public_configs = [ ":overrides_config" ]
   remove_public_deps = [ "*" ]
   public_deps = [ ":standard_library" ]
@@ -50,7 +51,7 @@
   include_dirs = [ "standard_library_public" ]
 }
 
-source_set("standard_library") {
+pw_source_set("standard_library") {
   public_configs = [ ":standard_library_public" ]
   remove_public_deps = [ "*" ]
   public = [
diff --git a/pw_preprocessor/BUILD.gn b/pw_preprocessor/BUILD.gn
index a813985..8e5c1cc 100644
--- a/pw_preprocessor/BUILD.gn
+++ b/pw_preprocessor/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_preprocessor") {
+pw_source_set("pw_preprocessor") {
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_preprocessor/boolean.h",
diff --git a/pw_protobuf/BUILD.gn b/pw_protobuf/BUILD.gn
index f5f05b9..1871afc 100644
--- a/pw_protobuf/BUILD.gn
+++ b/pw_protobuf/BUILD.gn
@@ -13,7 +13,7 @@
 # the License.
 
 import("$dir_pw_build/input_group.gni")
-import("$dir_pw_build/pw_executable.gni")
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_fuzzer/fuzzer.gni")
 import("$dir_pw_protobuf_compiler/proto.gni")
@@ -23,7 +23,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_protobuf") {
+pw_source_set("pw_protobuf") {
   public_configs = [ ":default_config" ]
   public_deps = [
     "$dir_pw_status",
diff --git a/pw_protobuf_compiler/proto.gni b/pw_protobuf_compiler/proto.gni
index 4a26bdc..92b49d4 100644
--- a/pw_protobuf_compiler/proto.gni
+++ b/pw_protobuf_compiler/proto.gni
@@ -14,6 +14,7 @@
 
 import("$dir_pw_build/input_group.gni")
 import("$dir_pw_build/python_script.gni")
+import("$dir_pw_build/target_types.gni")
 
 # Python script that invokes protoc.
 _gen_script_path =
@@ -72,7 +73,7 @@
   }
 
   # Create a library with the generated source files.
-  source_set(target_name) {
+  pw_source_set(target_name) {
     all_dependent_configs = [ ":$_include_config_target" ]
     deps = [ ":$_gen_target" ]
     public_deps = [ dir_pw_protobuf ] + invoker.gen_deps
@@ -152,7 +153,7 @@
   }
 
   # Create a library with the generated source files.
-  source_set(target_name) {
+  pw_source_set(target_name) {
     all_dependent_configs = [ ":$_include_config_target" ]
     deps = [ ":$_gen_target" ]
     public_deps = [ dir_third_party_nanopb ] + invoker.gen_deps
diff --git a/pw_result/BUILD.gn b/pw_result/BUILD.gn
index 26bbb7f..c1b4370 100644
--- a/pw_result/BUILD.gn
+++ b/pw_result/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_result") {
+pw_source_set("pw_result") {
   public_configs = [ ":default_config" ]
   public_deps = [ "$dir_pw_status" ]
   public = [ "public/pw_result/result.h" ]
diff --git a/pw_ring_buffer/BUILD.gn b/pw_ring_buffer/BUILD.gn
index 0c3bedb..26cb89f 100644
--- a/pw_ring_buffer/BUILD.gn
+++ b/pw_ring_buffer/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_ring_buffer") {
+pw_source_set("pw_ring_buffer") {
   public_configs = [ ":default_config" ]
   public_deps = [
     "$dir_pw_containers",
diff --git a/pw_rpc/BUILD.gn b/pw_rpc/BUILD.gn
index 2a6b637..404429c 100644
--- a/pw_rpc/BUILD.gn
+++ b/pw_rpc/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_protobuf_compiler/proto.gni")
 import("$dir_pw_unit_test/test.gni")
@@ -34,7 +35,7 @@
          "_pw_rpc_server_library requires an implementation to be set")
   _target_name = target_name
 
-  source_set(_target_name) {
+  pw_source_set(_target_name) {
     forward_variables_from(invoker, "*")
 
     public_configs = [ ":default_config" ]
@@ -78,7 +79,7 @@
 }
 
 # Classes with no dependencies on the protobuf library for method invocations.
-source_set("common") {
+pw_source_set("common") {
   public_configs = [ ":default_config" ]
   public_deps = [
     ":protos_pwpb",
diff --git a/pw_rpc/nanopb/BUILD.gn b/pw_rpc/nanopb/BUILD.gn
index a28d3a4..998fd4e 100644
--- a/pw_rpc/nanopb/BUILD.gn
+++ b/pw_rpc/nanopb/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_unit_test/test.gni")
 
 config("config") {
@@ -19,7 +20,7 @@
   visibility = [ ":*" ]
 }
 
-source_set("nanopb") {
+pw_source_set("nanopb") {
   public_configs = [ ":config" ]
   public = [ "public_overrides/pw_rpc/internal/method.h" ]
   sources = [ "method.cc" ]
diff --git a/pw_rpc/test_impl/BUILD.gn b/pw_rpc/test_impl/BUILD.gn
index 7c34c2a..faf7325 100644
--- a/pw_rpc/test_impl/BUILD.gn
+++ b/pw_rpc/test_impl/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_unit_test/test.gni")
 
 config("config") {
@@ -19,7 +20,7 @@
   visibility = [ ":*" ]
 }
 
-source_set("test_impl") {
+pw_source_set("test_impl") {
   public_configs = [ ":config" ]
   public = [ "public_overrides/pw_rpc/internal/method.h" ]
   public_deps = [ "../:common" ]
diff --git a/pw_span/BUILD.gn b/pw_span/BUILD.gn
index 2baabbd..725b842 100644
--- a/pw_span/BUILD.gn
+++ b/pw_span/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_span") {
+pw_source_set("pw_span") {
   public_configs = [ ":default_config" ]
   public_deps = [ "$dir_pw_polyfill" ]
   public = [ "public/pw_span/span.h" ]
diff --git a/pw_status/BUILD.gn b/pw_status/BUILD.gn
index 2763068..129b993 100644
--- a/pw_status/BUILD.gn
+++ b/pw_status/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_status") {
+pw_source_set("pw_status") {
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_status/status.h",
diff --git a/pw_stream/BUILD.gn b/pw_stream/BUILD.gn
index 311eb1b..34ffe40 100644
--- a/pw_stream/BUILD.gn
+++ b/pw_stream/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_stream") {
+pw_source_set("pw_stream") {
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_stream/memory_stream.h",
diff --git a/pw_string/BUILD.gn b/pw_string/BUILD.gn
index 69513da..6bf9cce 100644
--- a/pw_string/BUILD.gn
+++ b/pw_string/BUILD.gn
@@ -13,6 +13,7 @@
 # the License.
 
 import("$dir_pw_bloat/bloat.gni")
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -20,7 +21,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_string") {
+pw_source_set("pw_string") {
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_string/format.h",
diff --git a/pw_string/size_report/BUILD.gn b/pw_string/size_report/BUILD.gn
index cb11f76..9a63744 100644
--- a/pw_string/size_report/BUILD.gn
+++ b/pw_string/size_report/BUILD.gn
@@ -12,7 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-import("$dir_pw_build/pw_executable.gni")
+import("$dir_pw_build/target_types.gni")
 
 pw_executable("single_write_snprintf") {
   sources = [ "format_single.cc" ]
diff --git a/pw_sys_io/BUILD.gn b/pw_sys_io/BUILD.gn
index 0c48cf65d..b7afcc5 100644
--- a/pw_sys_io/BUILD.gn
+++ b/pw_sys_io/BUILD.gn
@@ -13,6 +13,7 @@
 # the License.
 
 import("$dir_pw_build/facade.gni")
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 
 config("default_config") {
@@ -29,7 +30,7 @@
   public = [ "public/pw_sys_io/sys_io.h" ]
 }
 
-source_set("default_putget_bytes") {
+pw_source_set("default_putget_bytes") {
   deps = [ ":facade" ]
   sources = [ "sys_io.cc" ]
 }
diff --git a/pw_sys_io_baremetal_lm3s6965evb/BUILD.gn b/pw_sys_io_baremetal_lm3s6965evb/BUILD.gn
index d032612..47219ae 100644
--- a/pw_sys_io_baremetal_lm3s6965evb/BUILD.gn
+++ b/pw_sys_io_baremetal_lm3s6965evb/BUILD.gn
@@ -12,12 +12,13 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 
 # This if statement allows docs to always build even if the target isn't
 # compatible with this backend.
 if (dir_pw_sys_io_backend == dir_pw_sys_io_baremetal_lm3s6965evb) {
-  source_set("pw_sys_io_baremetal_lm3s6965evb") {
+  pw_source_set("pw_sys_io_baremetal_lm3s6965evb") {
     public_deps = [ "$dir_pw_boot_armv7m" ]
     deps = [
       "$dir_pw_preprocessor",
diff --git a/pw_sys_io_baremetal_stm32f429/BUILD.gn b/pw_sys_io_baremetal_stm32f429/BUILD.gn
index faa9762..f2f4bcc 100644
--- a/pw_sys_io_baremetal_stm32f429/BUILD.gn
+++ b/pw_sys_io_baremetal_stm32f429/BUILD.gn
@@ -12,12 +12,13 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 
 # This if statement allows docs to always build even if the target isn't
 # compatible with this backend.
 if (dir_pw_sys_io_backend == dir_pw_sys_io_baremetal_stm32f429) {
-  source_set("pw_sys_io_baremetal_stm32f429") {
+  pw_source_set("pw_sys_io_baremetal_stm32f429") {
     public_deps = [ "$dir_pw_boot_armv7m" ]
     deps = [
       "$dir_pw_preprocessor",
diff --git a/pw_sys_io_stdio/BUILD.gn b/pw_sys_io_stdio/BUILD.gn
index a683ab9..48a1824 100644
--- a/pw_sys_io_stdio/BUILD.gn
+++ b/pw_sys_io_stdio/BUILD.gn
@@ -12,12 +12,13 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 
 # This if statement allows docs to always build even if the target isn't
 # compatible with this backend.
 if (dir_pw_sys_io_backend == dir_pw_sys_io_stdio) {
-  source_set("pw_sys_io_stdio") {
+  pw_source_set("pw_sys_io_stdio") {
     deps = [
       "$dir_pw_sys_io:default_putget_bytes",
       "$dir_pw_sys_io:facade",
diff --git a/pw_tokenizer/BUILD.gn b/pw_tokenizer/BUILD.gn
index 50f244f..0b9e612 100644
--- a/pw_tokenizer/BUILD.gn
+++ b/pw_tokenizer/BUILD.gn
@@ -13,6 +13,7 @@
 # the License.
 
 import("$dir_pw_build/facade.gni")
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_fuzzer/fuzzer.gni")
 import("$dir_pw_unit_test/test.gni")
@@ -21,7 +22,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_tokenizer") {
+pw_source_set("pw_tokenizer") {
   public_configs = [ ":default_config" ]
   public_deps = [
     dir_pw_preprocessor,
@@ -55,7 +56,7 @@
     dir_pw_tokenizer_global_handler_with_payload_backend == "") {
   # This is an empty library to use as the backend for global_handler and
   # global_handler_with_payload tests.
-  source_set("test_backend") {
+  pw_source_set("test_backend") {
     visibility = [ ":*" ]
   }
 
@@ -87,7 +88,7 @@
   public_deps = [ ":pw_tokenizer" ]
 }
 
-source_set("base64") {
+pw_source_set("base64") {
   public_configs = [ ":default_config" ]
   public = [ "public/pw_tokenizer/base64.h" ]
   sources = [ "base64.cc" ]
@@ -98,7 +99,7 @@
   deps = [ dir_pw_base64 ]
 }
 
-source_set("decoder") {
+pw_source_set("decoder") {
   public_configs = [ ":default_config" ]
   public_deps = [ dir_pw_span ]
   deps = [ dir_pw_varint ]
@@ -322,7 +323,7 @@
 # Create a shared library for the tokenizer JNI wrapper. The include paths for
 # the JNI headers must be available in the system or provided with the
 # pw_java_native_interface_include_dirs variable.
-shared_library("detokenizer_jni") {
+pw_shared_library("detokenizer_jni") {
   public_configs = [ ":default_config" ]
   include_dirs = pw_java_native_interface_include_dirs
   sources = [ "java/dev/pigweed/tokenizer/detokenizer.cc" ]
diff --git a/pw_unit_test/BUILD.gn b/pw_unit_test/BUILD.gn
index d849614..f0b3c39 100644
--- a/pw_unit_test/BUILD.gn
+++ b/pw_unit_test/BUILD.gn
@@ -12,7 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-import("$dir_pw_build/pw_executable.gni")
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -24,7 +24,7 @@
 }
 
 # pw_unit_test core library.
-source_set("pw_unit_test") {
+pw_source_set("pw_unit_test") {
   public_configs = [ ":default_config" ]
   public_deps = [
     "$dir_pw_polyfill",
@@ -40,7 +40,7 @@
 }
 
 # Library providing an event handler which outputs human-readable text.
-source_set("simple_printing_event_handler") {
+pw_source_set("simple_printing_event_handler") {
   public_deps = [
     ":pw_unit_test",
     "$dir_pw_preprocessor",
@@ -52,7 +52,7 @@
 # Library providing a standard desktop main function for the pw_unit_test
 # framework. Unit test files can link against this library to build runnable
 # unit test executables.
-source_set("simple_printing_main") {
+pw_source_set("simple_printing_main") {
   public_deps = [ ":pw_unit_test" ]
   deps = [
     ":simple_printing_event_handler",
@@ -67,7 +67,7 @@
 
 # Library providing an event handler which logs using pw_log.
 if (dir_pw_log_backend != "") {
-  source_set("logging_event_handler") {
+  pw_source_set("logging_event_handler") {
     public_deps = [
       ":pw_unit_test",
       "$dir_pw_log",
@@ -77,7 +77,7 @@
     sources = [ "logging_event_handler.cc" ] + public
   }
 
-  source_set("logging_main") {
+  pw_source_set("logging_main") {
     public_deps = [ ":pw_unit_test" ]
     deps = [
       ":logging_event_handler",
diff --git a/pw_unit_test/test.gni b/pw_unit_test/test.gni
index 0481432..f988a65 100644
--- a/pw_unit_test/test.gni
+++ b/pw_unit_test/test.gni
@@ -12,8 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-import("$dir_pw_build/pw_executable.gni")
 import("$dir_pw_build/python_script.gni")
+import("$dir_pw_build/target_types.gni")
 
 # Defines a target if enable_if is true. Otherwise, it defines that target as
 # <target_name>_DISABLED and creates an empty <target_name> group. This can be
diff --git a/pw_varint/BUILD.gn b/pw_varint/BUILD.gn
index ffd6b90..2b80ea4 100644
--- a/pw_varint/BUILD.gn
+++ b/pw_varint/BUILD.gn
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
 
@@ -19,7 +20,7 @@
   include_dirs = [ "public" ]
 }
 
-source_set("pw_varint") {
+pw_source_set("pw_varint") {
   public_configs = [ ":default_config" ]
   public_deps = [
     "$dir_pw_preprocessor",