Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / tools / gn / args.cc
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 useful\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   base::AutoLock lock(lock_);
71
72   overrides_[base::StringPiece(name)] = value;
73   all_overrides_[base::StringPiece(name)] = value;
74 }
75
76 void Args::AddArgOverrides(const Scope::KeyValueMap& overrides) {
77   base::AutoLock lock(lock_);
78
79   for (Scope::KeyValueMap::const_iterator i = overrides.begin();
80        i != overrides.end(); ++i) {
81     overrides_[i->first] = i->second;
82     all_overrides_[i->first] = i->second;
83   }
84 }
85
86 const Value* Args::GetArgOverride(const char* name) const {
87   base::AutoLock lock(lock_);
88
89   Scope::KeyValueMap::const_iterator found =
90       all_overrides_.find(base::StringPiece(name));
91   if (found == all_overrides_.end())
92     return NULL;
93   return &found->second;
94 }
95
96 Scope::KeyValueMap Args::GetAllOverrides() const {
97   base::AutoLock lock(lock_);
98   return all_overrides_;
99 }
100
101 void Args::SetupRootScope(Scope* dest,
102                           const Scope::KeyValueMap& toolchain_overrides) const {
103   base::AutoLock lock(lock_);
104
105   SetSystemVarsLocked(dest);
106   ApplyOverridesLocked(overrides_, dest);
107   ApplyOverridesLocked(toolchain_overrides, dest);
108   SaveOverrideRecordLocked(toolchain_overrides);
109 }
110
111 bool Args::DeclareArgs(const Scope::KeyValueMap& args,
112                        Scope* scope_to_set,
113                        Err* err) const {
114   base::AutoLock lock(lock_);
115
116   for (Scope::KeyValueMap::const_iterator i = args.begin();
117        i != args.end(); ++i) {
118     // Verify that the value hasn't already been declared. We want each value
119     // to be declared only once.
120     //
121     // The tricky part is that a buildfile can be interpreted multiple times
122     // when used from different toolchains, so we can't just check that we've
123     // seen it before. Instead, we check that the location matches.
124     Scope::KeyValueMap::iterator previously_declared =
125         declared_arguments_.find(i->first);
126     if (previously_declared != declared_arguments_.end()) {
127       if (previously_declared->second.origin() != i->second.origin()) {
128         // Declaration location mismatch.
129         *err = Err(i->second.origin(), "Duplicate build argument declaration.",
130             "Here you're declaring an argument that was already declared "
131             "elsewhere.\nYou can only declare each argument once in the entire "
132             "build so there is one\ncanonical place for documentation and the "
133             "default value. Either move this\nargument to the build config "
134             "file (for visibility everywhere) or to a .gni file\nthat you "
135             "\"import\" from the files where you need it (preferred).");
136         err->AppendSubErr(Err(previously_declared->second.origin(),
137                               "Previous declaration.",
138                               "See also \"gn help buildargs\" for more on how "
139                               "build arguments work."));
140         return false;
141       }
142     } else {
143       declared_arguments_.insert(*i);
144     }
145
146     // Only set on the current scope to the new value if it hasn't been already
147     // set. Mark the variable used so the build script can override it in
148     // certain cases without getting unused value errors.
149     if (!scope_to_set->GetValue(i->first)) {
150       scope_to_set->SetValue(i->first, i->second, i->second.origin());
151       scope_to_set->MarkUsed(i->first);
152     }
153   }
154
155   return true;
156 }
157
158 bool Args::VerifyAllOverridesUsed(Err* err) const {
159   base::AutoLock lock(lock_);
160   return VerifyAllOverridesUsed(all_overrides_, declared_arguments_, err);
161 }
162
163 bool Args::VerifyAllOverridesUsed(
164     const Scope::KeyValueMap& overrides,
165     const Scope::KeyValueMap& declared_arguments,
166     Err* err) {
167   for (Scope::KeyValueMap::const_iterator i = overrides.begin();
168        i != overrides.end(); ++i) {
169     if (declared_arguments.find(i->first) == declared_arguments.end()) {
170       // Get a list of all possible overrides for help with error finding.
171       //
172       // It might be nice to do edit distance checks to see if we can find one
173       // close to what you typed.
174       std::string all_declared_str;
175       for (Scope::KeyValueMap::const_iterator cur_str =
176                declared_arguments.begin();
177            cur_str != declared_arguments.end(); ++cur_str) {
178         if (cur_str != declared_arguments.begin())
179           all_declared_str += ", ";
180         all_declared_str += cur_str->first.as_string();
181       }
182
183       *err = Err(i->second.origin(), "Build argument has no effect.",
184           "The variable \"" + i->first.as_string() + "\" was set as a build "
185           "argument\nbut never appeared in a declare_args() block in any "
186           "buildfile.\n\nPossible arguments: " + all_declared_str);
187       return false;
188     }
189   }
190   return true;
191 }
192
193 void Args::MergeDeclaredArguments(Scope::KeyValueMap* dest) const {
194   base::AutoLock lock(lock_);
195
196   for (Scope::KeyValueMap::const_iterator i = declared_arguments_.begin();
197        i != declared_arguments_.end(); ++i)
198     (*dest)[i->first] = i->second;
199 }
200
201 void Args::SetSystemVarsLocked(Scope* dest) const {
202   lock_.AssertAcquired();
203
204   // Host OS.
205   const char* os = NULL;
206 #if defined(OS_WIN)
207   os = "win";
208 #elif defined(OS_MACOSX)
209   os = "mac";
210 #elif defined(OS_LINUX)
211   os = "linux";
212 #else
213   #error Unknown OS type.
214 #endif
215   Value os_val(NULL, std::string(os));
216   dest->SetValue(variables::kBuildOs, os_val, NULL);
217   dest->SetValue(variables::kOs, os_val, NULL);
218
219   // Host architecture.
220   static const char kX86[] = "x86";
221   static const char kX64[] = "x64";
222   const char* arch = NULL;
223 #if defined(OS_WIN)
224   // ...on Windows, set the CPU architecture based on the underlying OS, not
225   // whatever the current bit-tedness of the GN binary is.
226   const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
227   switch (os_info->architecture()) {
228     case base::win::OSInfo::X86_ARCHITECTURE:
229       arch = kX86;
230       break;
231     case base::win::OSInfo::X64_ARCHITECTURE:
232       arch = kX64;
233       break;
234     default:
235       CHECK(false) << "Windows architecture not handled.";
236       break;
237   }
238 #else
239   // ...on all other platforms, just use the bit-tedness of the current
240   // process.
241   #if defined(ARCH_CPU_X86_64)
242     arch = kX64;
243   #elif defined(ARCH_CPU_X86)
244     arch = kX86;
245   #elif defined(ARCH_CPU_ARMEL)
246     static const char kArm[] = "arm";
247     arch = kArm;
248   #else
249     #error Unknown architecture.
250   #endif
251 #endif
252   // Avoid unused var warning.
253   (void)kX86;
254   (void)kX64;
255
256   Value arch_val(NULL, std::string(arch));
257   dest->SetValue(variables::kBuildCpuArch, arch_val, NULL);
258   dest->SetValue(variables::kCpuArch, arch_val, NULL);
259
260   // Save the OS and architecture as build arguments that are implicitly
261   // declared. This is so they can be overridden in a toolchain build args
262   // override, and so that they will appear in the "gn args" output.
263   //
264   // Do not declare the build* variants since these shouldn't be changed.
265   //
266   // Mark these variables used so the build config file can override them
267   // without geting a warning about overwriting an unused variable.
268   declared_arguments_[variables::kOs] = os_val;
269   declared_arguments_[variables::kCpuArch] = arch_val;
270   dest->MarkUsed(variables::kCpuArch);
271   dest->MarkUsed(variables::kOs);
272 }
273
274 void Args::ApplyOverridesLocked(const Scope::KeyValueMap& values,
275                                 Scope* scope) const {
276   lock_.AssertAcquired();
277   for (Scope::KeyValueMap::const_iterator i = values.begin();
278        i != values.end(); ++i)
279     scope->SetValue(i->first, i->second, i->second.origin());
280 }
281
282 void Args::SaveOverrideRecordLocked(const Scope::KeyValueMap& values) const {
283   lock_.AssertAcquired();
284   for (Scope::KeyValueMap::const_iterator i = values.begin();
285        i != values.end(); ++i)
286     all_overrides_[i->first] = i->second;
287 }