Change next_proto member type.
[chromium-blink-merge.git] / tools / gn / args.cc
blobbce1ad2c6d9e789868b8f47c97495492b68afab2
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.
5 #include "tools/gn/args.h"
7 #include "build/build_config.h"
8 #include "tools/gn/variables.h"
10 #if defined(OS_WIN)
11 #include "base/win/windows_version.h"
12 #endif
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 " If specified, arguments from the --args command line flag are used. If\n"
30 " that flag is not specified, args from previous builds in the build\n"
31 " directory will be used (this is in the file args.gn in the build\n"
32 " directory).\n"
33 "\n"
34 " Last, for targets being compiled with a non-default toolchain, the\n"
35 " 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 " If you specify an override for a build argument that never appears in\n"
42 " a \"declare_args\" call, a nonfatal error will be displayed.\n"
43 "\n"
44 "Examples\n"
45 "\n"
46 " gn args out/FooBar\n"
47 " Create the directory out/FooBar and open an editor. You would type\n"
48 " something like this into that file:\n"
49 " enable_doom_melon=false\n"
50 " os=\"android\"\n"
51 "\n"
52 " gn gen out/FooBar --args=\"enable_doom_melon=true os=\\\"android\\\"\"\n"
53 " This will overwrite the build directory with the given arguments.\n"
54 " (Note that the quotes inside the args command will usually need to\n"
55 " be escaped for your shell to pass through strings values.)\n"
56 "\n"
57 "How build arguments are used\n"
58 "\n"
59 " If you want to use an argument, you use declare_args() and specify\n"
60 " default values. These default values will apply if none of the steps\n"
61 " listed in the \"How build arguments are set\" section above apply to\n"
62 " the given argument, but the defaults will not override any of these.\n"
63 "\n"
64 " Often, the root build config file will declare global arguments that\n"
65 " will be passed to all buildfiles. Individual build files can also\n"
66 " specify arguments that apply only to those files. It is also useful\n"
67 " to specify build args in an \"import\"-ed file if you want such\n"
68 " arguments to apply to multiple buildfiles.\n";
70 Args::Args() {
73 Args::Args(const Args& other)
74 : overrides_(other.overrides_),
75 all_overrides_(other.all_overrides_),
76 declared_arguments_(other.declared_arguments_) {
79 Args::~Args() {
82 void Args::AddArgOverride(const char* name, const Value& value) {
83 base::AutoLock lock(lock_);
85 overrides_[base::StringPiece(name)] = value;
86 all_overrides_[base::StringPiece(name)] = value;
89 void Args::AddArgOverrides(const Scope::KeyValueMap& overrides) {
90 base::AutoLock lock(lock_);
92 for (const auto& cur_override : overrides) {
93 overrides_[cur_override.first] = cur_override.second;
94 all_overrides_[cur_override.first] = cur_override.second;
98 const Value* Args::GetArgOverride(const char* name) const {
99 base::AutoLock lock(lock_);
101 Scope::KeyValueMap::const_iterator found =
102 all_overrides_.find(base::StringPiece(name));
103 if (found == all_overrides_.end())
104 return NULL;
105 return &found->second;
108 Scope::KeyValueMap Args::GetAllOverrides() const {
109 base::AutoLock lock(lock_);
110 return all_overrides_;
113 void Args::SetupRootScope(Scope* dest,
114 const Scope::KeyValueMap& toolchain_overrides) const {
115 base::AutoLock lock(lock_);
117 SetSystemVarsLocked(dest);
118 ApplyOverridesLocked(overrides_, dest);
119 ApplyOverridesLocked(toolchain_overrides, dest);
120 SaveOverrideRecordLocked(toolchain_overrides);
123 bool Args::DeclareArgs(const Scope::KeyValueMap& args,
124 Scope* scope_to_set,
125 Err* err) const {
126 base::AutoLock lock(lock_);
128 for (const auto& arg : args) {
129 // Verify that the value hasn't already been declared. We want each value
130 // to be declared only once.
132 // The tricky part is that a buildfile can be interpreted multiple times
133 // when used from different toolchains, so we can't just check that we've
134 // seen it before. Instead, we check that the location matches.
135 Scope::KeyValueMap::iterator previously_declared =
136 declared_arguments_.find(arg.first);
137 if (previously_declared != declared_arguments_.end()) {
138 if (previously_declared->second.origin() != arg.second.origin()) {
139 // Declaration location mismatch.
140 *err = Err(arg.second.origin(),
141 "Duplicate build argument declaration.",
142 "Here you're declaring an argument that was already declared "
143 "elsewhere.\nYou can only declare each argument once in the entire "
144 "build so there is one\ncanonical place for documentation and the "
145 "default value. Either move this\nargument to the build config "
146 "file (for visibility everywhere) or to a .gni file\nthat you "
147 "\"import\" from the files where you need it (preferred).");
148 err->AppendSubErr(Err(previously_declared->second.origin(),
149 "Previous declaration.",
150 "See also \"gn help buildargs\" for more on how "
151 "build arguments work."));
152 return false;
154 } else {
155 declared_arguments_.insert(arg);
158 // Only set on the current scope to the new value if it hasn't been already
159 // set. Mark the variable used so the build script can override it in
160 // certain cases without getting unused value errors.
161 if (!scope_to_set->GetValue(arg.first)) {
162 scope_to_set->SetValue(arg.first, arg.second, arg.second.origin());
163 scope_to_set->MarkUsed(arg.first);
167 return true;
170 bool Args::VerifyAllOverridesUsed(Err* err) const {
171 base::AutoLock lock(lock_);
172 return VerifyAllOverridesUsed(all_overrides_, declared_arguments_, err);
175 bool Args::VerifyAllOverridesUsed(
176 const Scope::KeyValueMap& overrides,
177 const Scope::KeyValueMap& declared_arguments,
178 Err* err) {
179 for (const auto& override : overrides) {
180 if (declared_arguments.find(override.first) == declared_arguments.end()) {
181 // Get a list of all possible overrides for help with error finding.
183 // It might be nice to do edit distance checks to see if we can find one
184 // close to what you typed.
185 std::string all_declared_str;
186 for (Scope::KeyValueMap::const_iterator cur_str =
187 declared_arguments.begin();
188 cur_str != declared_arguments.end(); ++cur_str) {
189 if (cur_str != declared_arguments.begin())
190 all_declared_str += ", ";
191 all_declared_str += cur_str->first.as_string();
194 *err = Err(override.second.origin(), "Build argument has no effect.",
195 "The variable \"" + override.first.as_string() +
196 "\" was set as a build "
197 "argument\nbut never appeared in a declare_args() block in any "
198 "buildfile.\n\nPossible arguments: " + all_declared_str);
199 return false;
202 return true;
205 void Args::MergeDeclaredArguments(Scope::KeyValueMap* dest) const {
206 base::AutoLock lock(lock_);
207 for (const auto& arg : declared_arguments_)
208 (*dest)[arg.first] = arg.second;
211 void Args::SetSystemVarsLocked(Scope* dest) const {
212 lock_.AssertAcquired();
214 // Host OS.
215 const char* os = NULL;
216 #if defined(OS_WIN)
217 os = "win";
218 #elif defined(OS_MACOSX)
219 os = "mac";
220 #elif defined(OS_LINUX)
221 os = "linux";
222 #elif defined(OS_ANDROID)
223 os = "android";
224 #else
225 #error Unknown OS type.
226 #endif
227 Value os_val(NULL, std::string(os));
228 dest->SetValue(variables::kBuildOs, os_val, NULL);
229 dest->SetValue(variables::kOs, os_val, NULL);
231 // Host architecture.
232 static const char kX86[] = "x86";
233 static const char kX64[] = "x64";
234 const char* arch = NULL;
235 #if defined(OS_WIN)
236 // ...on Windows, set the CPU architecture based on the underlying OS, not
237 // whatever the current bit-tedness of the GN binary is.
238 const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
239 switch (os_info->architecture()) {
240 case base::win::OSInfo::X86_ARCHITECTURE:
241 arch = kX86;
242 break;
243 case base::win::OSInfo::X64_ARCHITECTURE:
244 arch = kX64;
245 break;
246 default:
247 CHECK(false) << "Windows architecture not handled.";
248 break;
250 #else
251 // ...on all other platforms, just use the bit-tedness of the current
252 // process.
253 #if defined(ARCH_CPU_X86_64)
254 arch = kX64;
255 #elif defined(ARCH_CPU_X86)
256 arch = kX86;
257 #elif defined(ARCH_CPU_ARMEL)
258 static const char kArm[] = "arm";
259 arch = kArm;
260 #else
261 #error Unknown architecture.
262 #endif
263 #endif
264 // Avoid unused var warning.
265 (void)kX86;
266 (void)kX64;
268 Value arch_val(NULL, std::string(arch));
269 dest->SetValue(variables::kBuildCpuArch, arch_val, NULL);
270 dest->SetValue(variables::kCpuArch, arch_val, NULL);
272 // Save the OS and architecture as build arguments that are implicitly
273 // declared. This is so they can be overridden in a toolchain build args
274 // override, and so that they will appear in the "gn args" output.
276 // Do not declare the build* variants since these shouldn't be changed.
278 // Mark these variables used so the build config file can override them
279 // without geting a warning about overwriting an unused variable.
280 declared_arguments_[variables::kOs] = os_val;
281 declared_arguments_[variables::kCpuArch] = arch_val;
282 dest->MarkUsed(variables::kCpuArch);
283 dest->MarkUsed(variables::kOs);
286 void Args::ApplyOverridesLocked(const Scope::KeyValueMap& values,
287 Scope* scope) const {
288 lock_.AssertAcquired();
289 for (const auto& val : values)
290 scope->SetValue(val.first, val.second, val.second.origin());
293 void Args::SaveOverrideRecordLocked(const Scope::KeyValueMap& values) const {
294 lock_.AssertAcquired();
295 for (const auto& val : values)
296 all_overrides_[val.first] = val.second;