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, 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