• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Args()57 Args::Args() {
58 }
59 
Args(const Args & other)60 Args::Args(const Args& other)
61     : overrides_(other.overrides_),
62       all_overrides_(other.all_overrides_),
63       declared_arguments_(other.declared_arguments_) {
64 }
65 
~Args()66 Args::~Args() {
67 }
68 
AddArgOverride(const char * name,const Value & value)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 
AddArgOverrides(const Scope::KeyValueMap & overrides)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 
SetupRootScope(Scope * dest,const Scope::KeyValueMap & toolchain_overrides) const82 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 
DeclareArgs(const Scope::KeyValueMap & args,Scope * scope_to_set,Err * err) const90 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 
VerifyAllOverridesUsed(Err * err) const149 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 
SetSystemVars(Scope * dest) const165 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 
ApplyOverrides(const Scope::KeyValueMap & values,Scope * scope) const237 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 
SaveOverrideRecord(const Scope::KeyValueMap & values) const244 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