| # 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. |
| |
| import("//build_overrides/pigweed.gni") |
| |
| # Defines an action that runs a Python script. |
| # |
| # This wraps a regular Python script GN action with an invocation of a script- |
| # runner script that adds useful features. pw_python_action() uses the same |
| # actions as GN's action(), with the following additions or changes: |
| # |
| # module May be used in place of the script argument to run the |
| # provided Python module with `python -m` instead of a script. |
| # Either script or module must be provided. |
| # |
| # capture_output If true, script output is hidden unless the script fails |
| # with an error. Defaults to true. |
| # |
| # stamp File to touch if the script is successful. Actions that |
| # don't create output files can use this stamp file instead of |
| # creating their own placeholder file. If true, a generic file |
| # is used. If false or not set, no file is touched. |
| # |
| # environment Environment variables to set, passed as a list of NAME=VALUE |
| # strings. |
| # |
| # args Same as the standard action args, except special expressions |
| # may be used to extract information not normally accessible |
| # in GN. These include the following: |
| # |
| # <TARGET_FILE(//some/label:here)> - expands to the |
| # output file (such as a .a or .elf) from a GN target |
| # <TARGET_FILE_IF_EXISTS(//some/label:here)> - expands to |
| # the output file if the target exists, or nothing |
| # <TARGET_OBJECTS(//some/label:here)> - expands to the |
| # object files produced by the provided GN target |
| # |
| # python_deps Dependencies on pw_python_package or related Python targets. |
| # |
| template("pw_python_action") { |
| assert(defined(invoker.script) != defined(invoker.module), |
| "pw_python_action requires either 'script' or 'module'") |
| |
| _script_args = [ |
| # GN root directory relative to the build directory (in which the runner |
| # script is invoked). |
| "--gn-root", |
| rebase_path("//", root_build_dir), |
| |
| # Current directory, used to resolve relative paths. |
| "--current-path", |
| rebase_path(".", root_build_dir), |
| |
| "--default-toolchain=$default_toolchain", |
| "--current-toolchain=$current_toolchain", |
| ] |
| |
| if (defined(invoker.environment)) { |
| foreach(variable, invoker.environment) { |
| _script_args += [ "--env=$variable" ] |
| } |
| } |
| |
| if (defined(invoker.inputs)) { |
| _inputs = invoker.inputs |
| } else { |
| _inputs = [] |
| } |
| |
| # List the script to run as an input so that the action is re-run when it is |
| # modified. |
| if (defined(invoker.script)) { |
| _inputs += [ invoker.script ] |
| } |
| |
| if (defined(invoker.outputs)) { |
| _outputs = invoker.outputs |
| } else { |
| _outputs = [] |
| } |
| |
| # If a stamp file is requested, add it as an output of the runner script. |
| if (defined(invoker.stamp) && invoker.stamp != false) { |
| if (invoker.stamp == true) { |
| _stamp_file = "$target_gen_dir/$target_name.pw_pystamp" |
| } else { |
| _stamp_file = invoker.stamp |
| } |
| |
| _outputs += [ _stamp_file ] |
| _script_args += [ |
| "--touch", |
| rebase_path(_stamp_file, root_build_dir), |
| ] |
| } |
| |
| # Capture output or not (defaults to true). |
| if (!defined(invoker.capture_output) || invoker.capture_output) { |
| _script_args += [ "--capture-output" ] |
| } |
| |
| if (defined(invoker.module)) { |
| _script_args += [ |
| "--module", |
| invoker.module, |
| ] |
| } |
| |
| # "--" indicates the end of arguments to the runner script. |
| # Everything beyond this point is interpreted as the command and arguments |
| # of the Python script to run. |
| _script_args += [ "--" ] |
| |
| if (defined(invoker.script)) { |
| _script_args += [ rebase_path(invoker.script, root_build_dir) ] |
| } |
| |
| if (defined(invoker.args)) { |
| _script_args += invoker.args |
| } |
| |
| if (defined(invoker._pw_action_type)) { |
| _action_type = invoker._pw_action_type |
| } else { |
| _action_type = "action" |
| } |
| |
| if (defined(invoker.deps)) { |
| _deps = invoker.deps |
| } else { |
| _deps = [] |
| } |
| |
| if (defined(invoker.python_deps)) { |
| foreach(dep, invoker.python_deps) { |
| _deps += [ get_label_info(dep, "label_no_toolchain") + ".install(" + |
| get_label_info(dep, "toolchain") + ")" ] |
| } |
| |
| # Add the base target as a dep so the action reruns when any source files |
| # change, even if the package does not have to be reinstalled. |
| _deps += invoker.python_deps |
| } |
| |
| target(_action_type, target_name) { |
| _ignore_vars = [ |
| "script", |
| "args", |
| "deps", |
| "inputs", |
| "outputs", |
| ] |
| forward_variables_from(invoker, "*", _ignore_vars) |
| |
| script = "$dir_pw_build/py/pw_build/python_runner.py" |
| args = _script_args |
| inputs = _inputs |
| outputs = _outputs |
| deps = _deps |
| } |
| } |
| |
| # Runs pw_python_action once per file over a set of sources. |
| # |
| # This template brings pw_python_action's features to action_foreach. Usage is |
| # the same as pw_python_action, except that sources must be provided and source |
| # expansion (e.g. "{{source}}") may be used in args and outputs. |
| # |
| # See the pw_python_action and action_foreach documentation for full details. |
| template("pw_python_action_foreach") { |
| assert(defined(invoker.sources) && invoker.sources != [], |
| "pw_python_action_foreach requires a list of one or more sources") |
| |
| pw_python_action(target_name) { |
| if (defined(invoker.stamp) && invoker.stamp != false) { |
| if (invoker.stamp == true) { |
| # Use source file names in the generated stamp file path so they are |
| # unique for each source. |
| stamp = "$target_gen_dir/{{source_file_part}}.pw_pystamp" |
| } else { |
| stamp = invoker.stamp |
| } |
| } else { |
| stamp = false |
| } |
| |
| forward_variables_from(invoker, "*", [ "stamp" ]) |
| |
| _pw_action_type = "action_foreach" |
| } |
| } |