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, external, source_prereqs, 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 // component ------------------------------------------------------------------- 56 57 const char kComponent[] = "component"; 58 const char kComponent_Help[] = 59 "component: Declare a component target.\n" 60 "\n" 61 " A component is a shared library, static library, or source set\n" 62 " depending on the component mode. This allows a project to separate\n" 63 " out a build into shared libraries for faster devlopment (link time is\n" 64 " reduced) but to switch to a static build for releases (for better\n" 65 " performance).\n" 66 "\n" 67 " To use this function you must set the value of the \"component_mode\n" 68 " variable to one of the following strings:\n" 69 " - \"shared_library\"\n" 70 " - \"static_library\"\n" 71 " - \"source_set\"\n" 72 " It is an error to call \"component\" without defining the mode\n" 73 " (typically this is done in the master build configuration file).\n"; 74 75 Value RunComponent(Scope* scope, 76 const FunctionCallNode* function, 77 const std::vector<Value>& args, 78 BlockNode* block, 79 Err* err) { 80 // A component is either a shared or static library, depending on the value 81 // of |component_mode|. 82 const Value* component_mode_value = 83 scope->GetValue(variables::kComponentMode); 84 85 static const char helptext[] = 86 "You're declaring a component here but have not defined " 87 "\"component_mode\" to\neither \"shared_library\" or \"static_library\"."; 88 if (!component_mode_value) { 89 *err = Err(function->function(), "No component mode set.", helptext); 90 return Value(); 91 } 92 if (component_mode_value->type() != Value::STRING || 93 (component_mode_value->string_value() != functions::kSharedLibrary && 94 component_mode_value->string_value() != functions::kStaticLibrary && 95 component_mode_value->string_value() != functions::kSourceSet)) { 96 *err = Err(function->function(), "Invalid component mode set.", helptext); 97 return Value(); 98 } 99 const std::string& component_mode = component_mode_value->string_value(); 100 101 if (!EnsureNotProcessingImport(function, scope, err)) 102 return Value(); 103 Scope block_scope(scope); 104 if (!FillTargetBlockScope(scope, function, component_mode.c_str(), block, 105 args, &block_scope, err)) 106 return Value(); 107 108 block->ExecuteBlockInScope(&block_scope, err); 109 if (err->has_error()) 110 return Value(); 111 112 TargetGenerator::GenerateTarget(&block_scope, function, args, 113 component_mode, err); 114 return Value(); 115 } 116 117 // copy ------------------------------------------------------------------------ 118 119 const char kCopy[] = "copy"; 120 const char kCopy_Help[] = 121 "copy: Declare a target that copies files.\n" 122 "\n" 123 "File name handling\n" 124 "\n" 125 " All output files must be inside the output directory of the build.\n" 126 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n" 127 " reference the output or generated intermediate file directories,\n" 128 " respectively.\n" 129 "\n" 130 " Both \"sources\" and \"outputs\" must be specified. Sources can\n" 131 " as many files as you want, but there can only be one item in the\n" 132 " outputs list (plural is used for the name for consistency with\n" 133 " other target types).\n" 134 "\n" 135 " If there is more than one source file, your output name should specify\n" 136 " a mapping from each source files to output file names using source\n" 137 " expansion (see \"gn help source_expansion\"). The placeholders will\n" 138 " will look like \"{{source_name_part}}\", for example.\n" 139 "\n" 140 "Examples\n" 141 "\n" 142 " # Write a rule that copies a checked-in DLL to the output directory.\n" 143 " copy(\"mydll\") {\n" 144 " sources = [ \"mydll.dll\" ]\n" 145 " outputs = [ \"$target_out_dir/mydll.dll\" ]\n" 146 " }\n" 147 "\n" 148 " # Write a rule to copy several files to the target generated files\n" 149 " # directory.\n" 150 " copy(\"myfiles\") {\n" 151 " sources = [ \"data1.dat\", \"data2.dat\", \"data3.dat\" ]\n" 152 "\n" 153 " # Use source expansion to generate output files with the\n" 154 " # corresponding file names in the gen dir. This will just copy each\n" 155 " # file.\n" 156 " outputs = [ \"$target_gen_dir/{{source_file_part}}\" ]\n" 157 " }\n"; 158 159 Value RunCopy(const FunctionCallNode* function, 160 const std::vector<Value>& args, 161 Scope* scope, 162 Err* err) { 163 if (!EnsureNotProcessingImport(function, scope, err) || 164 !EnsureNotProcessingBuildConfig(function, scope, err)) 165 return Value(); 166 TargetGenerator::GenerateTarget(scope, function, args, functions::kCopy, err); 167 return Value(); 168 } 169 170 // custom ---------------------------------------------------------------------- 171 172 const char kCustom[] = "custom"; 173 const char kCustom_Help[] = 174 "custom: Declare a script-generated target.\n" 175 "\n" 176 " This target type allows you to run a script over a set of source\n" 177 " files and generate a set of output files.\n" 178 "\n" 179 " The script will be executed with the given arguments with the current\n" 180 " directory being that of the root build directory. If you pass files\n" 181 " to your script, see \"gn help to_build_path\" for how to convert\n" 182 " file names to be relative to the build directory (file names in the\n" 183 " sources, outputs, and source_prereqs will be all treated as relative\n" 184 " to the current build file and converted as needed automatically).\n" 185 "\n" 186 " There are two modes. The first mode is the \"per-file\" mode where you\n" 187 " specify a list of sources and the script is run once for each one as a\n" 188 " build rule. In this case, each file specified in the |outputs|\n" 189 " variable must be unique when applied to each source file (normally you\n" 190 " would reference |{{source_name_part}}| from within each one) or the\n" 191 " build system will get confused about how to build those files. You\n" 192 " should use the |source_prereqs| variable to list all additional\n" 193 " dependencies of your script: these will be added as dependencies for\n" 194 " each build step.\n" 195 "\n" 196 " The second mode is when you just want to run a script once rather than\n" 197 " as a general rule over a set of files. In this case you don't list any\n" 198 " sources. Dependencies of your script are specified only in the\n" 199 " |source_prereqs| variable and your |outputs| variable should just list\n" 200 " all outputs.\n" 201 "\n" 202 "File name handling\n" 203 "\n" 204 " All output files must be inside the output directory of the build.\n" 205 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n" 206 " reference the output or generated intermediate file directories,\n" 207 " respectively.\n" 208 "\n" 209 " You can specify a mapping from source files to output files using\n" 210 " source expansion (see \"gn help source_expansion\"). The placeholders\n" 211 " will look like \"{{source}}\", for example, and can appear in\n" 212 " either the outputs or the args lists.\n" 213 "\n" 214 "Variables\n" 215 "\n" 216 " args, deps, outputs, script*, source_prereqs, sources\n" 217 " * = required\n" 218 "\n" 219 "Examples\n" 220 "\n" 221 " # Runs the script over each IDL file. The IDL script will generate\n" 222 " # both a .cc and a .h file for each input.\n" 223 " custom(\"general_rule\") {\n" 224 " script = \"idl_processor.py\"\n" 225 " sources = [ \"foo.idl\", \"bar.idl\" ]\n" 226 " source_prereqs = [ \"my_configuration.txt\" ]\n" 227 " outputs = [ \"$target_gen_dir/{{source_name_part}}.h\",\n" 228 " \"$target_gen_dir/{{source_name_part}}.cc\" ]\n" 229 "\n" 230 " # Note that since \"args\" is opaque to GN, if you specify paths\n" 231 " # here, you will need to convert it to be relative to the build\n" 232 " # directory using \"to_build_path()\".\n" 233 " args = [ \"{{source}}\",\n" 234 " \"-o\",\n" 235 " to_build_path(relative_target_gen_dir) + \"/\" +\n" 236 " {{source_name_part}}.h\" ]\n" 237 " }\n" 238 "\n" 239 " custom(\"just_run_this_guy_once\") {\n" 240 " script = \"doprocessing.py\"\n" 241 " source_prereqs = [ \"my_configuration.txt\" ]\n" 242 " outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n" 243 " args = [ \"--output_dir\", to_build_path(target_gen_dir) ]\n" 244 " }\n"; 245 246 Value RunCustom(Scope* scope, 247 const FunctionCallNode* function, 248 const std::vector<Value>& args, 249 BlockNode* block, 250 Err* err) { 251 return ExecuteGenericTarget(functions::kCustom, scope, function, args, 252 block, err); 253 } 254 255 // executable ------------------------------------------------------------------ 256 257 const char kExecutable[] = "executable"; 258 const char kExecutable_Help[] = 259 "executable: Declare an executable target.\n" 260 "\n" 261 "Variables\n" 262 "\n" 263 CONFIG_VALUES_VARS_HELP 264 DEPS_VARS 265 DEPENDENT_CONFIG_VARS 266 GENERAL_TARGET_VARS; 267 268 Value RunExecutable(Scope* scope, 269 const FunctionCallNode* function, 270 const std::vector<Value>& args, 271 BlockNode* block, 272 Err* err) { 273 return ExecuteGenericTarget(functions::kExecutable, scope, function, args, 274 block, err); 275 } 276 277 // group ----------------------------------------------------------------------- 278 279 const char kGroup[] = "group"; 280 const char kGroup_Help[] = 281 "group: Declare a named group of targets.\n" 282 "\n" 283 " This target type allows you to create meta-targets that just collect a\n" 284 " set of dependencies into one named target. Groups can additionally\n" 285 " specify configs that apply to their dependents.\n" 286 "\n" 287 " Depending on a group is exactly like depending directly on that\n" 288 " group's deps. Direct dependent configs will get automatically fowarded\n" 289 " through the group so you shouldn't need to use\n" 290 " \"forward_dependent_configs_from.\n" 291 "\n" 292 "Variables\n" 293 "\n" 294 DEPS_VARS 295 DEPENDENT_CONFIG_VARS 296 " Other variables: external\n" 297 "\n" 298 "Example\n" 299 "\n" 300 " group(\"all\") {\n" 301 " deps = [\n" 302 " \"//project:runner\",\n" 303 " \"//project:unit_tests\",\n" 304 " ]\n" 305 " }\n"; 306 307 Value RunGroup(Scope* scope, 308 const FunctionCallNode* function, 309 const std::vector<Value>& args, 310 BlockNode* block, 311 Err* err) { 312 return ExecuteGenericTarget(functions::kGroup, scope, function, args, 313 block, err); 314 } 315 316 // shared_library -------------------------------------------------------------- 317 318 const char kSharedLibrary[] = "shared_library"; 319 const char kSharedLibrary_Help[] = 320 "shared_library: Declare a shared library target.\n" 321 "\n" 322 " A shared library will be specified on the linker line for targets\n" 323 " listing the shared library in its \"deps\". If you don't want this\n" 324 " (say you dynamically load the library at runtime), then you should\n" 325 " depend on the shared library via \"datadeps\" instead.\n" 326 "\n" 327 "Variables\n" 328 "\n" 329 CONFIG_VALUES_VARS_HELP 330 DEPS_VARS 331 DEPENDENT_CONFIG_VARS 332 GENERAL_TARGET_VARS; 333 334 Value RunSharedLibrary(Scope* scope, 335 const FunctionCallNode* function, 336 const std::vector<Value>& args, 337 BlockNode* block, 338 Err* err) { 339 return ExecuteGenericTarget(functions::kSharedLibrary, scope, function, args, 340 block, err); 341 } 342 343 // source_set ------------------------------------------------------------------ 344 345 extern const char kSourceSet[] = "source_set"; 346 extern const char kSourceSet_Help[] = 347 "source_set: Declare a source set target.\n" 348 "\n" 349 " A source set is a collection of sources that get compiled, but are not\n" 350 " linked to produce any kind of library. Instead, the resulting object\n" 351 " files are implicitly added to the linker line of all targets that\n" 352 " depend on the source set.\n" 353 "\n" 354 " In most cases, a source set will behave like a static library, except\n" 355 " no actual library file will be produced. This will make the build go\n" 356 " a little faster by skipping creation of a large static library, while\n" 357 " maintaining the organizational benefits of focused build targets.\n" 358 "\n" 359 " The main difference between a source set and a static library is\n" 360 " around handling of exported symbols. Most linkers assume declaring\n" 361 " a function exported means exported from the static library. The linker\n" 362 " can then do dead code elimination to delete code not reachable from\n" 363 " exported functions.\n" 364 "\n" 365 " A source set will not do this code elimination since there is no link\n" 366 " step. This allows you to link many sources sets into a shared library\n" 367 " and have the \"exported symbol\" notation indicate \"export from the\n" 368 " final shared library and not from the intermediate targets.\" There is\n" 369 " no way to express this concept when linking multiple static libraries\n" 370 " into a shared library.\n" 371 "\n" 372 "Variables\n" 373 "\n" 374 CONFIG_VALUES_VARS_HELP 375 DEPS_VARS 376 DEPENDENT_CONFIG_VARS 377 GENERAL_TARGET_VARS; 378 379 Value RunSourceSet(Scope* scope, 380 const FunctionCallNode* function, 381 const std::vector<Value>& args, 382 BlockNode* block, 383 Err* err) { 384 return ExecuteGenericTarget(functions::kSourceSet, scope, function, args, 385 block, err); 386 } 387 388 // static_library -------------------------------------------------------------- 389 390 const char kStaticLibrary[] = "static_library"; 391 const char kStaticLibrary_Help[] = 392 "static_library: Declare a static library target.\n" 393 "\n" 394 " Make a \".a\" / \".lib\" file.\n" 395 "\n" 396 " If you only need the static library for intermediate results in the\n" 397 " build, you should consider a source_set instead since it will skip\n" 398 " the (potentially slow) step of creating the intermediate library file.\n" 399 "\n" 400 "Variables\n" 401 "\n" 402 CONFIG_VALUES_VARS_HELP 403 DEPS_VARS 404 DEPENDENT_CONFIG_VARS 405 GENERAL_TARGET_VARS; 406 407 Value RunStaticLibrary(Scope* scope, 408 const FunctionCallNode* function, 409 const std::vector<Value>& args, 410 BlockNode* block, 411 Err* err) { 412 return ExecuteGenericTarget(functions::kStaticLibrary, scope, function, args, 413 block, err); 414 } 415 416 // test ------------------------------------------------------------------------ 417 418 const char kTest[] = "test"; 419 const char kTest_Help[] = 420 "test: Declares a test target.\n" 421 "\n" 422 " This is like an executable target, but is named differently to make\n" 423 " the purpose of the target more obvious. It's possible in the future\n" 424 " we can do some enhancements like \"list all of the tests in a given\n" 425 " directory\".\n" 426 "\n" 427 " See \"gn help executable\" for usage.\n"; 428 429 Value RunTest(Scope* scope, 430 const FunctionCallNode* function, 431 const std::vector<Value>& args, 432 BlockNode* block, 433 Err* err) { 434 return ExecuteGenericTarget(functions::kExecutable, scope, function, args, 435 block, err); 436 } 437 438 } // namespace functions 439