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 3 // found in the LICENSE file. 4 5 #include "tools/gn/functions.h" 6 7 #include "tools/gn/config_values_generator.h" 8 #include "tools/gn/err.h" 9 #include "tools/gn/parse_tree.h" 10 #include "tools/gn/scope.h" 11 #include "tools/gn/target_generator.h" 12 #include "tools/gn/value.h" 13 #include "tools/gn/variables.h" 14 15 #define DEPENDENT_CONFIG_VARS \ 16 " Dependent configs: all_dependent_configs, direct_dependent_configs\n" 17 #define DEPS_VARS \ 18 " Deps: data, datadeps, deps, forward_dependent_configs_from, hard_dep\n" 19 #define GENERAL_TARGET_VARS \ 20 " General: configs, inputs, sources\n" 21 22 namespace functions { 23 24 namespace { 25 26 Value ExecuteGenericTarget(const char* target_type, 27 Scope* scope, 28 const FunctionCallNode* function, 29 const std::vector<Value>& args, 30 BlockNode* block, 31 Err* err) { 32 if (!EnsureNotProcessingImport(function, scope, err) || 33 !EnsureNotProcessingBuildConfig(function, scope, err)) 34 return Value(); 35 Scope block_scope(scope); 36 if (!FillTargetBlockScope(scope, function, target_type, block, 37 args, &block_scope, err)) 38 return Value(); 39 40 block->ExecuteBlockInScope(&block_scope, err); 41 if (err->has_error()) 42 return Value(); 43 44 TargetGenerator::GenerateTarget(&block_scope, function, args, 45 target_type, err); 46 if (err->has_error()) 47 return Value(); 48 49 block_scope.CheckForUnusedVars(err); 50 return Value(); 51 } 52 53 } // namespace 54 55 // action ---------------------------------------------------------------------- 56 57 // Common help paragraph on script runtime execution directories. 58 #define SCRIPT_EXECUTION_CONTEXT \ 59 " The script will be executed with the given arguments with the current\n"\ 60 " directory being that of the root build directory. If you pass files\n"\ 61 " to your script, see \"gn help rebase_path\" for how to convert\n" \ 62 " file names to be relative to the build directory (file names in the\n" \ 63 " sources, outputs, and inputs will be all treated as relative to the\n" \ 64 " current build file and converted as needed automatically).\n" 65 66 // Common help paragraph on script output directories. 67 #define SCRIPT_EXECUTION_OUTPUTS \ 68 " All output files must be inside the output directory of the build.\n" \ 69 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n" \ 70 " reference the output or generated intermediate file directories,\n" \ 71 " respectively.\n" 72 73 #define ACTION_DEPS \ 74 " The \"deps\" for an action will always be completed before any part\n" \ 75 " of the action is run so it can depend on the output of previous\n" \ 76 " steps. The \"datadeps\" will be built if the action is built, but\n" \ 77 " may not have completed before all steps of the action are started.\n" \ 78 " This can give additional parallelism in the build for runtime-only\n" \ 79 " dependencies.\n" 80 81 const char kAction[] = "action"; 82 const char kAction_HelpShort[] = 83 "action: Declare a target that runs a script a single time."; 84 const char kAction_Help[] = 85 "action: Declare a target that runs a script a single time.\n" 86 "\n" 87 " This target type allows you to run a script a single time to produce\n" 88 " or more output files. If you want to run a script once for each of a\n" 89 " set of input files, see \"gn help action_foreach\".\n" 90 "\n" 91 "Inputs\n" 92 "\n" 93 " In an action the \"sources\" and \"inputs\" are treated the same:\n" 94 " they're both input dependencies on script execution with no special\n" 95 " handling. If you want to pass the sources to your script, you must do\n" 96 " so explicitly by including them in the \"args\". Note also that this\n" 97 " means there is no special handling of paths since GN doesn't know\n" 98 " which of the args are paths and not. You will want to use\n" 99 " rebase_path() to convert paths to be relative to the root_build_dir.\n" 100 "\n" 101 " You can dynamically write input dependencies (for incremental rebuilds\n" 102 " if an input file changes) by writing a depfile when the script is run\n" 103 " (see \"gn help depfile\"). This is more flexible than \"inputs\".\n" 104 "\n" 105 " It is recommended you put inputs to your script in the \"sources\"\n" 106 " variable, and stuff like other Python files required to run your\n" 107 " script in the \"inputs\" variable.\n" 108 "\n" 109 ACTION_DEPS 110 "\n" 111 "Outputs\n" 112 "\n" 113 " You should specify files created by your script by specifying them in\n" 114 " the \"outputs\".\n" 115 "\n" 116 SCRIPT_EXECUTION_CONTEXT 117 "\n" 118 "File name handling\n" 119 "\n" 120 SCRIPT_EXECUTION_OUTPUTS 121 "\n" 122 "Variables\n" 123 "\n" 124 " args, data, datadeps, depfile, deps, outputs*, script*,\n" 125 " inputs, sources\n" 126 " * = required\n" 127 "\n" 128 "Example\n" 129 "\n" 130 " action(\"run_this_guy_once\") {\n" 131 " script = \"doprocessing.py\"\n" 132 " sources = [ \"my_configuration.txt\" ]\n" 133 " outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n" 134 "\n" 135 " # Our script imports this Python file so we want to rebuild if it\n" 136 " # changes.\n" 137 " inputs = [ \"helper_library.py\" ]\n" 138 "\n" 139 " # Note that we have to manually pass the sources to our script if\n" 140 " # the script needs them as inputs.\n" 141 " args = [ \"--out\", rebase_path(target_gen_dir, root_build_dir) ] +\n" 142 " rebase_path(sources, root_build_dir)\n" 143 " }\n"; 144 145 Value RunAction(Scope* scope, 146 const FunctionCallNode* function, 147 const std::vector<Value>& args, 148 BlockNode* block, 149 Err* err) { 150 return ExecuteGenericTarget(functions::kAction, scope, function, args, 151 block, err); 152 } 153 154 // action_foreach -------------------------------------------------------------- 155 156 const char kActionForEach[] = "action_foreach"; 157 const char kActionForEach_HelpShort[] = 158 "action_foreach: Declare a target that runs a script over a set of files."; 159 const char kActionForEach_Help[] = 160 "action_foreach: Declare a target that runs a script over a set of files.\n" 161 "\n" 162 " This target type allows you to run a script once-per-file over a set\n" 163 " of sources. If you want to run a script once that takes many files as\n" 164 " input, see \"gn help action\".\n" 165 "\n" 166 "Inputs\n" 167 "\n" 168 " The script will be run once per file in the \"sources\" variable. The\n" 169 " \"outputs\" variable should specify one or more files with a source\n" 170 " expansion pattern in it (see \"gn help source_expansion\"). The output\n" 171 " file(s) for each script invocation should be unique. Normally you\n" 172 " use \"{{source_name_part}}\" in each output file.\n" 173 "\n" 174 " If your script takes additional data as input, such as a shared\n" 175 " configuration file or a Python module it uses, those files should be\n" 176 " listed in the \"inputs\" variable. These files are treated as\n" 177 " dependencies of each script invocation.\n" 178 "\n" 179 " You can dynamically write input dependencies (for incremental rebuilds\n" 180 " if an input file changes) by writing a depfile when the script is run\n" 181 " (see \"gn help depfile\"). This is more flexible than \"inputs\".\n" 182 "\n" 183 ACTION_DEPS 184 "\n" 185 "Outputs\n" 186 "\n" 187 SCRIPT_EXECUTION_CONTEXT 188 "\n" 189 "File name handling\n" 190 "\n" 191 SCRIPT_EXECUTION_OUTPUTS 192 "\n" 193 "Variables\n" 194 "\n" 195 " args, data, datadeps, depfile, deps, outputs*, script*,\n" 196 " inputs, sources*\n" 197 " * = required\n" 198 "\n" 199 "Example\n" 200 "\n" 201 " # Runs the script over each IDL file. The IDL script will generate\n" 202 " # both a .cc and a .h file for each input.\n" 203 " action_foreach(\"my_idl\") {\n" 204 " script = \"idl_processor.py\"\n" 205 " sources = [ \"foo.idl\", \"bar.idl\" ]\n" 206 "\n" 207 " # Our script reads this file each time, so we need to list is as a\n" 208 " # dependency so we can rebuild if it changes.\n" 209 " inputs = [ \"my_configuration.txt\" ]\n" 210 "\n" 211 " # Transformation from source file name to output file names.\n" 212 " outputs = [ \"$target_gen_dir/{{source_name_part}}.h\",\n" 213 " \"$target_gen_dir/{{source_name_part}}.cc\" ]\n" 214 "\n" 215 " # Note that since \"args\" is opaque to GN, if you specify paths\n" 216 " # here, you will need to convert it to be relative to the build\n" 217 " # directory using \"rebase_path()\".\n" 218 " args = [\n" 219 " \"{{source}}\",\n" 220 " \"-o\",\n" 221 " rebase_path(relative_target_gen_dir, root_build_dir) +\n" 222 " \"/{{source_name_part}}.h\" ]\n" 223 " }\n" 224 "\n"; 225 Value RunActionForEach(Scope* scope, 226 const FunctionCallNode* function, 227 const std::vector<Value>& args, 228 BlockNode* block, 229 Err* err) { 230 return ExecuteGenericTarget(functions::kActionForEach, scope, function, args, 231 block, err); 232 } 233 234 // component ------------------------------------------------------------------- 235 236 const char kComponent[] = "component"; 237 const char kComponent_HelpShort[] = 238 "component: Declare a component target."; 239 const char kComponent_Help[] = 240 "component: Declare a component target.\n" 241 "\n" 242 " A component is a shared library, static library, or source set\n" 243 " depending on the component mode. This allows a project to separate\n" 244 " out a build into shared libraries for faster development (link time is\n" 245 " reduced) but to switch to a static build for releases (for better\n" 246 " performance).\n" 247 "\n" 248 " To use this function you must set the value of the \"component_mode\"\n" 249 " variable to one of the following strings:\n" 250 " - \"shared_library\"\n" 251 " - \"static_library\"\n" 252 " - \"source_set\"\n" 253 " It is an error to call \"component\" without defining the mode\n" 254 " (typically this is done in the master build configuration file).\n"; 255 256 Value RunComponent(Scope* scope, 257 const FunctionCallNode* function, 258 const std::vector<Value>& args, 259 BlockNode* block, 260 Err* err) { 261 // A component is either a shared or static library, depending on the value 262 // of |component_mode|. 263 const Value* component_mode_value = 264 scope->GetValue(variables::kComponentMode); 265 266 static const char helptext[] = 267 "You're declaring a component here but have not defined " 268 "\"component_mode\" to\neither \"shared_library\" or \"static_library\"."; 269 if (!component_mode_value) { 270 *err = Err(function->function(), "No component mode set.", helptext); 271 return Value(); 272 } 273 if (component_mode_value->type() != Value::STRING || 274 (component_mode_value->string_value() != functions::kSharedLibrary && 275 component_mode_value->string_value() != functions::kStaticLibrary && 276 component_mode_value->string_value() != functions::kSourceSet)) { 277 *err = Err(function->function(), "Invalid component mode set.", helptext); 278 return Value(); 279 } 280 const std::string& component_mode = component_mode_value->string_value(); 281 282 if (!EnsureNotProcessingImport(function, scope, err)) 283 return Value(); 284 Scope block_scope(scope); 285 if (!FillTargetBlockScope(scope, function, component_mode.c_str(), block, 286 args, &block_scope, err)) 287 return Value(); 288 289 block->ExecuteBlockInScope(&block_scope, err); 290 if (err->has_error()) 291 return Value(); 292 293 TargetGenerator::GenerateTarget(&block_scope, function, args, 294 component_mode, err); 295 return Value(); 296 } 297 298 // copy ------------------------------------------------------------------------ 299 300 const char kCopy[] = "copy"; 301 const char kCopy_HelpShort[] = 302 "copy: Declare a target that copies files."; 303 const char kCopy_Help[] = 304 "copy: Declare a target that copies files.\n" 305 "\n" 306 "File name handling\n" 307 "\n" 308 " All output files must be inside the output directory of the build.\n" 309 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n" 310 " reference the output or generated intermediate file directories,\n" 311 " respectively.\n" 312 "\n" 313 " Both \"sources\" and \"outputs\" must be specified. Sources can\n" 314 " as many files as you want, but there can only be one item in the\n" 315 " outputs list (plural is used for the name for consistency with\n" 316 " other target types).\n" 317 "\n" 318 " If there is more than one source file, your output name should specify\n" 319 " a mapping from each source files to output file names using source\n" 320 " expansion (see \"gn help source_expansion\"). The placeholders will\n" 321 " will look like \"{{source_name_part}}\", for example.\n" 322 "\n" 323 "Examples\n" 324 "\n" 325 " # Write a rule that copies a checked-in DLL to the output directory.\n" 326 " copy(\"mydll\") {\n" 327 " sources = [ \"mydll.dll\" ]\n" 328 " outputs = [ \"$target_out_dir/mydll.dll\" ]\n" 329 " }\n" 330 "\n" 331 " # Write a rule to copy several files to the target generated files\n" 332 " # directory.\n" 333 " copy(\"myfiles\") {\n" 334 " sources = [ \"data1.dat\", \"data2.dat\", \"data3.dat\" ]\n" 335 "\n" 336 " # Use source expansion to generate output files with the\n" 337 " # corresponding file names in the gen dir. This will just copy each\n" 338 " # file.\n" 339 " outputs = [ \"$target_gen_dir/{{source_file_part}}\" ]\n" 340 " }\n"; 341 342 Value RunCopy(const FunctionCallNode* function, 343 const std::vector<Value>& args, 344 Scope* scope, 345 Err* err) { 346 if (!EnsureNotProcessingImport(function, scope, err) || 347 !EnsureNotProcessingBuildConfig(function, scope, err)) 348 return Value(); 349 TargetGenerator::GenerateTarget(scope, function, args, functions::kCopy, err); 350 return Value(); 351 } 352 353 // executable ------------------------------------------------------------------ 354 355 const char kExecutable[] = "executable"; 356 const char kExecutable_HelpShort[] = 357 "executable: Declare an executable target."; 358 const char kExecutable_Help[] = 359 "executable: Declare an executable target.\n" 360 "\n" 361 "Variables\n" 362 "\n" 363 CONFIG_VALUES_VARS_HELP 364 DEPS_VARS 365 DEPENDENT_CONFIG_VARS 366 GENERAL_TARGET_VARS; 367 368 Value RunExecutable(Scope* scope, 369 const FunctionCallNode* function, 370 const std::vector<Value>& args, 371 BlockNode* block, 372 Err* err) { 373 return ExecuteGenericTarget(functions::kExecutable, scope, function, args, 374 block, err); 375 } 376 377 // group ----------------------------------------------------------------------- 378 379 const char kGroup[] = "group"; 380 const char kGroup_HelpShort[] = 381 "group: Declare a named group of targets."; 382 const char kGroup_Help[] = 383 "group: Declare a named group of targets.\n" 384 "\n" 385 " This target type allows you to create meta-targets that just collect a\n" 386 " set of dependencies into one named target. Groups can additionally\n" 387 " specify configs that apply to their dependents.\n" 388 "\n" 389 " Depending on a group is exactly like depending directly on that\n" 390 " group's deps. Direct dependent configs will get automatically\n" 391 " forwarded through the group so you shouldn't need to use\n" 392 " \"forward_dependent_configs_from.\n" 393 "\n" 394 "Variables\n" 395 "\n" 396 DEPS_VARS 397 DEPENDENT_CONFIG_VARS 398 "\n" 399 "Example\n" 400 "\n" 401 " group(\"all\") {\n" 402 " deps = [\n" 403 " \"//project:runner\",\n" 404 " \"//project:unit_tests\",\n" 405 " ]\n" 406 " }\n"; 407 408 Value RunGroup(Scope* scope, 409 const FunctionCallNode* function, 410 const std::vector<Value>& args, 411 BlockNode* block, 412 Err* err) { 413 return ExecuteGenericTarget(functions::kGroup, scope, function, args, 414 block, err); 415 } 416 417 // shared_library -------------------------------------------------------------- 418 419 const char kSharedLibrary[] = "shared_library"; 420 const char kSharedLibrary_HelpShort[] = 421 "shared_library: Declare a shared library target."; 422 const char kSharedLibrary_Help[] = 423 "shared_library: Declare a shared library target.\n" 424 "\n" 425 " A shared library will be specified on the linker line for targets\n" 426 " listing the shared library in its \"deps\". If you don't want this\n" 427 " (say you dynamically load the library at runtime), then you should\n" 428 " depend on the shared library via \"datadeps\" instead.\n" 429 "\n" 430 "Variables\n" 431 "\n" 432 CONFIG_VALUES_VARS_HELP 433 DEPS_VARS 434 DEPENDENT_CONFIG_VARS 435 GENERAL_TARGET_VARS; 436 437 Value RunSharedLibrary(Scope* scope, 438 const FunctionCallNode* function, 439 const std::vector<Value>& args, 440 BlockNode* block, 441 Err* err) { 442 return ExecuteGenericTarget(functions::kSharedLibrary, scope, function, args, 443 block, err); 444 } 445 446 // source_set ------------------------------------------------------------------ 447 448 extern const char kSourceSet[] = "source_set"; 449 extern const char kSourceSet_HelpShort[] = 450 "source_set: Declare a source set target."; 451 extern const char kSourceSet_Help[] = 452 "source_set: Declare a source set target.\n" 453 "\n" 454 " A source set is a collection of sources that get compiled, but are not\n" 455 " linked to produce any kind of library. Instead, the resulting object\n" 456 " files are implicitly added to the linker line of all targets that\n" 457 " depend on the source set.\n" 458 "\n" 459 " In most cases, a source set will behave like a static library, except\n" 460 " no actual library file will be produced. This will make the build go\n" 461 " a little faster by skipping creation of a large static library, while\n" 462 " maintaining the organizational benefits of focused build targets.\n" 463 "\n" 464 " The main difference between a source set and a static library is\n" 465 " around handling of exported symbols. Most linkers assume declaring\n" 466 " a function exported means exported from the static library. The linker\n" 467 " can then do dead code elimination to delete code not reachable from\n" 468 " exported functions.\n" 469 "\n" 470 " A source set will not do this code elimination since there is no link\n" 471 " step. This allows you to link many sources sets into a shared library\n" 472 " and have the \"exported symbol\" notation indicate \"export from the\n" 473 " final shared library and not from the intermediate targets.\" There is\n" 474 " no way to express this concept when linking multiple static libraries\n" 475 " into a shared library.\n" 476 "\n" 477 "Variables\n" 478 "\n" 479 CONFIG_VALUES_VARS_HELP 480 DEPS_VARS 481 DEPENDENT_CONFIG_VARS 482 GENERAL_TARGET_VARS; 483 484 Value RunSourceSet(Scope* scope, 485 const FunctionCallNode* function, 486 const std::vector<Value>& args, 487 BlockNode* block, 488 Err* err) { 489 return ExecuteGenericTarget(functions::kSourceSet, scope, function, args, 490 block, err); 491 } 492 493 // static_library -------------------------------------------------------------- 494 495 const char kStaticLibrary[] = "static_library"; 496 const char kStaticLibrary_HelpShort[] = 497 "static_library: Declare a static library target."; 498 const char kStaticLibrary_Help[] = 499 "static_library: Declare a static library target.\n" 500 "\n" 501 " Make a \".a\" / \".lib\" file.\n" 502 "\n" 503 " If you only need the static library for intermediate results in the\n" 504 " build, you should consider a source_set instead since it will skip\n" 505 " the (potentially slow) step of creating the intermediate library file.\n" 506 "\n" 507 "Variables\n" 508 "\n" 509 CONFIG_VALUES_VARS_HELP 510 DEPS_VARS 511 DEPENDENT_CONFIG_VARS 512 GENERAL_TARGET_VARS; 513 514 Value RunStaticLibrary(Scope* scope, 515 const FunctionCallNode* function, 516 const std::vector<Value>& args, 517 BlockNode* block, 518 Err* err) { 519 return ExecuteGenericTarget(functions::kStaticLibrary, scope, function, args, 520 block, err); 521 } 522 523 // test ------------------------------------------------------------------------ 524 525 const char kTest[] = "test"; 526 const char kTest_HelpShort[] = 527 "test: Declares a test target."; 528 const char kTest_Help[] = 529 "test: Declares a test target.\n" 530 "\n" 531 " This is like an executable target, but is named differently to make\n" 532 " the purpose of the target more obvious. It's possible in the future\n" 533 " we can do some enhancements like \"list all of the tests in a given\n" 534 " directory\".\n" 535 "\n" 536 " See \"gn help executable\" for usage.\n"; 537 538 Value RunTest(Scope* scope, 539 const FunctionCallNode* function, 540 const std::vector<Value>& args, 541 BlockNode* block, 542 Err* err) { 543 return ExecuteGenericTarget(functions::kExecutable, scope, function, args, 544 block, err); 545 } 546 547 } // namespace functions 548