pw_build: Split target_types.gni

This splits target_types.gni into multiple gni files to allow
pw_executable templates to utilize pw_source_sets by importing
library_types.gni.

Change-Id: I6d8e28a0dcb53ed4e95d0c1d7ec922d013089f3b
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/51400
Reviewed-by: Joe Ethier <jethier@google.com>
Commit-Queue: Armando Montanez <amontanez@google.com>
diff --git a/pw_build/cc_executable.gni b/pw_build/cc_executable.gni
new file mode 100644
index 0000000..d922f0b
--- /dev/null
+++ b/pw_build/cc_executable.gni
@@ -0,0 +1,100 @@
+# 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.
+
+import("//build_overrides/pigweed.gni")
+
+import("$dir_pw_build/cc_library.gni")
+
+# Note: In general, prefer to import target_types.gni rather than this file.
+# cc_executable.gni and cc_library.gni are both provided by target_types.gni.
+#
+# cc_library.gni is split out from cc_executable.gni because pw_executable
+# templates may need to create pw_source_set targets internally, and can't
+# import target_types.gni because it creates a circular import path.
+
+declare_args() {
+  # The name of the GN target type used to build Pigweed executables.
+  #
+  # If this is a custom template, the .gni file containing the template must
+  # be imported at the top of the target configuration file to make it globally
+  # available.
+  pw_build_EXECUTABLE_TARGET_TYPE = "executable"
+
+  # The path to the .gni file that defines pw_build_EXECUTABLE_TARGET_TYPE.
+  #
+  # If pw_build_EXECUTABLE_TARGET_TYPE is not the default of `executable`, this
+  # .gni file is imported to provide the template definition.
+  pw_build_EXECUTABLE_TARGET_TYPE_FILE = ""
+}
+
+if (pw_build_EXECUTABLE_TARGET_TYPE != "executable" &&
+    pw_build_EXECUTABLE_TARGET_TYPE_FILE != "") {
+  import(pw_build_EXECUTABLE_TARGET_TYPE_FILE)
+}
+
+_supported_toolchain_defaults = [
+  "configs",
+  "public_deps",
+]
+
+# Wrapper for Pigweed executable build targets which uses a globally-defined,
+# configurable target type.
+template("pw_executable") {
+  _executable_output_dir = "${target_out_dir}/bin"
+  if (defined(invoker.output_dir)) {
+    _executable_output_dir = invoker.output_dir
+  }
+
+  target(pw_build_EXECUTABLE_TARGET_TYPE, target_name) {
+    import("$dir_pw_build/defaults.gni")
+
+    forward_variables_from(invoker, "*", _supported_toolchain_defaults)
+
+    if (!defined(configs)) {
+      configs = []
+    }
+    if (defined(pw_build_defaults.configs)) {
+      configs += pw_build_defaults.configs
+    }
+    if (defined(remove_configs)) {
+      if (remove_configs != [] && remove_configs[0] == "*") {
+        configs = []
+      } else {
+        configs += remove_configs  # Add configs in case they aren't already
+        configs -= remove_configs  # present, then remove them.
+      }
+    }
+    if (defined(invoker.configs)) {
+      configs += invoker.configs
+    }
+
+    public_deps = [ "$dir_pw_build:link_deps" ]
+    if (defined(pw_build_defaults.public_deps)) {
+      public_deps += pw_build_defaults.public_deps
+    }
+    if (defined(remove_public_deps)) {
+      if (remove_public_deps != [] && remove_public_deps[0] == "*") {
+        public_deps = []
+      } else {
+        public_deps += remove_public_deps
+        public_deps -= remove_public_deps
+      }
+    }
+    if (defined(invoker.public_deps)) {
+      public_deps += invoker.public_deps
+    }
+
+    output_dir = _executable_output_dir
+  }
+}