Home | History | Annotate | Download | only in gn
      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