Add pw_host_tool GN template

This change cerates a GN template called pw_host_tool which copies a
binary target to a common host_tools directory that can be added to a
user's PATH.

Change-Id: I9eb38ab4ff9d11a4a87e6be2547d5224370e3412
diff --git a/BUILD.gn b/BUILD.gn
index 39a95f6..8b691d9 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -26,6 +26,16 @@
     # With a test runner, depend on the run targets so they run with the build.
     deps += [ ":pw_module_tests_run" ]
   }
+  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") {
diff --git a/pw_build/go.gni b/pw_build/go.gni
index 86bc4d1..b0433b6 100644
--- a/pw_build/go.gni
+++ b/pw_build/go.gni
@@ -125,9 +125,7 @@
   pw_exec(_download_target_name) {
     program = "go"
     args = [ "get" ]
-    deps = [
-      ":$_deps_metadata_target_name",
-    ]
+    deps = [ ":$_deps_metadata_target_name" ] + invoker.deps
     env = [ "GOPATH=$_default_gopath" ]
     args_file = _deps_metadata_file
 
diff --git a/pw_build/host_tool.gni b/pw_build/host_tool.gni
new file mode 100644
index 0000000..3011b6e
--- /dev/null
+++ b/pw_build/host_tool.gni
@@ -0,0 +1,71 @@
+# 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("python_script.gni")
+
+if (pw_build_host_tools) {
+  # Defines a Pigweed host tool and installs it into the host_tools directory.
+  #
+  # Args:
+  #   deps: List containing exactly one target which outputs a binary tool.
+  #   name: Optional name for the installed program. Defaults to the name of
+  #     the compiled binary.
+  template("pw_host_tool") {
+    assert(defined(invoker.deps),
+           "pw_host_tool must specify an executable as a dependency")
+
+    num_deps = 0
+    foreach(_dep, invoker.deps) {
+      num_deps += 1
+    }
+    assert(num_deps == 1, "pw_host_tool must have exactly one dependency")
+
+    _host_tools_dir = "$root_out_dir/host_tools"
+
+    # Can't do invoker.deps[0] in GN.
+    _deps = invoker.deps
+    _out_target = get_label_info(_deps[0], "target_out_dir") + ":" +
+                  get_label_info(_deps[0], "name")
+
+    _script_args = [
+      "--src",
+      _out_target,
+      "--dst",
+      _host_tools_dir,
+    ]
+
+    if (defined(invoker.name) && invoker.name != "") {
+      _script_args += [
+        "--name",
+        invoker.name,
+      ]
+    }
+
+    pw_python_script(target_name) {
+      script = "$dir_pw_build/py/host_tool.py"
+      args = _script_args
+      deps = _deps
+      stamp = true
+    }
+  }
+} else {
+  # For builds without host tools, create an empty target.
+  template("pw_host_tool") {
+    not_needed("*")
+    not_needed(invoker, "*")
+
+    group(target_name) {
+    }
+  }
+}  # pw_build_host_tools
diff --git a/pw_build/py/host_tool.py b/pw_build/py/host_tool.py
new file mode 100644
index 0000000..ca0fbc8
--- /dev/null
+++ b/pw_build/py/host_tool.py
@@ -0,0 +1,68 @@
+# 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.
+"""Copies built host tools into Pigweed's host_tools directory."""
+
+import argparse
+import logging
+import os
+import shutil
+import sys
+from typing import Optional
+
+import pw_cli.log
+
+_LOG = logging.getLogger(__name__)
+
+
+def argument_parser(
+    parser: Optional[argparse.ArgumentParser] = None
+) -> argparse.ArgumentParser:
+    """Registers the script's arguments on an argument parser."""
+
+    if parser is None:
+        parser = argparse.ArgumentParser(description=__doc__)
+
+    parser.add_argument('--dst',
+                        required=True,
+                        help='Path to host tools directory')
+    parser.add_argument('--name', help='Name for the installed tool')
+    parser.add_argument('--src',
+                        required=True,
+                        help='Path to host tool executable')
+
+    return parser
+
+
+def main() -> int:
+    args = argument_parser().parse_args()
+
+    if not os.path.isfile(args.src):
+        _LOG.error('%s is not a file', args.src)
+        return 1
+
+    os.makedirs(args.dst, exist_ok=True)
+
+    if args.name is not None:
+        if '/' in args.name:
+            _LOG.error('Host tool name cannot contain "/"')
+            return 1
+        args.dst = os.path.join(args.dst, args.name)
+
+    shutil.copy2(args.src, args.dst)
+    return 0
+
+
+if __name__ == '__main__':
+    pw_cli.log.install()
+    sys.exit(main())
diff --git a/pw_target_runner/go/BUILD.gn b/pw_target_runner/go/BUILD.gn
index 75fd41e..4dad302 100644
--- a/pw_target_runner/go/BUILD.gn
+++ b/pw_target_runner/go/BUILD.gn
@@ -13,6 +13,7 @@
 # the License.
 
 import("$dir_pw_build/go.gni")
+import("$dir_pw_build/host_tool.gni")
 import("$dir_pw_docgen/docs.gni")
 
 pw_doc_group("docs") {
@@ -21,16 +22,28 @@
   ]
 }
 
-pw_go_executable("simple_client") {
+pw_go_executable("pw_target_runner_client") {
   deps = [
     "src/pigweed.dev/pw_target_runner_client",
   ]
   package = "pigweed.dev/pw_target_runner_client"
 }
 
-pw_go_executable("simple_server") {
+pw_go_executable("pw_target_runner_server") {
   deps = [
     "src/pigweed.dev/pw_target_runner_server",
   ]
   package = "pigweed.dev/pw_target_runner_server"
 }
+
+pw_host_tool("simple_client") {
+  deps = [
+    ":pw_target_runner_client",
+  ]
+}
+
+pw_host_tool("simple_server") {
+  deps = [
+    ":pw_target_runner_server",
+  ]
+}
diff --git a/pw_vars_default.gni b/pw_vars_default.gni
index 9572a5d..c5458da 100644
--- a/pw_vars_default.gni
+++ b/pw_vars_default.gni
@@ -20,7 +20,7 @@
 # importing this file, then changing the variables as desired.
 
 # Whether to build host-side tooling.
-pw_build_host_tools = true
+pw_build_host_tools = false
 
 # Options which configure the executable targets created in Pigweed builds.
 pw_executable_config = {
diff --git a/targets/host/host.gni b/targets/host/host.gni
index 47a887b..451852f 100644
--- a/targets/host/host.gni
+++ b/targets/host/host.gni
@@ -35,3 +35,5 @@
 } else {
   assert(false, "Please define a host config for your system: $host_os")
 }
+
+pw_build_host_tools = true