Define Linux clang target as toolchain

This change configures the Linux clang -Og target as a toolchain with
args. To support this, all Pigweed variables from pw_vars_default are
made into build args, defined within their respective modules.

The Linux clang target/toolchain is the only one that currently works.
Pigweed's other targets will be ported in later changes.

Change-Id: I051e29fde7577e41a3184c37031a4e04936404e1
diff --git a/.gitignore b/.gitignore
index d799107..4f09cea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,4 +54,6 @@
 
 # Web Tools
 node_modules
-yarn-error.log
\ No newline at end of file
+yarn-error.log
+
+nanopb
diff --git a/BUILD.gn b/BUILD.gn
index f469597..c5e5af3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -15,125 +15,142 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
+import("$dir_pigweed/modules.gni")
+import("$dir_pw_build/host_tool.gni")
 import("$dir_pw_unit_test/test.gni")
+declare_args() {
+  pw_IS_HOST_TOOLCHAIN = false
+}
+
+# Enumerate all of the different targets that Pigweed will build.
 group("default") {
-  deps = [ ":pigweed_default($pw_target_toolchain)" ]
+  _host_target = "$dir_pigweed/targets/host/linux:clang_og"
+
+  deps = [ ":pigweed_default($_host_target)" ]
 }
 
 # By default, Pigweed will build this target when invoking ninja.
 group("pigweed_default") {
   deps = []
-  if (defined(pw_is_docs_target) && pw_is_docs_target) {
-    deps += [ "$dir_pigweed/docs" ]
-  } else {
-    if (pw_automatic_test_runner == "") {
-      # Without a test runner defined, build the tests but don't run them.
-      deps += [ ":pw_module_tests" ]
+
+  # Prevent the default toolchain from parsing any other BUILD.gn files.
+  if (current_toolchain != default_toolchain) {
+    if (defined(pw_is_docs_target) && pw_is_docs_target) {
+      deps += [ "$dir_pigweed/docs" ]
     } else {
-      # With a test runner, depend on the run targets so they run with the
-      # build.
-      deps += [ ":pw_module_tests_run" ]
+      if (pw_unit_test_AUTOMATIC_RUNNER == "") {
+        # Without a test runner defined, build the tests but don't run them.
+        deps += [ ":pw_module_tests" ]
+      } else {
+        # With a test runner, depend on the run targets so they run with the
+        # build.
+        deps += [ ":pw_module_tests_run" ]
+      }
+    }
+    if (pw_IS_HOST_TOOLCHAIN) {
+      deps += [ ":host_tools" ]
     }
   }
-  if (pw_build_host_tools) {
-    deps += [ ":host_tools" ]
-  }
 }
 
-group("host_tools") {
-  deps = [
-    "$dir_pw_target_runner/go:simple_client",
-    "$dir_pw_target_runner/go:simple_server",
-  ]
-}
-
-group("pw_facades") {
-  deps = [
-    "$dir_pw_cpu_exception",
-    "$dir_pw_sys_io",
-  ]
-}
-
-# All Pigweed modules that can be built using gn. This is not built by default.
-group("pw_modules") {
-  deps = [
-    "$dir_pigweed/docs",
-    "$dir_pw_allocator",
-    "$dir_pw_base64",
-    "$dir_pw_checksum",
-    "$dir_pw_polyfill",
-    "$dir_pw_preprocessor",
-    "$dir_pw_protobuf",
-    "$dir_pw_result",
-    "$dir_pw_span",
-    "$dir_pw_status",
-    "$dir_pw_stream",
-    "$dir_pw_string",
-    "$dir_pw_trace",
-    "$dir_pw_unit_test",
-    "$dir_pw_varint",
-  ]
-
-  if (host_os != "win") {
-    deps += [
-      # TODO(frolv): Remove these two when new KVS is ready.
-      "$dir_pw_kvs",
-      "$dir_pw_minimal_cpp_stdlib",
-
-      # TODO(pwbug/111): Remove this when building successfully on Windows.
-      "$dir_pw_tokenizer",
+# Prevent the default toolchain from parsing any other BUILD.gn files.
+if (current_toolchain != default_toolchain) {
+  group("host_tools") {
+    deps = [
+      "$dir_pw_target_runner/go:simple_client",
+      "$dir_pw_target_runner/go:simple_server",
     ]
   }
-}
 
-# Targets for all module unit test groups.
-pw_test_group("pw_module_tests") {
-  group_deps = [
-    "$dir_pw_allocator:tests",
-    "$dir_pw_assert:tests",
-    "$dir_pw_base64:tests",
-    "$dir_pw_checksum:tests",
-    "$dir_pw_containers:tests",
-    "$dir_pw_fuzzer:tests",
-    "$dir_pw_log:tests",
-    "$dir_pw_log_tokenized:tests",
-    "$dir_pw_polyfill:tests",
-    "$dir_pw_preprocessor:tests",
-    "$dir_pw_protobuf:tests",
-    "$dir_pw_protobuf_compiler:tests",
-    "$dir_pw_result:tests",
-    "$dir_pw_ring_buffer:tests",
-    "$dir_pw_rpc:tests",
-    "$dir_pw_span:tests",
-    "$dir_pw_status:tests",
-    "$dir_pw_stream:tests",
-    "$dir_pw_string:tests",
-    "$dir_pw_tokenizer:tests",
-    "$dir_pw_trace:tests",
-    "$dir_pw_unit_test:tests",
-    "$dir_pw_varint:tests",
-  ]
-
-  # TODO(pwbug/17): Re-think when Pigweed config system is added.
-  if (dir_pw_cpu_exception_backend == dir_pw_cpu_exception_armv7m) {
-    group_deps += [ "$dir_pw_cpu_exception_armv7m:tests" ]
+  group("pw_facades") {
+    deps = [
+      "$dir_pw_cpu_exception",
+      "$dir_pw_sys_io",
+    ]
   }
 
-  if (pw_build_host_tools) {
-    # TODO(pwbug/196): KVS tests are not compatible with device builds as they
-    # use features such as std::map and are computationally expensive. Solving
-    # this requires a more complex capabilities-based build and configuration
-    # system which allowing enabling specific tests for targets that support
-    # them and modifying test parameters for different targets.
-    #
-    # Checking for pw_build_host_tools (which is only set by the host) is a
-    # temporary fix until the problem can be properly solved.
-    group_deps += [ "$dir_pw_kvs:tests" ]
+  # All Pigweed modules that can be built using gn. This is not built by default.
+  group("pw_modules") {
+    deps = [
+      "$dir_pigweed/docs",
+      "$dir_pw_allocator",
+      "$dir_pw_base64",
+      "$dir_pw_checksum",
+      "$dir_pw_polyfill",
+      "$dir_pw_preprocessor",
+      "$dir_pw_protobuf",
+      "$dir_pw_result",
+      "$dir_pw_span",
+      "$dir_pw_status",
+      "$dir_pw_stream",
+      "$dir_pw_string",
+      "$dir_pw_trace",
+      "$dir_pw_unit_test",
+      "$dir_pw_varint",
+    ]
+
+    if (host_os != "win") {
+      deps += [
+        # TODO(frolv): Remove these two when new KVS is ready.
+        "$dir_pw_kvs",
+        "$dir_pw_minimal_cpp_stdlib",
+
+        # TODO(pwbug/111): Remove this when building successfully on Windows.
+        "$dir_pw_tokenizer",
+      ]
+    }
   }
 
-  if (host_os != "win") {
-    # TODO(amontanez): pw_minimal_cpp_stdlib tests do not build on windows.
-    group_deps += [ "$dir_pw_minimal_cpp_stdlib:tests" ]
+  # Targets for all module unit test groups.
+  pw_test_group("pw_module_tests") {
+    group_deps = [
+      "$dir_pw_allocator:tests",
+      "$dir_pw_assert:tests",
+      "$dir_pw_base64:tests",
+      "$dir_pw_checksum:tests",
+      "$dir_pw_containers:tests",
+      "$dir_pw_fuzzer:tests",
+      "$dir_pw_log:tests",
+      "$dir_pw_log_tokenized:tests",
+      "$dir_pw_polyfill:tests",
+      "$dir_pw_preprocessor:tests",
+      "$dir_pw_protobuf:tests",
+      "$dir_pw_protobuf_compiler:tests",
+      "$dir_pw_result:tests",
+      "$dir_pw_ring_buffer:tests",
+      "$dir_pw_rpc:tests",
+      "$dir_pw_span:tests",
+      "$dir_pw_status:tests",
+      "$dir_pw_stream:tests",
+      "$dir_pw_string:tests",
+      "$dir_pw_tokenizer:tests",
+      "$dir_pw_trace:tests",
+      "$dir_pw_unit_test:tests",
+      "$dir_pw_varint:tests",
+    ]
+
+    import("$dir_pw_cpu_exception/backend.gni")
+
+    # TODO(pwbug/17): Re-think when Pigweed config system is added.
+    if (pw_cpu_exception_BACKEND == dir_pw_cpu_exception_armv7m) {
+      group_deps += [ "$dir_pw_cpu_exception_armv7m:tests" ]
+    }
+
+    if (pw_build_HOST_TOOLS) {
+      # TODO(pwbug/196): KVS tests are not compatible with device builds as they
+      # use features such as std::map and are computationally expensive. Solving
+      # this requires a more complex capabilities-based build and configuration
+      # system which allowing enabling specific tests for targets that support
+      # them and modifying test parameters for different targets.
+      #
+      # Checking for pw_build_host_tools (which is only set by the host) is a
+      # temporary fix until the problem can be properly solved.
+      group_deps += [ "$dir_pw_kvs:tests" ]
+    }
+
+    if (host_os != "win") {
+      # TODO(amontanez): pw_minimal_cpp_stdlib tests do not build on windows.
+      group_deps += [ "$dir_pw_minimal_cpp_stdlib:tests" ]
+    }
   }
 }
diff --git a/BUILDCONFIG.gn b/BUILDCONFIG.gn
index 42640b0..dbf7ed4 100644
--- a/BUILDCONFIG.gn
+++ b/BUILDCONFIG.gn
@@ -16,30 +16,13 @@
 # new project, you'll need to copy this file to your project and then modify it
 # to fit your needs. Due to the way Pigweed handles file imports, you won't be
 # able to simply import this file in your own BUILDCONFIG.gn.
-#
-# Keep in mind when importing .gni files that `gn format` will try to
-# alphabetically sort imports unless they're separated by comments. For this
-# file, import order matters (modules.gni MUST be imported first).
 
 # This is imported into a scope so as not to pollute the global variable space.
 _pigweed_directory = {
   import("//build_overrides/pigweed.gni")
 }
 
-_pigweed_modules = {
-  # Import target configuration. This is what "completes" a Pigweed
-  # configuration. This file should set a default toolchain, configure
-  # pw_executable, select backends to build against, and provide target-specific
-  # build arguments.
-  import("${_pigweed_directory.dir_pigweed}/legacy_target.gni")
-}
-
-# Ensure some sort of default toolchain was provided by the target, and then
-# set the default toolchain.
-assert(_pigweed_modules.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("${_pigweed_modules.dir_pw_toolchain}/dummy")
+set_default_toolchain("${_pigweed_directory.dir_pw_toolchain}/dummy")
diff --git a/legacy_target.gni b/legacy_target.gni
index 7347af6..3519108 100644
--- a/legacy_target.gni
+++ b/legacy_target.gni
@@ -13,17 +13,3 @@
 # the License.
 
 import("//build_overrides/pigweed.gni")
-
-# This file uses the old method of declaring targets via global defines in a
-# .gni file. We're transitioning to declaring all target config options as
-# individual build args that toolchains can manage.
-
-declare_args() {
-  # Path to the Pigweed variables config file for the build target.
-  #
-  # When this is changed, you must run `ninja -t clean` to remove any files from
-  # the previous target's build before building again.
-  pw_target_config = "$dir_pigweed/targets/host/target_config.gni"
-}
-
-import(pw_target_config)
diff --git a/pw_assert/BUILD.gn b/pw_assert/BUILD.gn
index db3c184..417e0b2 100644
--- a/pw_assert/BUILD.gn
+++ b/pw_assert/BUILD.gn
@@ -15,16 +15,20 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/facade.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
+declare_args() {
+  # Backend for the pw_assert module.
+  pw_assert_BACKEND = ""
+}
+
 config("default_config") {
   include_dirs = [ "public" ]
 }
 
 pw_facade("pw_assert") {
-  backend = dir_pw_assert_backend
+  backend = pw_assert_BACKEND
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_assert/assert.h",
@@ -54,15 +58,15 @@
   deps = [ dir_pw_status ]
 
   # TODO(frolv): Fix this test on the QEMU target.
-  enable_if = pw_executable_config.target_type != "lm3s6965evb_executable"
+  enable_if = pw_build_EXECUTABLE_TARGET_TYPE != "lm3s6965evb_executable"
 }
 
 pw_test("assert_backend_compile_test") {
-  enable_if = dir_pw_assert_backend != ""
+  enable_if = pw_assert_BACKEND != ""
   deps = [
     ":pw_assert",
-    dir_pw_assert_backend,
     dir_pw_status,
+    pw_assert_BACKEND,
   ]
   sources = [
     "assert_backend_compile_test.c",
diff --git a/pw_assert_basic/BUILD.gn b/pw_assert_basic/BUILD.gn
index 311ab19..b885a90 100644
--- a/pw_assert_basic/BUILD.gn
+++ b/pw_assert_basic/BUILD.gn
@@ -26,16 +26,14 @@
   include_dirs = [ "public_overrides" ]
 }
 
-if (dir_pw_assert_backend == dir_pw_assert_basic) {
-  pw_source_set("pw_assert_basic") {
-    public_configs = [
-      ":backend_config",
-      ":default_config",
-    ]
-    deps = [ ":core" ]
-    public = [ "public_overrides/pw_assert_backend/assert_backend.h" ]
-    sources = public
-  }
+pw_source_set("pw_assert_basic") {
+  public_configs = [
+    ":backend_config",
+    ":default_config",
+  ]
+  deps = [ ":core" ]
+  public = [ "public_overrides/pw_assert_backend/assert_backend.h" ]
+  sources = public
 }
 
 pw_source_set("core") {
diff --git a/pw_base64/BUILD.gn b/pw_base64/BUILD.gn
index b421afb..47b95c7 100644
--- a/pw_base64/BUILD.gn
+++ b/pw_base64/BUILD.gn
@@ -15,7 +15,6 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
diff --git a/pw_bloat/bloat.gni b/pw_bloat/bloat.gni
index 6443c3c..69aa222 100644
--- a/pw_bloat/bloat.gni
+++ b/pw_bloat/bloat.gni
@@ -17,6 +17,25 @@
 
 import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/python_script.gni")
+declare_args() {
+  # Path to the Bloaty configuration file that defines the memory layout and
+  # capacities for the target binaries.
+  pw_bloat_BLOATY_CONFIG = ""
+
+  # List of toolchains to use in pw_toolchain_size_report templates.
+  #
+  # Each entry is a scope containing the following variables:
+  #
+  #   name: Human-readable toolchain name.
+  #   target: GN target that defines the toolchain.
+  #   linker_script: Optional path to a linker script file to build for the
+  #     toolchain's target.
+  #   bloaty_config: Optional Bloaty confirugation file defining the memory
+  #     layout of the binaries as specified in the linker script.
+  #
+  # If this list is empty, pw_toolchain_size_report targets become no-ops.
+  pw_bloat_TOOLCHAINS = []
+}
 
 # Creates a target which runs a size report diff on a set of executables.
 #
@@ -98,8 +117,9 @@
     if (defined(binary.bloaty_config)) {
       _bloaty_configs += [ get_path_info(binary.bloaty_config, "abspath") ]
     } else {
-      _bloaty_configs +=
-          [ get_path_info(pw_executable_config.bloaty_config_file, "abspath") ]
+      assert(pw_bloat_BLOATY_CONFIG != "",
+             "Target must provide a default bloaty config")
+      _bloaty_configs += [ get_path_info(pw_bloat_BLOATY_CONFIG, "abspath") ]
     }
 
     _base_dir = get_label_info(_binary_base, "target_out_dir")
@@ -182,7 +202,7 @@
 
 # Creates a report card comparing the sizes of the same binary compiled with
 # different toolchains. The toolchains to use are listed in the build variable
-# pw_size_report_toolchains.
+# pw_bloat_TOOLCHAINS.
 #
 # Args:
 #   base_executable: Scope containing a list of variables defining an executable
@@ -222,7 +242,7 @@
   # Create a base and diff executable for each toolchain, adding the toolchain's
   # linker script to the link flags for the executable, and add them all to a
   # list of binaries for the pw_size_report template.
-  foreach(_toolchain, pw_size_report_toolchains) {
+  foreach(_toolchain, pw_bloat_TOOLCHAINS) {
     _prefix = "_${target_name}_${i}_pw_size"
 
     # Create a config which adds the toolchain's linker script as a linker flag
@@ -294,7 +314,7 @@
       binaries = _size_report_binaries
     }
   } else {
-    # If no toolchains are listed in pw_size_report_toolchains, prevent GN from
+    # If no toolchains are listed in pw_bloat_TOOLCHAINS, prevent GN from
     # complaining about unused variables and run a script that outputs a ReST
     # warning to the size report file.
     not_needed("*")
diff --git a/pw_boot_armv7m/BUILD.gn b/pw_boot_armv7m/BUILD.gn
index 01bbc1d..7857557 100644
--- a/pw_boot_armv7m/BUILD.gn
+++ b/pw_boot_armv7m/BUILD.gn
@@ -19,16 +19,25 @@
 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) {
+declare_args() {
+  # TODO(frolv): Move this into the pw_boot module.
+  pw_boot_BACKEND = ""
+
+  # Module configuration options for pw_boot_armv7m.
+  pw_boot_armv7m_CONFIG = {
+    # C Preprocessor defines used for linker script configuration.
+    defines = []
+  }
+}
+
+if (pw_boot_BACKEND == dir_pw_boot_armv7m) {
   config("default_config") {
     include_dirs = [ "public" ]
   }
 
   pw_linker_script("armv7m_linker_script") {
-    # pw_boot_armv7m_config is a scope provided by the target.
-    assert(defined(pw_boot_armv7m_config),
-           "pw_boot_armv7m depends on pw_boot_armv7m_config being defined!")
-    defines = pw_boot_armv7m_config.defines
+    # pw_boot_armv7m_CONFIG is a scope provided by the target.
+    defines = pw_boot_armv7m_CONFIG.defines
     linker_script = "basic_armv7m.ld"
   }
 
diff --git a/pw_build/host_tool.gni b/pw_build/host_tool.gni
index cc0fde9..b9890bb 100644
--- a/pw_build/host_tool.gni
+++ b/pw_build/host_tool.gni
@@ -14,7 +14,12 @@
 
 import("python_script.gni")
 
-if (pw_build_host_tools) {
+declare_args() {
+  # Whether to build host-side tooling.
+  pw_build_HOST_TOOLS = false
+}
+
+if (pw_build_HOST_TOOLS) {
   # Defines a Pigweed host tool and installs it into the host_tools directory.
   #
   # Args:
@@ -70,4 +75,4 @@
     group(target_name) {
     }
   }
-}  # pw_build_host_tools
+}  # pw_build_HOST_TOOLS
diff --git a/pw_build/target_types.gni b/pw_build/target_types.gni
index 98b6aca..f714f22 100644
--- a/pw_build/target_types.gni
+++ b/pw_build/target_types.gni
@@ -14,8 +14,14 @@
 
 # gn-format disable
 import("//build_overrides/pigweed.gni")
-
-import("$dir_pigweed/legacy_target.gni")
+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"
+}
 
 # 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.
@@ -150,7 +156,7 @@
 template("pw_executable") {
   import("$dir_pw_build/defaults.gni")
 
-  target(pw_executable_config.target_type, target_name) {
+  target(pw_build_EXECUTABLE_TARGET_TYPE, target_name) {
     forward_variables_from(invoker, "*", _supported_toolchain_defaults)
 
     if (defined(pw_build_defaults.configs)) {
diff --git a/pw_cpu_exception/BUILD.gn b/pw_cpu_exception/BUILD.gn
index 839c6f1..d90b1c7 100644
--- a/pw_cpu_exception/BUILD.gn
+++ b/pw_cpu_exception/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright 2019 The Pigweed Authors
+# 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
@@ -15,7 +15,6 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/facade.gni")
 import("$dir_pw_docgen/docs.gni")
 config("default_config") {
@@ -23,7 +22,7 @@
 }
 
 pw_facade("pw_cpu_exception") {
-  backend = dir_pw_cpu_exception_backend
+  backend = pw_cpu_exception_BACKEND
   public_configs = [ ":default_config" ]
   public_deps = [
     "$dir_pw_preprocessor",
diff --git a/targets/host/linux.gni b/pw_cpu_exception/backend.gni
similarity index 63%
copy from targets/host/linux.gni
copy to pw_cpu_exception/backend.gni
index 245154a..adc62ae 100644
--- a/targets/host/linux.gni
+++ b/pw_cpu_exception/backend.gni
@@ -1,4 +1,4 @@
-# Copyright 2019 The Pigweed Authors
+# 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
@@ -12,14 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-import("host_common.gni")
-
 declare_args() {
-  # Specifies the toolchain to use for this build.
-  pw_target_toolchain = "$dir_pw_toolchain:host_clang_og"
+  # Backend for the pw_cpu_exception module.
+  pw_cpu_exception_BACKEND = ""
 }
-
-pw_executable_config.bloaty_config_file =
-    get_path_info("linux.bloaty", "abspath")
-
-pw_automatic_test_runner = get_path_info("run_test", "abspath")
diff --git a/pw_log/BUILD.gn b/pw_log/BUILD.gn
index 10c5cd7..203739e 100644
--- a/pw_log/BUILD.gn
+++ b/pw_log/BUILD.gn
@@ -15,16 +15,20 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/facade.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
+declare_args() {
+  # Backend for the pw_log module.
+  pw_log_BACKEND = ""
+}
+
 config("default_config") {
   include_dirs = [ "public" ]
 }
 
 pw_facade("pw_log") {
-  backend = dir_pw_log_backend
+  backend = pw_log_BACKEND
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_log/levels.h",
@@ -37,11 +41,11 @@
 }
 
 pw_test("basic_log_test") {
-  enable_if = dir_pw_log_backend != ""
+  enable_if = pw_log_BACKEND != ""
   deps = [
     ":pw_log",
-    dir_pw_log_backend,
     dir_pw_preprocessor,
+    pw_log_BACKEND,
   ]
 
   sources = [
diff --git a/pw_log_basic/BUILD.gn b/pw_log_basic/BUILD.gn
index e04bd5c..cfeb7df 100644
--- a/pw_log_basic/BUILD.gn
+++ b/pw_log_basic/BUILD.gn
@@ -26,15 +26,13 @@
   include_dirs = [ "public_overrides" ]
 }
 
-if (dir_pw_log_backend == dir_pw_log_basic) {
-  pw_source_set("pw_log_basic") {
-    public_configs = [
-      ":backend_config",
-      ":default_config",
-    ]
-    public = [ "public_overrides/pw_log_backend/log_backend.h" ]
-    public_deps = [ ":core" ]
-  }
+pw_source_set("pw_log_basic") {
+  public_configs = [
+    ":backend_config",
+    ":default_config",
+  ]
+  public = [ "public_overrides/pw_log_backend/log_backend.h" ]
+  public_deps = [ ":core" ]
 }
 
 pw_source_set("core") {
diff --git a/pw_log_tokenized/BUILD.gn b/pw_log_tokenized/BUILD.gn
index b5b0acd..543f789 100644
--- a/pw_log_tokenized/BUILD.gn
+++ b/pw_log_tokenized/BUILD.gn
@@ -18,6 +18,7 @@
 import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
+import("$dir_pw_tokenizer/backend.gni")
 import("$dir_pw_unit_test/test.gni")
 config("default_config") {
   include_dirs = [ "public" ]
@@ -58,7 +59,7 @@
   deps = [ ":pw_log_tokenized" ]
 
   # TODO(hepler): Switch this to a facade test when available.
-  enable_if = dir_pw_tokenizer_global_handler_with_payload_backend == ""
+  enable_if = pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND == ""
 }
 
 pw_doc_group("docs") {
diff --git a/pw_protobuf_compiler/BUILD.gn b/pw_protobuf_compiler/BUILD.gn
index e36c286..4b3c483 100644
--- a/pw_protobuf_compiler/BUILD.gn
+++ b/pw_protobuf_compiler/BUILD.gn
@@ -15,7 +15,6 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/input_group.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_protobuf_compiler/proto.gni")
@@ -24,8 +23,8 @@
   sources = [ "docs.rst" ]
 }
 
-_compiling_for_nanopb = pw_protobuf_generators + [ "nanopb" ] - [ "nanopb" ] !=
-                        pw_protobuf_generators
+_compiling_for_nanopb = pw_protobuf_GENERATORS + [ "nanopb" ] - [ "nanopb" ] !=
+                        pw_protobuf_GENERATORS
 
 pw_test_group("tests") {
   tests = []
diff --git a/pw_protobuf_compiler/docs.rst b/pw_protobuf_compiler/docs.rst
index a510d2c..43a4355 100644
--- a/pw_protobuf_compiler/docs.rst
+++ b/pw_protobuf_compiler/docs.rst
@@ -24,9 +24,9 @@
 | Go          | ``go``     | Compiles using the standard Go protobuf plugin    |
 |             |            | with gRPC service support.                        |
 +-------------+------------+---------------------------------------------------+
-| Nanopb      | ``nanopb`` | Compiles using Nanopb. The build variable         |
-|             |            | ``dir_third_party_nanopb`` must be set to point   |
-|             |            | to a local nanopb installation.                   |
+| Nanopb      | ``nanopb`` | Compiles using Nanopb. The build argument         |
+|             |            | ``dir_pw_third_party_nanopb`` must be set to      |
+|             |            | point to a local nanopb installation.             |
 +-------------+------------+---------------------------------------------------+
 
 The build variable ``pw_protobuf_generators`` tells the module the generators
diff --git a/targets/host/linux.gni b/pw_protobuf_compiler/nanopb.gni
similarity index 63%
copy from targets/host/linux.gni
copy to pw_protobuf_compiler/nanopb.gni
index 245154a..3c3be32 100644
--- a/targets/host/linux.gni
+++ b/pw_protobuf_compiler/nanopb.gni
@@ -1,4 +1,4 @@
-# Copyright 2019 The Pigweed Authors
+# 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
@@ -12,14 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-import("host_common.gni")
-
 declare_args() {
-  # Specifies the toolchain to use for this build.
-  pw_target_toolchain = "$dir_pw_toolchain:host_clang_og"
+  # If compiling protos for nanopb, this variable is set to the path to the
+  # nanopb installation.
+  dir_pw_third_party_nanopb = ""
 }
-
-pw_executable_config.bloaty_config_file =
-    get_path_info("linux.bloaty", "abspath")
-
-pw_automatic_test_runner = get_path_info("run_test", "abspath")
diff --git a/pw_protobuf_compiler/proto.gni b/pw_protobuf_compiler/proto.gni
index 58ed4e7..197cacc 100644
--- a/pw_protobuf_compiler/proto.gni
+++ b/pw_protobuf_compiler/proto.gni
@@ -19,6 +19,17 @@
 import("$dir_pw_build/input_group.gni")
 import("$dir_pw_build/python_script.gni")
 import("$dir_pw_build/target_types.gni")
+declare_args() {
+  # Generators with which to compile protobuf code. These are used by the
+  # pw_proto_library template to determine which build targets to create.
+  #
+  # Supported generators:
+  #   "pwpb", "nanopb", "go"
+  pw_protobuf_GENERATORS = [
+    "pwpb",
+    "go",
+  ]
+}
 
 # Python script that invokes protoc.
 _gen_script_path =
@@ -93,8 +104,8 @@
 # Args:
 #  protos: List of input .proto files.
 template("_pw_nanopb_proto_library") {
-  assert(defined(dir_third_party_nanopb) && dir_third_party_nanopb != "",
-         "\$dir_third_party_nanopb must be set to compile nanopb protobufs")
+  assert(defined(dir_pw_third_party_nanopb) && dir_pw_third_party_nanopb != "",
+         "\$dir_pw_third_party_nanopb must be set to compile nanopb protobufs")
 
   _proto_gen_dir = "$root_gen_dir/protos"
   _module_path = get_path_info(".", "abspath")
@@ -110,7 +121,7 @@
     ]
   }
 
-  _nanopb_plugin = "$dir_third_party_nanopb/generator/protoc-gen-nanopb"
+  _nanopb_plugin = "$dir_pw_third_party_nanopb/generator/protoc-gen-nanopb"
   if (host_os == "win") {
     _nanopb_plugin += ".bat"
   }
@@ -127,7 +138,7 @@
              "--module-path",
              _module_path,
              "--include-paths",
-             "$dir_third_party_nanopb/generator/proto",
+             "$dir_pw_third_party_nanopb/generator/proto",
              "--include-file",
              invoker.include_file,
              "--out-dir",
@@ -160,7 +171,7 @@
   pw_source_set(target_name) {
     all_dependent_configs = [ ":$_include_config_target" ]
     deps = [ ":$_gen_target" ]
-    public_deps = [ dir_third_party_nanopb ] + invoker.gen_deps
+    public_deps = [ dir_pw_third_party_nanopb ] + invoker.gen_deps
     sources = get_target_outputs(":$_gen_target")
     public = filter_include(sources, [ "*.pb.h" ])
   }
@@ -204,14 +215,14 @@
 
 # Generates protobuf code from .proto definitions for various languages.
 #
-# The generators to use are defined in the pw_protobuf_generators build
+# The generators to use are defined in the pw_protobuf_GENERATORS build
 # variable. Each listed generator creates a generated code target called
 #
 #   <target_name>_<generator>
 #
 # For example, with the following definitions:
 #
-#   pw_protobuf_generators = [ "pwpb", "py" ]
+#   pw_protobuf_GENERATORS = [ "pwpb", "py" ]
 #
 #   pw_proto_library("my_protos") {
 #     sources = [ "foo.proto" ]
@@ -261,7 +272,7 @@
     _deps += [ ":$_input_target_name" ]
   }
 
-  foreach(_gen, pw_protobuf_generators) {
+  foreach(_gen, pw_protobuf_GENERATORS) {
     _lang_target = "${target_name}_${_gen}"
     _gen_deps = []
     if (defined(invoker.deps)) {
@@ -315,7 +326,7 @@
   ]
 
   # Create stub versions of the proto library for other protobuf generators.
-  foreach(_gen, _protobuf_generators - pw_protobuf_generators) {
+  foreach(_gen, _protobuf_generators - pw_protobuf_GENERATORS) {
     pw_python_script("${target_name}_${_gen}") {
       forward_variables_from(invoker, _forwarded_vars)
       script = string_join("/",
@@ -353,7 +364,7 @@
              get_path_info(".", "abspath"),
              "--root",
              "//",
-           ] + pw_protobuf_generators
+           ] + pw_protobuf_GENERATORS
     stamp = true
   }
 }
diff --git a/pw_rpc/BUILD.gn b/pw_rpc/BUILD.gn
index cc65316..28aedf6 100644
--- a/pw_rpc/BUILD.gn
+++ b/pw_rpc/BUILD.gn
@@ -15,7 +15,6 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_protobuf_compiler/proto.gni")
diff --git a/pw_rpc/nanopb/BUILD.gn b/pw_rpc/nanopb/BUILD.gn
index 5c02676..a8916f4 100644
--- a/pw_rpc/nanopb/BUILD.gn
+++ b/pw_rpc/nanopb/BUILD.gn
@@ -15,8 +15,8 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/target_types.gni")
+import("$dir_pw_protobuf_compiler/nanopb.gni")
 import("$dir_pw_unit_test/test.gni")
 config("config") {
   include_dirs = [ "public_overrides" ]
@@ -34,8 +34,8 @@
     dir_pw_status,
   ]
 
-  if (dir_third_party_nanopb != "") {
-    public_deps += [ dir_third_party_nanopb ]
+  if (dir_pw_third_party_nanopb != "") {
+    public_deps += [ dir_pw_third_party_nanopb ]
   }
 
   visibility = [ "../*" ]
@@ -48,5 +48,5 @@
     "..:test_utils_nanopb_server",
   ]
   sources = [ "method_test.cc" ]
-  enable_if = dir_third_party_nanopb != ""
+  enable_if = dir_pw_third_party_nanopb != ""
 }
diff --git a/pw_sys_io/BUILD.gn b/pw_sys_io/BUILD.gn
index aeb8eb5..ce2b30f 100644
--- a/pw_sys_io/BUILD.gn
+++ b/pw_sys_io/BUILD.gn
@@ -15,16 +15,20 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/facade.gni")
 import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
+declare_args() {
+  # Backend for the pw_sys_io module.
+  pw_sys_io_BACKEND = ""
+}
+
 config("default_config") {
   include_dirs = [ "public" ]
 }
 
 pw_facade("pw_sys_io") {
-  backend = dir_pw_sys_io_backend
+  backend = pw_sys_io_BACKEND
   public_configs = [ ":default_config" ]
   public_deps = [
     "$dir_pw_span",
diff --git a/pw_sys_io_stdio/BUILD.gn b/pw_sys_io_stdio/BUILD.gn
index f9b8d4a..135b65a 100644
--- a/pw_sys_io_stdio/BUILD.gn
+++ b/pw_sys_io_stdio/BUILD.gn
@@ -18,17 +18,12 @@
 import("$dir_pigweed/legacy_target.gni")
 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) {
-  pw_source_set("pw_sys_io_stdio") {
-    deps = [
-      "$dir_pw_sys_io:default_putget_bytes",
-      "$dir_pw_sys_io:facade",
-    ]
-    sources = [ "sys_io.cc" ]
-  }
+pw_source_set("pw_sys_io_stdio") {
+  deps = [
+    "$dir_pw_sys_io:default_putget_bytes",
+    "$dir_pw_sys_io:facade",
+  ]
+  sources = [ "sys_io.cc" ]
 }
 
 pw_doc_group("docs") {
diff --git a/pw_tokenizer/BUILD.gn b/pw_tokenizer/BUILD.gn
index 60af352..1c967dd 100644
--- a/pw_tokenizer/BUILD.gn
+++ b/pw_tokenizer/BUILD.gn
@@ -21,6 +21,7 @@
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_fuzzer/fuzzer.gni")
 import("$dir_pw_unit_test/test.gni")
+import("backend.gni")
 config("default_config") {
   include_dirs = [ "public" ]
 }
@@ -55,16 +56,16 @@
 # As a temporary workaround, if no backend is set, use an empty test backend so
 # that the test can define the handler function.
 # TODO(hepler): Switch this to a facade test when available.
-if (dir_pw_tokenizer_global_handler_backend == "" &&
-    dir_pw_tokenizer_global_handler_with_payload_backend == "") {
+if (pw_tokenizer_GLOBAL_HANDLER_BACKEND == "" &&
+    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.
   pw_source_set("test_backend") {
     visibility = [ ":*" ]
   }
 
-  dir_pw_tokenizer_global_handler_backend = ":test_backend"
-  dir_pw_tokenizer_global_handler_with_payload_backend = ":test_backend"
+  pw_tokenizer_GLOBAL_HANDLER_BACKEND = ":test_backend"
+  pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND = ":test_backend"
 
   enable_global_handler_test = true
 } else {
@@ -73,7 +74,7 @@
 
 pw_facade("global_handler") {
   facade_name = "global_handler_facade"
-  backend = dir_pw_tokenizer_global_handler_backend
+  backend = pw_tokenizer_GLOBAL_HANDLER_BACKEND
 
   public_configs = [ ":default_config" ]
   public = [ "public/pw_tokenizer/tokenize_to_global_handler.h" ]
@@ -83,7 +84,7 @@
 
 pw_facade("global_handler_with_payload") {
   facade_name = "global_handler_with_payload_facade"
-  backend = dir_pw_tokenizer_global_handler_with_payload_backend
+  backend = pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND
 
   public_configs = [ ":default_config" ]
   public = [ "public/pw_tokenizer/tokenize_to_global_handler_with_payload.h" ]
@@ -309,26 +310,26 @@
 }
 
 declare_args() {
-  # pw_java_native_interface_include_dirs specifies the paths to use for
+  # pw_JAVA_NATIVE_INTERFACE_INCLUDE_DIRS specifies the paths to use for
   # building Java Native Interface libraries. If no paths are provided, targets
   # that require JNI may not build correctly.
   #
   # Example JNI include paths for a Linux system:
   #
-  #   pw_java_native_interface_include_dirs = [
+  #   pw_JAVA_NATIVE_INTERFACE_INCLUDE_DIRS = [
   #     "/usr/local/buildtools/java/jdk/include/",
   #     "/usr/local/buildtools/java/jdk/include/linux",
   #   ]
   #
-  pw_java_native_interface_include_dirs = []
+  pw_JAVA_NATIVE_INTERFACE_INCLUDE_DIRS = []
 }
 
 # 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.
+# pw_JAVA_NATIVE_INTERFACE_INCLUDE_DIRS variable.
 pw_shared_library("detokenizer_jni") {
   public_configs = [ ":default_config" ]
-  include_dirs = pw_java_native_interface_include_dirs
+  include_dirs = pw_JAVA_NATIVE_INTERFACE_INCLUDE_DIRS
   sources = [ "java/dev/pigweed/tokenizer/detokenizer.cc" ]
   public_deps = [
     ":decoder",
diff --git a/targets/host/linux.gni b/pw_tokenizer/backend.gni
similarity index 63%
rename from targets/host/linux.gni
rename to pw_tokenizer/backend.gni
index 245154a..dd00ac9 100644
--- a/targets/host/linux.gni
+++ b/pw_tokenizer/backend.gni
@@ -1,4 +1,4 @@
-# Copyright 2019 The Pigweed Authors
+# 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
@@ -12,14 +12,9 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-import("host_common.gni")
-
 declare_args() {
-  # Specifies the toolchain to use for this build.
-  pw_target_toolchain = "$dir_pw_toolchain:host_clang_og"
+  # Backends for the pw_tokenizer:global_handler and
+  # pw_tokenizer:global_handler_with_payload facades.
+  pw_tokenizer_GLOBAL_HANDLER_BACKEND = ""
+  pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND = ""
 }
-
-pw_executable_config.bloaty_config_file =
-    get_path_info("linux.bloaty", "abspath")
-
-pw_automatic_test_runner = get_path_info("run_test", "abspath")
diff --git a/pw_toolchain/generate_toolchain.gni b/pw_toolchain/generate_toolchain.gni
index 3445212..41b100a 100644
--- a/pw_toolchain/generate_toolchain.gni
+++ b/pw_toolchain/generate_toolchain.gni
@@ -19,7 +19,7 @@
 declare_args() {
   # Scope defining the current toolchain. Contains all of the arguments required
   # by the generate_toolchain template.
-  pw_toolchain_scope = {
+  pw_toolchain_SCOPE = {
   }
 }
 
@@ -213,14 +213,14 @@
       #     in this toolchain. It is analogous to $pw_target_defaults in
       #     $dir_pigweed/pw_vars_default.gni.
       #
-      #   pw_toolchain_scope: A copy of the invoker scope that defines the
+      #   pw_toolchain_SCOPE: A copy of the invoker scope that defines the
       #     toolchain. Used for generating derivative toolchains.
       #
       assert(defined(invoker.defaults), "toolchain is missing 'defaults'")
       toolchain_args = {
-        pw_toolchain_scope = {
+        pw_toolchain_SCOPE = {
         }
-        pw_toolchain_scope = {
+        pw_toolchain_SCOPE = {
           forward_variables_from(invoker, "*")
         }
         forward_variables_from(invoker.defaults, "*")
diff --git a/pw_toolchain/host_clang/toolchains.gni b/pw_toolchain/host_clang/toolchains.gni
index 7d850e9..8737b61 100644
--- a/pw_toolchain/host_clang/toolchains.gni
+++ b/pw_toolchain/host_clang/toolchains.gni
@@ -19,12 +19,12 @@
 declare_args() {
   # Sets the sanitizer to pass to clang. Valid values are those for "-fsanitize"
   # listed in https://clang.llvm.org/docs/UsersManual.html#id9.
-  pw_sanitizer = ""
+  pw_toolchain_SANITIZER = ""
 
   # Indicates if this build is a part of OSS-Fuzz, which needs to be able to
   # provide its own compiler and flags. This violates the build hermeticisim and
   # should only be used for OSS-Fuzz.
-  oss_fuzz_enabled = false
+  pw_toolchain_OSS_FUZZ_ENABLED = false
 }
 
 # Specifies the tools used by host Clang toolchains.
@@ -33,7 +33,7 @@
   # ar. This should get updated for linux systems.
   ar = "ar"
 
-  if (oss_fuzz_enabled) {
+  if (pw_toolchain_OSS_FUZZ_ENABLED) {
     cc = getenv("CC")
     cxx = getenv("CXX")
   } else {
@@ -51,10 +51,10 @@
     "$dir_pw_toolchain/host_clang:no_system_libcpp",
     "$dir_pw_toolchain/host_clang:xcode_sysroot",
   ]
-  if (pw_sanitizer != "") {
-    configs += [ "$dir_pw_toolchain/host_clang:sanitize_$pw_sanitizer" ]
+  if (pw_toolchain_SANITIZER != "") {
+    configs += [ "$dir_pw_toolchain/host_clang:sanitize_$pw_toolchain_SANITIZER" ]
   }
-  if (oss_fuzz_enabled) {
+  if (pw_toolchain_OSS_FUZZ_ENABLED) {
     default_configs += oss_fuzz_added_configs
     default_configs += [ "$dir_pw_fuzzer:oss_fuzz_extra" ]
 
@@ -65,24 +65,28 @@
   }
 }
 
+host_clang_og = {
+  name = "host_clang_og"
+  forward_variables_from(_host_clang_toolchain, "*")
+  defaults = {
+    forward_variables_from(_defaults, "*")
+    default_configs += [ "$dir_pw_build:optimize_debugging" ]
+  }
+}
+
+host_clang_o2 = {
+  name = "host_clang_o2"
+  forward_variables_from(_host_clang_toolchain, "*")
+  defaults = {
+    forward_variables_from(_defaults, "*")
+    default_configs += [ "$dir_pw_build:optimize_speed" ]
+  }
+}
+
 # Describes host clang toolchains.
 host_clang_toolchains = [
-  {
-    name = "host_clang_og"
-    forward_variables_from(_host_clang_toolchain, "*")
-    defaults = {
-      forward_variables_from(_defaults, "*")
-      default_configs += [ "$dir_pw_build:optimize_debugging" ]
-    }
-  },
-  {
-    name = "host_clang_o2"
-    forward_variables_from(_host_clang_toolchain, "*")
-    defaults = {
-      forward_variables_from(_defaults, "*")
-      default_configs += [ "$dir_pw_build:optimize_speed" ]
-    }
-  },
+  host_clang_og,
+  host_clang_o2,
   {
     name = "host_clang_os"
     forward_variables_from(_host_clang_toolchain, "*")
diff --git a/pw_trace/BUILD.gn b/pw_trace/BUILD.gn
index 6be9ebc..3b3ca20 100644
--- a/pw_trace/BUILD.gn
+++ b/pw_trace/BUILD.gn
@@ -19,12 +19,17 @@
 import("$dir_pw_build/facade.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
+declare_args() {
+  # Backend for the pw_trace module.
+  pw_trace_BACKEND = ""
+}
+
 config("default_config") {
   include_dirs = [ "public" ]
 }
 
 pw_facade("pw_trace") {
-  backend = dir_pw_trace_backend
+  backend = pw_trace_BACKEND
   public_configs = [ ":default_config" ]
   public = [
     "public/pw_trace/internal/trace_internal.h",
@@ -35,7 +40,7 @@
 
 pw_test_group("tests") {
   tests = [ ":trace_facade_test" ]
-  if (dir_pw_trace_backend != "") {
+  if (pw_trace_BACKEND != "") {
     tests += [ ":trace_backend_compile_test" ]
   }
 }
@@ -56,11 +61,11 @@
 }
 
 pw_test("trace_backend_compile_test") {
-  enable_if = dir_pw_trace_backend != ""
+  enable_if = pw_trace_BACKEND != ""
 
   deps = [
     ":pw_trace",
-    dir_pw_trace_backend,
+    pw_trace_BACKEND,
   ]
 
   sources = [
diff --git a/pw_unit_test/BUILD.gn b/pw_unit_test/BUILD.gn
index 2da4cd7..5184919 100644
--- a/pw_unit_test/BUILD.gn
+++ b/pw_unit_test/BUILD.gn
@@ -15,7 +15,6 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_unit_test/test.gni")
@@ -69,25 +68,23 @@
 }
 
 # Library providing an event handler which logs using pw_log.
-if (dir_pw_log_backend != "") {
-  pw_source_set("logging_event_handler") {
-    public_deps = [
-      ":pw_unit_test",
-      "$dir_pw_log",
-      "$dir_pw_preprocessor",
-    ]
-    public = [ "public/pw_unit_test/logging_event_handler.h" ]
-    sources = [ "logging_event_handler.cc" ] + public
-  }
+pw_source_set("logging_event_handler") {
+  public_deps = [
+    ":pw_unit_test",
+    "$dir_pw_log",
+    "$dir_pw_preprocessor",
+  ]
+  public = [ "public/pw_unit_test/logging_event_handler.h" ]
+  sources = [ "logging_event_handler.cc" ] + public
+}
 
-  pw_source_set("logging_main") {
-    public_deps = [ ":pw_unit_test" ]
-    deps = [
-      ":logging_event_handler",
-      "$dir_pw_sys_io",
-    ]
-    sources = [ "logging_main.cc" ]
-  }
+pw_source_set("logging_main") {
+  public_deps = [ ":pw_unit_test" ]
+  deps = [
+    ":logging_event_handler",
+    "$dir_pw_sys_io",
+  ]
+  sources = [ "logging_main.cc" ]
 }
 
 pw_test("framework_test") {
diff --git a/pw_unit_test/test.gni b/pw_unit_test/test.gni
index 182d1f5..481f56b 100644
--- a/pw_unit_test/test.gni
+++ b/pw_unit_test/test.gni
@@ -15,9 +15,22 @@
 # gn-format disable
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/legacy_target.gni")
 import("$dir_pw_build/python_script.gni")
 import("$dir_pw_build/target_types.gni")
+declare_args() {
+  # Path to a test runner to automatically run unit tests after they are built.
+  #
+  # If set, the pw_test() template creates an action that invokes the test runner
+  # on each test executable. If unset, the pw_test() template only creates a test
+  # executable target.
+  #
+  # This should only be enabled for targets which support parallelized running of
+  # unit tests, such as desktops with multiple cores.
+  pw_unit_test_AUTOMATIC_RUNNER = ""
+
+  # Implementation of a main function for "pw_test" unit test binaries.
+  pw_unit_test_MAIN = "$dir_pw_unit_test:simple_printing_main"
+}
 
 # 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
@@ -62,7 +75,7 @@
 
 # Creates an executable target for a unit test.
 #
-# If the pw_automatic_test_runner variable is set, this template also creates a
+# If the pw_unit_test_AUTOMATIC_RUNNER variable is set, this template also creates a
 # "${test_name}_run" target which runs the unit test executable after building
 # it.
 #
@@ -102,10 +115,10 @@
     if (!defined(deps)) {
       deps = []
     }
-    deps += [ pw_unit_test_main ]
+    deps += [ pw_unit_test_MAIN ]
   }
 
-  if (pw_automatic_test_runner != "") {
+  if (pw_unit_test_AUTOMATIC_RUNNER != "") {
     # When the automatic runner is set, create an action which runs the unit
     # test executable using the test runner script.
     if (_test_is_enabled) {
@@ -122,11 +135,11 @@
 
     pw_python_script(_test_to_run + "_run") {
       deps = [ ":$_test_target_name" ]
-      inputs = [ pw_automatic_test_runner ]
+      inputs = [ pw_unit_test_AUTOMATIC_RUNNER ]
       script = "$dir_pw_unit_test/py/pw_unit_test/test_runner.py"
       args = [
         "--runner",
-        pw_automatic_test_runner,
+        pw_unit_test_AUTOMATIC_RUNNER,
         "--test",
         get_path_info("$target_out_dir:$_test_to_run", "abspath"),
       ]
@@ -210,7 +223,7 @@
 
     # If automatic test running is enabled, create a *_run group that collects
     # all of the individual *_run targets and groups.
-    if (pw_automatic_test_runner != "") {
+    if (pw_unit_test_AUTOMATIC_RUNNER != "") {
       group(_group_target + "_run") {
         deps = [ ":$_group_target" ]
         foreach(_target, _deps) {
@@ -223,7 +236,7 @@
     group(_group_target) {
     }
 
-    if (pw_automatic_test_runner != "") {
+    if (pw_unit_test_AUTOMATIC_RUNNER != "") {
       group(_group_target + "_run") {
       }
     }
diff --git a/pw_vars_default.gni b/pw_vars_default.gni
deleted file mode 100644
index 20930f8..0000000
--- a/pw_vars_default.gni
+++ /dev/null
@@ -1,151 +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.
-
-import("//build_overrides/pigweed.gni")
-
-# This file defines default values for all of the build variables used by
-# Pigweed.
-#
-# Each individual variable can be overriden by a target to configure the system
-# to build for it. This is done in a .gni file specific to the target by first
-# importing this file, then changing the variables as desired.
-
-# Whether to build host-side tooling.
-pw_build_host_tools = false
-
-# Options which configure the executable targets created in Pigweed builds.
-pw_executable_config = {
-  # 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.
-  target_type = "executable"
-
-  # Path to an instantiation of the "linker_script" GN template defining the
-  # linker script configuration for the target.
-  linker_script_target = ""
-
-  # Path to the Bloaty configuration file that defines the memory layout and
-  # capacities for the target binaries.
-  bloaty_config_file = ""
-}
-
-# Default toolchain for the build target.
-#
-# If this is changed, you must run `ninja -t clean` to remove any files from
-# the previous toolchain's build before building again.
-pw_target_toolchain = ""
-
-# Defaults variables for the build target.
-#
-# Scope containing defaults to be added to GN targets for the target. With the
-# exception of "remove_configs", all variables will be automatically be
-# forwarded to GN targets with the following types:
-#   source_set
-#   executable
-#   shared_library
-#   static_library
-#
-# "remove_configs" is a special case. This variable can be set to a list of
-# configs that will be removed from the defaults, including those provided by
-# $dir_pw_build/defaults.gni.
-#
-pw_target_defaults = {
-}
-
-# List of toolchains to use in pw_toolchain_size_report templates.
-#
-# Each entry is a scope containing the following variables:
-#
-#   name: Human-readable toolchain name.
-#   target: GN target that defines the toolchain.
-#   linker_script: Optional path to a linker script file to build for the
-#     toolchain's target.
-#   bloaty_config: Optional Bloaty confirugation file defining the memory
-#     layout of the binaries as specified in the linker script.
-#
-# If this list is empty, pw_toolchain_size_report targets become no-ops.
-pw_size_report_toolchains = []
-
-# Implementation of a main function for "pw_test" unit test binaries.
-pw_unit_test_main = "$dir_pw_unit_test:simple_printing_main"
-
-# Path to a test runner to automatically run unit tests after they are built.
-#
-# If set, the pw_test() template creates an action that invokes the test runner
-# on each test executable. If unset, the pw_test() template only creates a test
-# executable target.
-#
-# This should only be enabled for targets which support parallelized running of
-# unit tests, such as desktops with multiple cores.
-pw_automatic_test_runner = ""
-
-################################# PROTOBUF #####################################
-
-# Generators with which to compile protobuf code. These are used by the
-# pw_proto_library template to determine which build targets to create.
-#
-# Supported generators:
-#   "pwpb", "nanopb", "go"
-pw_protobuf_generators = [
-  "pwpb",
-  "go",
-]
-
-# If compiling for nanopb, this variable is set to the path to the nanopb
-# installation.
-dir_third_party_nanopb = ""
-
-################################# BACKENDS #####################################
-
-# This section of the file defines empty variables for each of the Pigweed
-# facades that expect a backend. This allows minimal breakages when adding new
-# facades. Instead of GN always halting due to encountering an undefined
-# variable, GN will only emit an error if something in the build depends on the
-# empty (but defined) variable.
-#
-# All of these should default to empty strings. For target-specific defaults,
-# modify these variables in a target configuration file.
-
-# Backend for the pw_assert module.
-dir_pw_assert_backend = ""
-
-# Backend for the pw_boot module.
-dir_pw_boot_backend = ""
-
-# Backend for the pw_cpu_exception module.
-dir_pw_cpu_exception_backend = ""
-
-# Backend for the pw_log module.
-dir_pw_log_backend = ""
-
-# Backend for the pw_trace module.
-dir_pw_trace_backend = ""
-
-# Backend for the pw_sys_io module.
-dir_pw_sys_io_backend = ""
-
-# Backends for the pw_tokenizer:global_handler and
-# pw_tokenizer:global_handler_with_payload facades.
-dir_pw_tokenizer_global_handler_backend = ""
-dir_pw_tokenizer_global_handler_with_payload_backend = ""
-
-############################## MODULE CONFIGS ##################################
-
-# Module configuration options for pw_boot_armv7m.
-pw_boot_armv7m_config = {
-  # C Preprocessor defines used for linker script configuration.
-  defines = []
-}
diff --git a/targets/host/host_common.gni b/targets/host/host_common.gni
index b7f925d..d4742f2 100644
--- a/targets/host/host_common.gni
+++ b/targets/host/host_common.gni
@@ -14,26 +14,14 @@
 
 import("//build_overrides/pigweed.gni")
 
-import("$dir_pigweed/pw_vars_default.gni")
-
-declare_args() {
-  pw_build_host_tools = false
-  dir_third_party_nanopb = ""
-}
-
-# Allow nanopb to be toggled via a build arg on host for easy testing.
-if (dir_third_party_nanopb != "") {
-  pw_protobuf_generators += [ "nanopb" ]
-}
-
 # Use logging-based test output on host.
-pw_unit_test_main = "$dir_pw_unit_test:logging_main"
+pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main"
 
 # Configure backend for assert facade.
-dir_pw_assert_backend = "$dir_pw_assert_basic"
+pw_assert_BACKEND = "$dir_pw_assert_basic"
 
 # Configure backend for logging facade.
-dir_pw_log_backend = "$dir_pw_log_basic"
+pw_log_BACKEND = "$dir_pw_log_basic"
 
 # Configure backend for pw_sys_io facade.
-dir_pw_sys_io_backend = "$dir_pw_sys_io_stdio"
+pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio"
diff --git a/targets/host/linux/BUILD.gn b/targets/host/linux/BUILD.gn
new file mode 100644
index 0000000..8627a81
--- /dev/null
+++ b/targets/host/linux/BUILD.gn
@@ -0,0 +1,34 @@
+# 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.
+
+# gn-format disable
+import("//build_overrides/pigweed.gni")
+
+import("$dir_pw_toolchain/generate_toolchain.gni")
+import("$dir_pw_toolchain/host_clang/toolchains.gni")
+
+linux_toolchains = [
+  {
+    name = "clang_og"
+    forward_variables_from(host_clang_og, "*", [ "defaults", "name" ])
+    defaults = {
+      forward_variables_from(host_clang_og.defaults, "*")
+      import("linux.gni")
+    }
+  }
+]
+
+generate_toolchains("linux") {
+  toolchains = linux_toolchains
+}
diff --git a/targets/host/linux.bloaty b/targets/host/linux/linux.bloaty
similarity index 100%
rename from targets/host/linux.bloaty
rename to targets/host/linux/linux.bloaty
diff --git a/targets/host/linux.gni b/targets/host/linux/linux.gni
similarity index 61%
copy from targets/host/linux.gni
copy to targets/host/linux/linux.gni
index 245154a..c81bb37 100644
--- a/targets/host/linux.gni
+++ b/targets/host/linux/linux.gni
@@ -1,4 +1,4 @@
-# Copyright 2019 The Pigweed Authors
+# 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
@@ -12,14 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-import("host_common.gni")
+import("../host_common.gni")
 
-declare_args() {
-  # Specifies the toolchain to use for this build.
-  pw_target_toolchain = "$dir_pw_toolchain:host_clang_og"
-}
-
-pw_executable_config.bloaty_config_file =
-    get_path_info("linux.bloaty", "abspath")
-
-pw_automatic_test_runner = get_path_info("run_test", "abspath")
+pw_bloat_BLOATY_CONFIG = get_path_info("linux.bloaty", "abspath")
+pw_unit_test_AUTOMATIC_RUNNER = get_path_info("../run_test", "abspath")