• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
15import("python_action.gni")
16
17# Runs a program which isn't in Python.
18#
19# This is provided to avoid having to write a new Python wrapper script every
20# time a program needs to be run from GN.
21#
22# Args:
23#  program: The program to run. Can be a full path or just a name (in which case
24#    $PATH is searched).
25#
26#  args: Optional list of arguments to the program.
27#
28#  deps: Dependencies for this target.
29#
30#  public_deps: Public dependencies for this target. In addition to outputs from
31#    this target, outputs generated by public dependencies can be used as inputs
32#    from targets that depend on this one. This is not the case for private
33#    deps.
34#
35#  inputs: Optional list of build inputs to the program.
36#
37#  outputs: Optional list of artifacts produced by the program's execution.
38#
39#  env: Optional list of key-value pairs defining environment variables for
40#    the program.
41#
42#  env_file: Optional path to a file containing a list of newline-separated
43#    key-value pairs defining environment variables for the program.
44#
45#  args_file: Optional path to a file containing additional positional arguments
46#    to the program. Each line of the file is appended to the invocation. Useful
47#    for specifying arguments from GN metadata.
48#
49#  skip_empty_args: If args_file is provided, boolean indicating whether to skip
50#    running the program if the file is empty. Used to avoid running commands
51#    which error when called without arguments.
52#
53#  capture_output: If true, output from the program is hidden unless the program
54#    exits with an error. Defaults to true.
55#
56#  working_directory: The working directory to execute the subprocess with. If
57#    not specified it will not be set and the subprocess will have whatever the
58#    parent current working directory is.
59#
60# Example:
61#
62#   pw_exec("hello_world") {
63#     program = "/bin/sh"
64#     args = [
65#       "-c",
66#       "echo hello \$WORLD",
67#     ]
68#     env = [
69#       "WORLD=world",
70#     ]
71#   }
72#
73template("pw_exec") {
74  assert(defined(invoker.program), "pw_exec requires a program to run")
75
76  _script_args = [
77    "--target",
78    target_name,
79  ]
80
81  if (defined(invoker.env_file)) {
82    _script_args += [
83      "--env-file",
84      rebase_path(invoker.env_file, root_build_dir),
85    ]
86  }
87
88  if (defined(invoker.args_file)) {
89    _script_args += [
90      "--args-file",
91      rebase_path(invoker.args_file, root_build_dir),
92    ]
93
94    if (defined(invoker.skip_empty_args) && invoker.skip_empty_args) {
95      _script_args += [ "--skip-empty-args" ]
96    }
97  }
98
99  if (defined(invoker.env)) {
100    foreach(_env, invoker.env) {
101      _script_args += [
102        "--env",
103        _env,
104      ]
105    }
106  }
107
108  if (!defined(invoker.capture_output) || invoker.capture_output) {
109    _script_args += [ "--capture-output" ]
110    _capture_output = true
111  } else {
112    _capture_output = false
113  }
114
115  if (defined(invoker.working_directory)) {
116    _script_args += [
117      "--working-directory",
118      invoker.working_directory,
119    ]
120  }
121
122  _script_args += [
123    "--",
124    invoker.program,
125  ]
126  if (defined(invoker.args)) {
127    _script_args += invoker.args
128  }
129
130  pw_python_action(target_name) {
131    script = "$dir_pw_build/py/pw_build/exec.py"
132    args = _script_args
133    capture_output = _capture_output
134
135    forward_variables_from(invoker,
136                           [
137                             "deps",
138                             "inputs",
139                             "pool",
140                             "public_deps",
141                           ])
142
143    if (!defined(inputs)) {
144      inputs = []
145    }
146    if (defined(invoker.env_file)) {
147      inputs += [ invoker.env_file ]
148    }
149
150    if (defined(invoker.outputs)) {
151      outputs = invoker.outputs
152    } else {
153      stamp = true
154    }
155  }
156}
157