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/args.h"
      6 
      7 #include "build/build_config.h"
      8 #include "tools/gn/variables.h"
      9 
     10 #if defined(OS_WIN)
     11 #include "base/win/windows_version.h"
     12 #endif
     13 
     14 const char kBuildArgs_Help[] =
     15     "Build Arguments Overview\n"
     16     "\n"
     17     "  Build arguments are variables passed in from outside of the build\n"
     18     "  that build files can query to determine how the build works.\n"
     19     "\n"
     20     "How build arguments are set\n"
     21     "\n"
     22     "  First, system default arguments are set based on the current system.\n"
     23     "  The built-in arguments are:\n"
     24     "   - cpu_arch (by default this is the same as \"default_cpu_arch\")\n"
     25     "   - default_cpu_arch\n"
     26     "   - default_os\n"
     27     "   - os (by default this is the same as \"default_os\")\n"
     28     "\n"
     29     "  Second, arguments specified on the command-line via \"--args\" are\n"
     30     "  applied. These can override the system default ones, and add new ones.\n"
     31     "  These are whitespace-separated. For example:\n"
     32     "\n"
     33     "    gn --args=\"enable_doom_melon=false\" os=\\\"beos\\\"\n"
     34     "\n"
     35     "  Third, toolchain overrides are applied. These are specified in the\n"
     36     "  toolchain_args section of a toolchain definition. The use-case for\n"
     37     "  this is that a toolchain may be building code for a different\n"
     38     "  platform, and that it may want to always specify Posix, for example.\n"
     39     "  See \"gn help toolchain_args\" for more.\n"
     40     "\n"
     41     "  It is an error to specify an override for a build argument that never\n"
     42     "  appears in a \"declare_args\" call.\n"
     43     "\n"
     44     "How build arguments are used\n"
     45     "\n"
     46     "  If you want to use an argument, you use declare_args() and specify\n"
     47     "  default values. These default values will apply if none of the steps\n"
     48     "  listed in the \"How build arguments are set\" section above apply to\n"
     49     "  the given argument, but the defaults will not override any of these.\n"
     50     "\n"
     51     "  Often, the root build config file will declare global arguments that\n"
     52     "  will be passed to all buildfiles. Individual build files can also\n"
     53     "  specify arguments that apply only to those files. It is also usedful\n"
     54     "  to specify build args in an \"import\"-ed file if you want such\n"
     55     "  arguments to apply to multiple buildfiles.\n";
     56 
     57 Args::Args() {
     58 }
     59 
     60 Args::Args(const Args& other)
     61     : overrides_(other.overrides_),
     62       all_overrides_(other.all_overrides_),
     63       declared_arguments_(other.declared_arguments_) {
     64 }
     65 
     66 Args::~Args() {
     67 }
     68 
     69 void Args::AddArgOverride(const char* name, const Value& value) {
     70   overrides_[base::StringPiece(name)] = value;
     71   all_overrides_[base::StringPiece(name)] = value;
     72 }
     73 
     74 void Args::AddArgOverrides(const Scope::KeyValueMap& overrides) {
     75   for (Scope::KeyValueMap::const_iterator i = overrides.begin();
     76        i != overrides.end(); ++i) {
     77     overrides_[i->first] = i->second;
     78     all_overrides_[i->first] = i->second;
     79   }
     80 }
     81 
     82 void Args::SetupRootScope(Scope* dest,
     83                           const Scope::KeyValueMap& toolchain_overrides) const {
     84   SetSystemVars(dest);
     85   ApplyOverrides(overrides_, dest);
     86   ApplyOverrides(toolchain_overrides, dest);
     87   SaveOverrideRecord(toolchain_overrides);
     88 }
     89 
     90 bool Args::DeclareArgs(const Scope::KeyValueMap& args,
     91                        Scope* scope_to_set,
     92                        Err* err) const {
     93   base::AutoLock lock(lock_);
     94 
     95   for (Scope::KeyValueMap::const_iterator i = args.begin();
     96        i != args.end(); ++i) {
     97     // Verify that the value hasn't already been declared. We want each value
     98     // to be declared only once.
     99     //
    100     // The tricky part is that a buildfile can be interpreted multiple times
    101     // when used from different toolchains, so we can't just check that we've
    102     // seen it before. Instead, we check that the location matches. We
    103     // additionally check that the value matches to prevent people from
    104     // declaring defaults based on other parameters that may change. The
    105     // rationale is that you should have exactly one default value for each
    106     // argument that we can display in the help.
    107     Scope::KeyValueMap::iterator previously_declared =
    108         declared_arguments_.find(i->first);
    109     if (previously_declared != declared_arguments_.end()) {
    110       if (previously_declared->second.origin() != i->second.origin()) {
    111         // Declaration location mismatch.
    112         *err = Err(i->second.origin(), "Duplicate build arg declaration.",
    113             "Here you're declaring an argument that was already declared "
    114             "elsewhere.\nYou can only declare each argument once in the entire "
    115             "build so there is one\ncanonical place for documentation and the "
    116             "default value. Either move this\nargument to the build config "
    117             "file (for visibility everywhere) or to a .gni file\nthat you "
    118             "\"import\" from the files where you need it (preferred).");
    119         err->AppendSubErr(Err(previously_declared->second.origin(),
    120                               "Previous declaration.",
    121                               "See also \"gn help buildargs\" for more on how "
    122                               "build args work."));
    123         return false;
    124       } else if (previously_declared->second != i->second) {
    125         // Default value mismatch.
    126         *err = Err(i->second.origin(),
    127             "Non-constant default value for build arg.",
    128             "Each build arg should have one default value so we report it "
    129             "nicely in the\n\"gn args\" command. Please make this value "
    130             "constant.");
    131         return false;
    132       }
    133     } else {
    134       declared_arguments_.insert(*i);
    135     }
    136 
    137     // Only set on the current scope to the new value if it hasn't been already
    138     // set. Mark the variable used so the build script can override it in
    139     // certain cases without getting unused value errors.
    140     if (!scope_to_set->GetValue(i->first)) {
    141       scope_to_set->SetValue(i->first, i->second, i->second.origin());
    142       scope_to_set->MarkUsed(i->first);
    143     }
    144   }
    145 
    146   return true;
    147 }
    148 
    149 bool Args::VerifyAllOverridesUsed(Err* err) const {
    150   base::AutoLock lock(lock_);
    151 
    152   for (Scope::KeyValueMap::const_iterator i = all_overrides_.begin();
    153        i != all_overrides_.end(); ++i) {
    154     if (declared_arguments_.find(i->first) == declared_arguments_.end()) {
    155       *err = Err(i->second.origin(), "Build arg has no effect.",
    156           "The value \"" + i->first.as_string() + "\" was set a build "
    157           "argument\nbut never appeared in a declare_args() block in any "
    158           "buildfile.");
    159       return false;
    160     }
    161   }
    162   return true;
    163 }
    164 
    165 void Args::SetSystemVars(Scope* dest) const {
    166   // Host OS.
    167   const char* os = NULL;
    168 #if defined(OS_WIN)
    169   os = "win";
    170 #elif defined(OS_MACOSX)
    171   os = "mac";
    172 #elif defined(OS_LINUX)
    173   os = "linux";
    174 #else
    175   #error Unknown OS type.
    176 #endif
    177   Value os_val(NULL, std::string(os));
    178   dest->SetValue(variables::kBuildOs, os_val, NULL);
    179   dest->SetValue(variables::kOs, os_val, NULL);
    180 
    181   // Host architecture.
    182   static const char kX86[] = "x86";
    183   static const char kX64[] = "x64";
    184   const char* arch = NULL;
    185 #if defined(OS_WIN)
    186   // ...on Windows, set the CPU architecture based on the underlying OS, not
    187   // whatever the current bit-tedness of the GN binary is.
    188   const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
    189   switch (os_info->architecture()) {
    190     case base::win::OSInfo::X86_ARCHITECTURE:
    191       arch = kX86;
    192       break;
    193     case base::win::OSInfo::X64_ARCHITECTURE:
    194       arch = kX64;
    195       break;
    196     default:
    197       CHECK(false) << "Windows architecture not handled.";
    198       break;
    199   }
    200 #else
    201   // ...on all other platforms, just use the bit-tedness of the current
    202   // process.
    203   #if defined(ARCH_CPU_X86_64)
    204     arch = kX64;
    205   #elif defined(ARCH_CPU_X86)
    206     arch = kX86;
    207   #elif defined(ARCH_CPU_ARMEL)
    208     static const char kArm[] = "arm";
    209     arch = kArm;
    210   #else
    211     #error Unknown architecture.
    212   #endif
    213 #endif
    214   // Avoid unused var warning.
    215   (void)kX86;
    216   (void)kX64;
    217 
    218   Value arch_val(NULL, std::string(arch));
    219   dest->SetValue(variables::kBuildCpuArch, arch_val, NULL);
    220   dest->SetValue(variables::kCpuArch, arch_val, NULL);
    221 
    222   // Save the OS and architecture as build arguments that are implicitly
    223   // declared. This is so they can be overridden in a toolchain build args
    224   // override, and so that they will appear in the "gn args" output.
    225   //
    226   // Do not declare the build* variants since these shouldn't be changed.
    227   //
    228   // Mark these variables used so the build config file can override them
    229   // without geting a warning about overwriting an unused variable.
    230   declared_arguments_[variables::kOs] = os_val;
    231   declared_arguments_[variables::kCpuArch] = arch_val;
    232   dest->MarkUsed(variables::kCpuArch);
    233   dest->MarkUsed(variables::kOs);
    234 }
    235 
    236 
    237 void Args::ApplyOverrides(const Scope::KeyValueMap& values,
    238                           Scope* scope) const {
    239   for (Scope::KeyValueMap::const_iterator i = values.begin();
    240        i != values.end(); ++i)
    241     scope->SetValue(i->first, i->second, i->second.origin());
    242 }
    243 
    244 void Args::SaveOverrideRecord(const Scope::KeyValueMap& values) const {
    245   base::AutoLock lock(lock_);
    246   for (Scope::KeyValueMap::const_iterator i = values.begin();
    247        i != values.end(); ++i)
    248     all_overrides_[i->first] = i->second;
    249 }
    250