| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/command_line.h" | 5 #include "base/command_line.h" |
| 6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/process/kill.h" | 8 #include "base/process/kill.h" |
| 9 #include "base/process/launch.h" | 9 #include "base/process/launch.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 return false; | 229 return false; |
| 230 } | 230 } |
| 231 #endif | 231 #endif |
| 232 | 232 |
| 233 } // namespace | 233 } // namespace |
| 234 | 234 |
| 235 const char kExecScript[] = "exec_script"; | 235 const char kExecScript[] = "exec_script"; |
| 236 const char kExecScript_Help[] = | 236 const char kExecScript_Help[] = |
| 237 "exec_script: Synchronously run a script and return the output.\n" | 237 "exec_script: Synchronously run a script and return the output.\n" |
| 238 "\n" | 238 "\n" |
| 239 " exec_script(filename, arguments, input_conversion,\n" | 239 " exec_script(filename,\n" |
| 240 " [file_dependencies])\n" | 240 " arguments = [],\n" |
| 241 " input_conversion = \"\",\n" |
| 242 " file_dependencies = [])\n" |
| 241 "\n" | 243 "\n" |
| 242 " Runs the given script, returning the stdout of the script. The build\n" | 244 " Runs the given script, returning the stdout of the script. The build\n" |
| 243 " generation will fail if the script does not exist or returns a nonzero\n" | 245 " generation will fail if the script does not exist or returns a nonzero\n" |
| 244 " exit code.\n" | 246 " exit code.\n" |
| 245 "\n" | 247 "\n" |
| 246 " The current directory when executing the script will be the root\n" | 248 " The current directory when executing the script will be the root\n" |
| 247 " build directory. If you are passing file names, you will want to use\n" | 249 " build directory. If you are passing file names, you will want to use\n" |
| 248 " the rebase_path() function to make file names relative to this\n" | 250 " the rebase_path() function to make file names relative to this\n" |
| 249 " path (see \"gn help rebase_path\").\n" | 251 " path (see \"gn help rebase_path\").\n" |
| 250 "\n" | 252 "\n" |
| 251 "Arguments:\n" | 253 "Arguments:\n" |
| 252 "\n" | 254 "\n" |
| 253 " filename:\n" | 255 " filename:\n" |
| 254 " File name of python script to execute. Non-absolute names will\n" | 256 " File name of python script to execute. Non-absolute names will\n" |
| 255 " be treated as relative to the current build file.\n" | 257 " be treated as relative to the current build file.\n" |
| 256 "\n" | 258 "\n" |
| 257 " arguments:\n" | 259 " arguments:\n" |
| 258 " A list of strings to be passed to the script as arguments.\n" | 260 " A list of strings to be passed to the script as arguments.\n" |
| 261 " May be unspecified or the empty list which means no arguments.\n" |
| 259 "\n" | 262 "\n" |
| 260 " input_conversion:\n" | 263 " input_conversion:\n" |
| 261 " Controls how the file is read and parsed.\n" | 264 " Controls how the file is read and parsed.\n" |
| 262 " See \"gn help input_conversion\".\n" | 265 " See \"gn help input_conversion\".\n" |
| 263 "\n" | 266 "\n" |
| 267 " If unspecified, defaults to the empty string which causes the\n" |
| 268 " script result to be discarded. exec script will return None.\n" |
| 269 "\n" |
| 264 " dependencies:\n" | 270 " dependencies:\n" |
| 265 " (Optional) A list of files that this script reads or otherwise\n" | 271 " (Optional) A list of files that this script reads or otherwise\n" |
| 266 " depends on. These dependencies will be added to the build result\n" | 272 " depends on. These dependencies will be added to the build result\n" |
| 267 " such that if any of them change, the build will be regenerated and\n" | 273 " such that if any of them change, the build will be regenerated and\n" |
| 268 " the script will be re-run.\n" | 274 " the script will be re-run.\n" |
| 269 "\n" | 275 "\n" |
| 270 " The script itself will be an implicit dependency so you do not\n" | 276 " The script itself will be an implicit dependency so you do not\n" |
| 271 " need to list it.\n" | 277 " need to list it.\n" |
| 272 "\n" | 278 "\n" |
| 273 "Example:\n" | 279 "Example:\n" |
| 274 "\n" | 280 "\n" |
| 275 " all_lines = exec_script(\"myscript.py\", [some_input], \"list lines\",\n" | 281 " all_lines = exec_script(\"myscript.py\", [some_input], \"list lines\",\n" |
| 276 " [ rebase_path(\"data_file.txt\", \".\"," | 282 " [ rebase_path(\"data_file.txt\", \".\"," |
| 277 " root_build_dir) ])\n"; | 283 " root_build_dir) ])\n" |
| 284 "\n" |
| 285 " # This example just calls the script with no arguments and discards\n" |
| 286 " # the result.\n" |
| 287 " exec_script(\"//foo/bar/myscript.py\")\n"; |
| 278 | 288 |
| 279 Value RunExecScript(Scope* scope, | 289 Value RunExecScript(Scope* scope, |
| 280 const FunctionCallNode* function, | 290 const FunctionCallNode* function, |
| 281 const std::vector<Value>& args, | 291 const std::vector<Value>& args, |
| 282 Err* err) { | 292 Err* err) { |
| 283 if (args.size() != 3 && args.size() != 4) { | 293 if (args.size() < 1 || args.size() > 4) { |
| 284 *err = Err(function->function(), "Wrong number of arguments to exec_script", | 294 *err = Err(function->function(), "Wrong number of arguments to exec_script", |
| 285 "I expected three or four arguments."); | 295 "I expected between one and four arguments."); |
| 286 return Value(); | 296 return Value(); |
| 287 } | 297 } |
| 288 | 298 |
| 289 const Settings* settings = scope->settings(); | 299 const Settings* settings = scope->settings(); |
| 290 const BuildSettings* build_settings = settings->build_settings(); | 300 const BuildSettings* build_settings = settings->build_settings(); |
| 291 const SourceDir& cur_dir = scope->GetSourceDir(); | 301 const SourceDir& cur_dir = scope->GetSourceDir(); |
| 292 | 302 |
| 293 // Find the python script to run. | 303 // Find the python script to run. |
| 294 if (!args[0].VerifyTypeIs(Value::STRING, err)) | 304 if (!args[0].VerifyTypeIs(Value::STRING, err)) |
| 295 return Value(); | 305 return Value(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 320 build_settings->GetFullPath(cur_dir.ResolveRelativeFile( | 330 build_settings->GetFullPath(cur_dir.ResolveRelativeFile( |
| 321 deps_value.list_value()[0].string_value()))); | 331 deps_value.list_value()[0].string_value()))); |
| 322 } | 332 } |
| 323 } | 333 } |
| 324 | 334 |
| 325 // Make the command line. | 335 // Make the command line. |
| 326 const base::FilePath& python_path = build_settings->python_path(); | 336 const base::FilePath& python_path = build_settings->python_path(); |
| 327 CommandLine cmdline(python_path); | 337 CommandLine cmdline(python_path); |
| 328 cmdline.AppendArgPath(script_path); | 338 cmdline.AppendArgPath(script_path); |
| 329 | 339 |
| 330 const Value& script_args = args[1]; | 340 if (args.size() >= 2) { |
| 331 if (!script_args.VerifyTypeIs(Value::LIST, err)) | 341 // Optional command-line arguments to the script. |
| 332 return Value(); | 342 const Value& script_args = args[1]; |
| 333 for (size_t i = 0; i < script_args.list_value().size(); i++) { | 343 if (!script_args.VerifyTypeIs(Value::LIST, err)) |
| 334 if (!script_args.list_value()[i].VerifyTypeIs(Value::STRING, err)) | |
| 335 return Value(); | 344 return Value(); |
| 336 cmdline.AppendArg(script_args.list_value()[i].string_value()); | 345 for (size_t i = 0; i < script_args.list_value().size(); i++) { |
| 346 if (!script_args.list_value()[i].VerifyTypeIs(Value::STRING, err)) |
| 347 return Value(); |
| 348 cmdline.AppendArg(script_args.list_value()[i].string_value()); |
| 349 } |
| 337 } | 350 } |
| 338 | 351 |
| 339 // Log command line for debugging help. | 352 // Log command line for debugging help. |
| 340 trace.SetCommandLine(cmdline); | 353 trace.SetCommandLine(cmdline); |
| 341 base::TimeTicks begin_exec; | 354 base::TimeTicks begin_exec; |
| 342 if (g_scheduler->verbose_logging()) { | 355 if (g_scheduler->verbose_logging()) { |
| 343 #if defined(OS_WIN) | 356 #if defined(OS_WIN) |
| 344 g_scheduler->Log("Pythoning", | 357 g_scheduler->Log("Pythoning", |
| 345 base::UTF16ToUTF8(cmdline.GetCommandLineString())); | 358 base::UTF16ToUTF8(cmdline.GetCommandLineString())); |
| 346 #else | 359 #else |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 "\nReturned " + base::IntToString(exit_code); | 400 "\nReturned " + base::IntToString(exit_code); |
| 388 if (!output.empty()) | 401 if (!output.empty()) |
| 389 msg += " and printed out:\n\n" + output; | 402 msg += " and printed out:\n\n" + output; |
| 390 else | 403 else |
| 391 msg += "."; | 404 msg += "."; |
| 392 *err = Err(function->function(), "Script returned non-zero exit code.", | 405 *err = Err(function->function(), "Script returned non-zero exit code.", |
| 393 msg); | 406 msg); |
| 394 return Value(); | 407 return Value(); |
| 395 } | 408 } |
| 396 | 409 |
| 397 return ConvertInputToValue(output, function, args[2], err); | 410 // Default to None value for the input conversion if unspecified. |
| 411 return ConvertInputToValue(output, function, |
| 412 args.size() >= 3 ? args[2] : Value(), err); |
| 398 } | 413 } |
| 399 | 414 |
| 400 } // namespace functions | 415 } // namespace functions |
| OLD | NEW |