pw_build: Configurable Python and proto toolchains
- Rename pw_toolchain/dummy to pw_toolchain/default to make its intended
purpose clear. Keep pw_toolchain/dummy around for compatibility.
- Create a template that generates non-C++ toolchains. This is used for
non-C++ tasks like Python and proto. GN parses build files differently
in the default toolchain (all targets are instantiated), so the
these toolchains can be used when that is not desired.
- Make pw_python_package's toolchain configurable with the
pw_build_PYTHON_TOOLCHAIN arg.
- Make pw_proto_library's toolchain configurable with the
pw_protobuf_compiler_TOOLCHAIN arg.
Requires: pigweed-internal:11680
Change-Id: I0aad049c605906b77c58b93a08efc63a648947ee
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/40763
Reviewed-by: Armando Montanez <amontanez@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
diff --git a/BUILDCONFIG.gn b/BUILDCONFIG.gn
index dbf7ed4..1dbd4c5 100644
--- a/BUILDCONFIG.gn
+++ b/BUILDCONFIG.gn
@@ -22,7 +22,7 @@
import("//build_overrides/pigweed.gni")
}
-# 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_directory.dir_pw_toolchain}/dummy")
+# The default toolchain is not used in Pigweed builds, so it is set to a
+# toolchain that cannot compile C/C++ code. The top-level BUILD.gn should stamp
+# a group with all of the build targets and their toolchains.
+set_default_toolchain("${_pigweed_directory.dir_pw_toolchain}/default")
diff --git a/pw_build/python.gni b/pw_build/python.gni
index 038d9a2..c7ff3e4 100644
--- a/pw_build/python.gni
+++ b/pw_build/python.gni
@@ -17,6 +17,13 @@
import("$dir_pw_build/input_group.gni")
import("$dir_pw_build/mirror_tree.gni")
import("$dir_pw_build/python_action.gni")
+import("$dir_pw_protobuf_compiler/toolchain.gni")
+
+declare_args() {
+ # Python tasks, such as running tests and Pylint, are done in a single GN
+ # toolchain to avoid unnecessary duplication in the build.
+ pw_build_PYTHON_TOOLCHAIN = "$dir_pw_build/python_toolchain:python"
+}
# Python packages provide the following targets as $target_name.$subtarget.
pw_python_package_subtargets = [
@@ -125,8 +132,9 @@
# - $name.install - Installs the package in a venv.
# - $name.wheel - Builds a Python wheel for the package.
#
-# All Python packages are instantiated with the default toolchain, regardless of
-# the current toolchain.
+# All Python packages are instantiated with in pw_build_PYTHON_TOOLCHAIN,
+# regardless of the current toolchain. This prevents Python-specific work, like
+# running Pylint, from occurring multiple times in a build.
#
# Args:
# setup: List of setup file paths (setup.py or pyproject.toml & setup.cfg),
@@ -153,7 +161,7 @@
# directory will take precedence over others.
#
template("pw_python_package") {
- # The Python targets are always instantiated in the default toolchain. Use
+ # The Python targets are always instantiated in pw_build_PYTHON_TOOLCHAIN. Use
# fully qualified labels so that the toolchain is not lost.
_other_deps = []
if (defined(invoker.other_deps)) {
@@ -304,9 +312,10 @@
_all_py_files = _sources + _test_sources + _setup_sources
- # The pw_python_package subtargets are only instantiated in the default
- # toolchain. Other toolchains just refer to targets in the default toolchain.
- if (current_toolchain == default_toolchain) {
+ # The pw_python_package subtargets are only instantiated in
+ # pw_build_PYTHON_TOOLCHAIN. Targets in other toolchains just refer to the
+ # targets in this toolchain.
+ if (current_toolchain == pw_build_PYTHON_TOOLCHAIN) {
# Declare the main Python package group. This represents the Python files,
# but does not take any actions. GN targets can depend on the package name
# to run when any files in the package change.
@@ -330,8 +339,8 @@
# Depend on the proto's _gen targets (from the default toolchain).
_gen_protos = []
foreach(proto, _import_protos) {
- _gen_protos +=
- [ get_label_info(proto, "label_no_toolchain") + ".python._gen" ]
+ _gen_protos += [ get_label_info(proto, "label_no_toolchain") +
+ ".python._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
}
generated_file("$target_name._protos") {
@@ -387,9 +396,12 @@
":$target_name._protos_root",
]
+ # Each pw_proto_library generates a file that indicates which Python
+ # package it is nested in, if any. Locate those files.
foreach(proto, _import_protos) {
_tgt = get_label_info(proto, "label_no_toolchain")
- _path = get_label_info("$_tgt($default_toolchain)", "target_gen_dir")
+ _path = get_label_info("$_tgt($pw_protobuf_compiler_TOOLCHAIN)",
+ "target_gen_dir")
_name = get_label_info(_tgt, "name")
args += [
@@ -398,7 +410,8 @@
rebase_path("$_path/$_name.proto_library/python_package.txt"),
]
- public_deps += [ "$_tgt.python._gen($default_toolchain)" ]
+ public_deps +=
+ [ "$_tgt.python._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
}
outputs = _setup_sources
@@ -575,12 +588,13 @@
#
# The $target_name.tests group is created separately below.
group("$target_name") {
- deps = [ ":$target_name($default_toolchain)" ]
+ deps = [ ":$target_name($pw_build_PYTHON_TOOLCHAIN)" ]
}
foreach(subtarget, pw_python_package_subtargets - [ "tests" ]) {
group("$target_name.$subtarget") {
- deps = [ ":${invoker.target_name}.$subtarget($default_toolchain)" ]
+ deps =
+ [ ":${invoker.target_name}.$subtarget($pw_build_PYTHON_TOOLCHAIN)" ]
}
}
@@ -602,7 +616,7 @@
_test_target = "$target_name.tests." + string_replace(_name, "/", "_")
- if (current_toolchain == default_toolchain) {
+ if (current_toolchain == pw_build_PYTHON_TOOLCHAIN) {
pw_python_action(_test_target) {
script = test
stamp = true
@@ -617,7 +631,7 @@
# Create a public version of each test target, so tests can be executed as
# //path/to:package.tests.foo.py.
group(_test_target) {
- deps = [ ":$_test_target($default_toolchain)" ]
+ deps = [ ":$_test_target($pw_build_PYTHON_TOOLCHAIN)" ]
}
}
diff --git a/pw_build/python.rst b/pw_build/python.rst
index 09b92a2..c1d25c9 100644
--- a/pw_build/python.rst
+++ b/pw_build/python.rst
@@ -31,6 +31,11 @@
//path/to/my_python_package:my_python_package.tests
//path/to/my_python_package:tests
+The actions in a ``pw_python_package`` (e.g. installing packages and running
+Pylint) are done within a single GN toolchain to avoid duplication in
+multi-toolchain builds. This toolchain can be set with the
+``pw_build_PYTHON_TOOLCHAIN`` GN arg, which defaults to a dummy toolchain.
+
Arguments
---------
- ``setup`` - List of setup file paths (setup.py or pyproject.toml & setup.cfg),
diff --git a/pw_build/python_toolchain/BUILD.gn b/pw_build/python_toolchain/BUILD.gn
new file mode 100644
index 0000000..56d2aba
--- /dev/null
+++ b/pw_build/python_toolchain/BUILD.gn
@@ -0,0 +1,23 @@
+# 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_toolchain/non_c_toolchain.gni")
+
+# A toolchain that provides no C/C++ compiler. It can be used for non-C/C++
+# languages or actions that should only happen once across all builds. This
+# toolchain cannot compile C/C++, and trying to use it to do so causes errors.
+pw_non_c_toolchain("python") {
+}
diff --git a/pw_protobuf_compiler/proto.gni b/pw_protobuf_compiler/proto.gni
index a6ec15e..c6348c9 100644
--- a/pw_protobuf_compiler/proto.gni
+++ b/pw_protobuf_compiler/proto.gni
@@ -21,6 +21,7 @@
import("$dir_pw_build/python_action.gni")
import("$dir_pw_build/target_types.gni")
import("$dir_pw_third_party/nanopb/nanopb.gni")
+import("toolchain.gni")
# Variables forwarded from the public pw_proto_library template to the final
# pw_source_set.
@@ -35,7 +36,7 @@
# This creates the internal GN target $target_name.$language._gen that compiles
# proto files with protoc.
template("_pw_invoke_protoc") {
- if (current_toolchain == default_toolchain) {
+ if (current_toolchain == pw_protobuf_compiler_TOOLCHAIN) {
if (defined(invoker.out_dir)) {
_out_dir = invoker.out_dir
} else {
@@ -101,7 +102,7 @@
}
}
} else {
- # protoc is only ever invoked from the default toolchain.
+ # protoc is only ever invoked from pw_protobuf_compiler_TOOLCHAIN.
not_needed([ "target_name" ])
not_needed(invoker, "*")
}
@@ -127,7 +128,7 @@
pw_source_set(target_name) {
forward_variables_from(invoker, _forwarded_vars)
public_configs = [ ":$target_name._include_path" ]
- deps = [ ":$target_name._gen($default_toolchain)" ]
+ deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
public_deps = [ dir_pw_protobuf ] + invoker.deps
sources = invoker.outputs
public = filter_include(sources, [ "*.pwpb.h" ])
@@ -156,7 +157,7 @@
pw_source_set(target_name) {
forward_variables_from(invoker, _forwarded_vars)
public_configs = [ ":$target_name._include_path" ]
- deps = [ ":$target_name._gen($default_toolchain)" ]
+ deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
public_deps = [
":${invoker.base_target}.nanopb",
"$dir_pw_rpc:server",
@@ -175,11 +176,14 @@
# compiled internally, so skip recompiling it with protoc.
if (rebase_path(invoker.sources, invoker.compile_dir) == [ "nanopb.proto" ]) {
group("$target_name._gen") {
- deps = [ ":${invoker.base_target}._sources" ]
+ deps = [
+ ":${invoker.base_target}._sources($pw_protobuf_compiler_TOOLCHAIN)",
+ ]
}
group("$target_name") {
- deps = invoker.deps + [ ":$target_name._gen($default_toolchain)" ]
+ deps = invoker.deps +
+ [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
}
} else {
# Create a target which runs protoc configured with the nanopb plugin to
@@ -199,7 +203,7 @@
pw_source_set(target_name) {
forward_variables_from(invoker, _forwarded_vars)
public_configs = [ ":$target_name._include_path" ]
- deps = [ ":$target_name._gen($default_toolchain)" ]
+ deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
public_deps = [ "$dir_pw_third_party/nanopb" ] + invoker.deps
sources = invoker.outputs
public = filter_include(sources, [ "*.pb.h" ])
@@ -229,7 +233,7 @@
pw_source_set(target_name) {
forward_variables_from(invoker, _forwarded_vars)
public_configs = [ ":$target_name._include_path" ]
- deps = [ ":$target_name._gen($default_toolchain)" ]
+ deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
public_deps = [
"$dir_pw_rpc:server",
"$dir_pw_rpc/raw:method_union",
@@ -259,7 +263,8 @@
}
group(target_name) {
- deps = invoker.deps + [ ":$target_name._gen($default_toolchain)" ]
+ deps =
+ invoker.deps + [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
}
}
@@ -305,7 +310,7 @@
sources = invoker.outputs
strip_prefix = "${invoker.base_out_dir}/python"
python_deps = invoker.deps
- other_deps = [ ":$target_name._gen($default_toolchain)" ]
+ other_deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
static_analysis = []
_pw_module_as_package = invoker.module_as_package != ""
@@ -380,8 +385,8 @@
# Sources are mirrored to "$base_out_dir/sources" and protoc puts outputs in
# "$base_out_dir/$language" by default.
base_out_dir =
- get_label_info(":$target_name($default_toolchain)", "target_gen_dir") +
- "/$target_name.proto_library"
+ get_label_info(":$target_name($pw_protobuf_compiler_TOOLCHAIN)",
+ "target_gen_dir") + "/$target_name.proto_library"
compile_dir = "$base_out_dir/sources"
@@ -468,15 +473,19 @@
}
# Mirror the proto sources to the output directory with the prefix added.
- pw_mirror_tree("$target_name._sources") {
- source_root = _source_root
- sources = invoker.sources
+ if (current_toolchain == pw_protobuf_compiler_TOOLCHAIN) {
+ pw_mirror_tree("$target_name._sources") {
+ source_root = _source_root
+ sources = invoker.sources
- if (defined(invoker.inputs)) {
- sources += invoker.inputs
+ if (defined(invoker.inputs)) {
+ sources += invoker.inputs
+ }
+
+ directory = "${_common.compile_dir}/$_prefix"
}
-
- directory = "${_common.compile_dir}/$_prefix"
+ } else {
+ not_needed(invoker, [ "inputs" ])
}
# Enumerate all of the protobuf generator targets.
diff --git a/pw_protobuf_compiler/toolchain.gni b/pw_protobuf_compiler/toolchain.gni
new file mode 100644
index 0000000..606e69d
--- /dev/null
+++ b/pw_protobuf_compiler/toolchain.gni
@@ -0,0 +1,23 @@
+# 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")
+
+declare_args() {
+ # Compiling protobufs involves mirroring .proto files to the output directory
+ # in a specific configuration and invoking protoc on them. This work is done
+ # in a single toolchain to avoid unnecessary duplication in the build.
+ pw_protobuf_compiler_TOOLCHAIN =
+ "$dir_pw_protobuf_compiler/toolchain:protocol_buffer"
+}
diff --git a/pw_protobuf_compiler/toolchain/BUILD.gn b/pw_protobuf_compiler/toolchain/BUILD.gn
new file mode 100644
index 0000000..6d2fd5b
--- /dev/null
+++ b/pw_protobuf_compiler/toolchain/BUILD.gn
@@ -0,0 +1,22 @@
+# 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_toolchain/non_c_toolchain.gni")
+
+# A toolchain used for compiling protocol buffers. This toolchain cannot compile
+# C/C++, and trying to use it to do so results in errors.
+pw_non_c_toolchain("protocol_buffer") {
+}
diff --git a/pw_toolchain/default/BUILD.gn b/pw_toolchain/default/BUILD.gn
new file mode 100644
index 0000000..e961c97
--- /dev/null
+++ b/pw_toolchain/default/BUILD.gn
@@ -0,0 +1,28 @@
+# 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_toolchain/non_c_toolchain.gni")
+
+# A toolchain that provides no C/C++ compiler for use as Pigweed's default
+# toolchain. This toolchain cannot compile C/C++, and trying to use it to do so
+# causes errors. The top-level BUILD.gn must explicitly specify the non-default
+# toolchains to use for each build.
+pw_non_c_toolchain("default") {
+ # If the user tries to build a target with the default toolchain, run a script
+ # printing out the error.
+ command = "python " +
+ rebase_path("$dir_pw_toolchain/py/pw_toolchain/bad_toolchain.py")
+}
diff --git a/pw_toolchain/docs.rst b/pw_toolchain/docs.rst
index 07e27fb..919eb88 100644
--- a/pw_toolchain/docs.rst
+++ b/pw_toolchain/docs.rst
@@ -3,10 +3,15 @@
------------
pw_toolchain
------------
-The ``pw_toolchain`` module enumerates GN toolchain definitions that may be used
-to build pigweed.
+GN toolchains function both as a set of tools for compilation and as a workspace
+for evaluating build files. The same compilations and actions can be executed by
+different toolchains. Each toolchain maintains its own set of build args, and
+build steps from all toolchains can be executed in parallel.
-``pw_toolchain`` defines the following toolchains:
+Toolchains
+==========
+``pw_toolchain`` provides GN toolchains that may be used to build Pigweed. The
+following toolchains are defined:
- arm_gcc_cortex_m4_og
- arm_gcc_cortex_m4_o1
@@ -25,3 +30,21 @@
.. note::
The documentation for this module is currently incomplete.
+
+Non-C/C++ toolchains
+====================
+``pw_toolchain/non_c_toolchain.gni`` provides the ``pw_non_c_toolchain``
+template. This template creates toolchains that cannot compile C/C++ source
+code. These toolchains may only be used to execute GN actions or declare groups
+of targets in other toolchains. Attempting to compile C/C++ code with either of
+these toolchains results in errors.
+
+Non-C/C++ toolchains can be used to consolidate actions that should only occur
+once in a multi-toolchain build. Build targets from all toolchains can refer to
+these actions in a non-C/C++ toolchain so they only execute once instead of once
+per toolchain.
+
+For example, Pigweed runs protobuf compilation and Python package actions like
+installation and Pylint in toolchains created with ``pw_non_c_toolchain``. This
+allows all toolchains to cleanly share the same protobuf and Python declarations
+without any duplicated work.
diff --git a/pw_toolchain/dummy/BUILD.gn b/pw_toolchain/dummy/BUILD.gn
index ba0d738..a19f1d0 100644
--- a/pw_toolchain/dummy/BUILD.gn
+++ b/pw_toolchain/dummy/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright 2020 The Pigweed Authors
+# 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
@@ -14,55 +14,9 @@
import("//build_overrides/pigweed.gni")
-import("$dir_pw_toolchain/universal_tools.gni")
+import("$dir_pw_toolchain/non_c_toolchain.gni")
-# A dummy toolchain which is set as the default for Pigweed. This is never used;
-# the top-level BUILD.gn enumerates the toolchains for each build.
-toolchain("dummy") {
- tool("stamp") {
- forward_variables_from(pw_universal_stamp, "*")
- }
-
- tool("copy") {
- forward_variables_from(pw_universal_copy, "*")
- }
-
- # If the user tries to build a target with the default toolchain, run a script
- # printing out the error.
- _bad_toolchain_command =
- "python " +
- rebase_path("$dir_pw_toolchain/py/pw_toolchain/bad_toolchain.py")
-
- tool("asm") {
- command = _bad_toolchain_command
- outputs =
- [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
- }
-
- tool("cc") {
- command = _bad_toolchain_command
- outputs =
- [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
- }
-
- tool("cxx") {
- command = _bad_toolchain_command
- outputs =
- [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
- }
-
- tool("link") {
- command = _bad_toolchain_command
- outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
- }
-
- tool("alink") {
- command = _bad_toolchain_command
- outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
- }
-
- tool("solink") {
- command = _bad_toolchain_command
- outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
- }
+# This toolchain has been DEPRECATED. Do not use it; use
+# "$dir_pw_toolchain/default:default" instead.
+pw_non_c_toolchain("dummy") {
}
diff --git a/pw_toolchain/non_c_toolchain.gni b/pw_toolchain/non_c_toolchain.gni
new file mode 100644
index 0000000..04e7013
--- /dev/null
+++ b/pw_toolchain/non_c_toolchain.gni
@@ -0,0 +1,105 @@
+# 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")
+
+# Creates a toolchain that provides no C/C++ compiler. It can be used for
+# non-C/C++ languages or actions that should only happen once across all builds.
+# The toolchain cannot compile C/C++, and trying to use it to is an error.
+#
+# Args:
+# command: Run this command if this toolchain is used to build C/C++ code.
+#
+template("pw_non_c_toolchain") {
+ # Import the universal stamp & copy tools.
+ import("$dir_pw_toolchain/universal_tools.gni")
+ _label = get_label_info(":$target_name", "label_no_toolchain")
+
+ # If the user tries to build a target with this toolchain, run a script that
+ # prints out an error.
+ _message =
+ "Attempted to use the $target_name toolchain to compile {{source}}.\n" +
+ "This toolchain cannot be used to compile C/C++ source code.\n\n" +
+ "This toolchain was either explicitly specified in a deps list with\n" +
+ "GN's :target($_label) syntax or was set as the\n" +
+ "default toolchain in the BUILDCONFIG.gn file.\n\n" +
+ "Ensure that no C/C++ GN targets are referred to with this toolchain,\n" +
+ "even transitively.\n\n" +
+ "See https://pigweed.dev/pw_toolchain for more information."
+
+ _command = string_join(" ",
+ [
+ "python",
+ rebase_path("$dir_pw_build/py/pw_build/error.py"),
+ "--message \"$_message\"",
+ "--target",
+ _label,
+ "--root",
+ rebase_path("//"),
+ "--out",
+ rebase_path(root_build_dir),
+ ])
+
+ if (defined(invoker.command)) {
+ _command = invoker.command
+ } else {
+ not_needed([ "invoker" ])
+ }
+
+ toolchain(target_name) {
+ tool("stamp") {
+ forward_variables_from(pw_universal_stamp, "*")
+ }
+
+ tool("copy") {
+ forward_variables_from(pw_universal_copy, "*")
+ }
+
+ tool("asm") {
+ command = _command
+ outputs =
+ [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
+ }
+
+ tool("cc") {
+ command = _command
+ outputs =
+ [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
+ }
+
+ tool("cxx") {
+ command = _command
+ outputs =
+ [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
+ }
+
+ # Can't use {{source}} for the linker, so replace it if it's in the command.
+ _command_no_source = string_replace(_command, "{{source}}", "C/C++ sources")
+
+ tool("link") {
+ command = _command_no_source
+ outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
+ }
+
+ tool("alink") {
+ command = _command_no_source
+ outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
+ }
+
+ tool("solink") {
+ command = _command_no_source
+ outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
+ }
+ }
+}