pw_build: Update path and target resolution
- Don't implicitly convert paths and labels in python_runner.py.
- To enable finding target outputs, support explicit resolution with
the <TARGET_FILE($target)> expression.
- Use the standard GN rebase_path approach to resolve GN paths to
filesystem paths for scripts. Remove workarounds that are no longer
necessary.
- Update build files to use rebase_path and <TARGET_FILE(target)>.
- Add tests for python_runner.py.
Bug: 110
Change-Id: Iae262820bb265c648c270c2b78d058f20e1d3d1f
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/14801
Reviewed-by: Alexei Frolov <frolv@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
diff --git a/pw_build/docs.rst b/pw_build/docs.rst
index 50a80bc..05b31dc 100644
--- a/pw_build/docs.rst
+++ b/pw_build/docs.rst
@@ -82,10 +82,9 @@
pw_python_script
^^^^^^^^^^^^^^^^
The ``pw_python_script`` template is a convenience wrapper around ``action`` for
-running Python scripts. The main benefit it provides is automatic resolution of
-GN paths to filesystem paths and GN target names to compiled binary files. This
-allows Python scripts to be written independent of GN, taking only filesystem as
-arguments.
+running Python scripts. The main benefit it provides is resolution of GN target
+labels to compiled binary files. This allows Python scripts to be written
+independently of GN, taking only filesystem paths as arguments.
Another convenience provided by the template is to allow running scripts without
any outputs. Sometimes scripts run in a build do not directly produce output
@@ -102,15 +101,59 @@
output file for the script. This allows running scripts without specifying any
``outputs``.
+**Expressions**
+
+``pw_python_script`` evaluates expressions in ``args``, the arguments passed to
+the script. These expressions function similarly to generator expressions in
+CMake. Expressions may be passed as a standalone argument or as part of another
+argument. A single argument may contain multiple expressions.
+
+Generally, these expressions are used within templates rather than directly in
+BUILD.gn files. This allows build code to use GN labels without having to worry
+about converting them to files.
+
+Currently, only one expression is supported.
+
+.. describe:: <TARGET_FILE(gn_target)>
+
+ Evaluates to the output file of the provided GN target. For example, the
+ expression
+
+ .. code::
+
+ "<TARGET_FILE(//foo/bar:static_lib)>"
+
+ might expand to
+
+ .. code::
+
+ "/home/User/project_root/out/obj/foo/bar/static_lib.a"
+
+ ``TARGET_FILE`` parses the ``.ninja`` file for the GN target, so it should
+ always find the correct output file, regardless of the toolchain's or target's
+ configuration. Some targets, such as ``source_set`` and ``group`` targets, do
+ not have an output file, and attempting to use ``TARGET_FILE`` with them
+ results in an error.
+
+ ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve
+ paths generally, use the standard GN approach of applying the
+ ``rebase_path(path)`` function. With default arguments, ``rebase_path``
+ converts the provided GN path or list of paths to be relative to the build
+ directory, from which all build commands and scripts are executed.
+
**Example**
.. code::
import("$dir_pw_build/python_script.gni")
- python_script("hello_world") {
- script = "py/say_hello.py"
- args = [ "world" ]
+ pw_python_script("postprocess_main_image") {
+ script = "py/postprocess_binary.py"
+ args = [
+ "--database",
+ rebase_path("my/database.csv"),
+ "--binary=<TARGET_FILE(//firmware/images:main)>",
+ ]
stamp = true
}