blob: 9aaafb0854da7ca28ec08360eebb01e1ac858671 [file] [log] [blame]
[email protected]60749e1c2013-08-19 21:11:051// 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
thakis3dd547102014-12-17 20:05:027#include "base/sys_info.h"
[email protected]145e5a12013-10-18 21:57:138#include "build/build_config.h"
[email protected]60749e1c2013-08-19 21:11:059#include "tools/gn/variables.h"
10
11const char kBuildArgs_Help[] =
[email protected]ea3690c2013-09-23 17:59:2212 "Build Arguments Overview\n"
[email protected]60749e1c2013-08-19 21:11:0513 "\n"
14 " Build arguments are variables passed in from outside of the build\n"
15 " that build files can query to determine how the build works.\n"
16 "\n"
[email protected]ea3690c2013-09-23 17:59:2217 "How build arguments are set\n"
[email protected]60749e1c2013-08-19 21:11:0518 "\n"
19 " First, system default arguments are set based on the current system.\n"
20 " The built-in arguments are:\n"
dpranke74add9fc2015-02-19 20:21:0021 " - host_cpu\n"
22 " - host_os\n"
23 " - current_cpu\n"
24 " - current_os\n"
25 " - target_cpu\n"
26 " - target_os\n"
[email protected]60749e1c2013-08-19 21:11:0527 "\n"
[email protected]d5645f12014-05-03 04:32:1928 " If specified, arguments from the --args command line flag are used. If\n"
29 " that flag is not specified, args from previous builds in the build\n"
30 " directory will be used (this is in the file args.gn in the build\n"
31 " directory).\n"
[email protected]60749e1c2013-08-19 21:11:0532 "\n"
[email protected]d5645f12014-05-03 04:32:1933 " Last, for targets being compiled with a non-default toolchain, the\n"
34 " toolchain overrides are applied. These are specified in the\n"
[email protected]60749e1c2013-08-19 21:11:0535 " toolchain_args section of a toolchain definition. The use-case for\n"
36 " this is that a toolchain may be building code for a different\n"
37 " platform, and that it may want to always specify Posix, for example.\n"
brettw222278962016-08-05 19:04:3538 " See \"gn help toolchain\" for more.\n"
[email protected]60749e1c2013-08-19 21:11:0539 "\n"
[email protected]d5645f12014-05-03 04:32:1940 " If you specify an override for a build argument that never appears in\n"
41 " a \"declare_args\" call, a nonfatal error will be displayed.\n"
42 "\n"
43 "Examples\n"
44 "\n"
45 " gn args out/FooBar\n"
46 " Create the directory out/FooBar and open an editor. You would type\n"
47 " something like this into that file:\n"
48 " enable_doom_melon=false\n"
49 " os=\"android\"\n"
50 "\n"
51 " gn gen out/FooBar --args=\"enable_doom_melon=true os=\\\"android\\\"\"\n"
52 " This will overwrite the build directory with the given arguments.\n"
53 " (Note that the quotes inside the args command will usually need to\n"
54 " be escaped for your shell to pass through strings values.)\n"
[email protected]60749e1c2013-08-19 21:11:0555 "\n"
[email protected]ea3690c2013-09-23 17:59:2256 "How build arguments are used\n"
[email protected]60749e1c2013-08-19 21:11:0557 "\n"
58 " If you want to use an argument, you use declare_args() and specify\n"
59 " default values. These default values will apply if none of the steps\n"
60 " listed in the \"How build arguments are set\" section above apply to\n"
61 " the given argument, but the defaults will not override any of these.\n"
62 "\n"
63 " Often, the root build config file will declare global arguments that\n"
64 " will be passed to all buildfiles. Individual build files can also\n"
[email protected]b8aa81242014-01-05 11:59:5165 " specify arguments that apply only to those files. It is also useful\n"
[email protected]60749e1c2013-08-19 21:11:0566 " to specify build args in an \"import\"-ed file if you want such\n"
67 " arguments to apply to multiple buildfiles.\n";
68
skyca5cccef2015-03-16 18:06:0069namespace {
70
71// Removes all entries in |overrides| that are in |declared_overrides|.
72void RemoveDeclaredOverrides(const Scope::KeyValueMap& declared_arguments,
73 Scope::KeyValueMap* overrides) {
74 for (Scope::KeyValueMap::iterator override = overrides->begin();
75 override != overrides->end();) {
76 if (declared_arguments.find(override->first) == declared_arguments.end())
77 ++override;
78 else
79 overrides->erase(override++);
80 }
81}
82
83} // namespace
84
[email protected]60749e1c2013-08-19 21:11:0585Args::Args() {
86}
87
[email protected]e3730f812013-10-16 16:46:1488Args::Args(const Args& other)
89 : overrides_(other.overrides_),
90 all_overrides_(other.all_overrides_),
skyca5cccef2015-03-16 18:06:0091 declared_arguments_per_toolchain_(
tim5662a802016-07-12 00:07:4692 other.declared_arguments_per_toolchain_),
93 toolchain_overrides_(other.toolchain_overrides_) {
[email protected]e3730f812013-10-16 16:46:1494}
95
[email protected]60749e1c2013-08-19 21:11:0596Args::~Args() {
97}
98
[email protected]e3730f812013-10-16 16:46:1499void Args::AddArgOverride(const char* name, const Value& value) {
[email protected]0aa183b2014-02-06 08:23:40100 base::AutoLock lock(lock_);
101
[email protected]e3730f812013-10-16 16:46:14102 overrides_[base::StringPiece(name)] = value;
103 all_overrides_[base::StringPiece(name)] = value;
104}
105
[email protected]0a79fe42013-08-29 21:06:26106void Args::AddArgOverrides(const Scope::KeyValueMap& overrides) {
[email protected]0aa183b2014-02-06 08:23:40107 base::AutoLock lock(lock_);
108
brettwd1033b62014-09-30 21:44:05109 for (const auto& cur_override : overrides) {
110 overrides_[cur_override.first] = cur_override.second;
111 all_overrides_[cur_override.first] = cur_override.second;
[email protected]0a79fe42013-08-29 21:06:26112 }
[email protected]60749e1c2013-08-19 21:11:05113}
114
[email protected]8d039c62014-02-03 12:04:33115const Value* Args::GetArgOverride(const char* name) const {
[email protected]0aa183b2014-02-06 08:23:40116 base::AutoLock lock(lock_);
117
[email protected]8d039c62014-02-03 12:04:33118 Scope::KeyValueMap::const_iterator found =
119 all_overrides_.find(base::StringPiece(name));
120 if (found == all_overrides_.end())
tfarina9b636af2014-12-23 00:52:07121 return nullptr;
[email protected]8d039c62014-02-03 12:04:33122 return &found->second;
123}
124
[email protected]60fe5092014-02-13 18:03:43125Scope::KeyValueMap Args::GetAllOverrides() const {
126 base::AutoLock lock(lock_);
127 return all_overrides_;
128}
129
[email protected]60749e1c2013-08-19 21:11:05130void Args::SetupRootScope(Scope* dest,
131 const Scope::KeyValueMap& toolchain_overrides) const {
[email protected]0aa183b2014-02-06 08:23:40132 base::AutoLock lock(lock_);
133
134 SetSystemVarsLocked(dest);
tim5662a802016-07-12 00:07:46135
136 // Apply overrides for already declared args.
137 // (i.e. the system vars we set above)
[email protected]0aa183b2014-02-06 08:23:40138 ApplyOverridesLocked(overrides_, dest);
139 ApplyOverridesLocked(toolchain_overrides, dest);
tim5662a802016-07-12 00:07:46140
141 OverridesForToolchainLocked(dest) = toolchain_overrides;
142
[email protected]0aa183b2014-02-06 08:23:40143 SaveOverrideRecordLocked(toolchain_overrides);
[email protected]60749e1c2013-08-19 21:11:05144}
145
146bool Args::DeclareArgs(const Scope::KeyValueMap& args,
147 Scope* scope_to_set,
148 Err* err) const {
149 base::AutoLock lock(lock_);
150
skyca5cccef2015-03-16 18:06:00151 Scope::KeyValueMap& declared_arguments(
152 DeclaredArgumentsForToolchainLocked(scope_to_set));
tim5662a802016-07-12 00:07:46153
154 const Scope::KeyValueMap& toolchain_overrides(
155 OverridesForToolchainLocked(scope_to_set));
156
brettwd1033b62014-09-30 21:44:05157 for (const auto& arg : args) {
[email protected]60749e1c2013-08-19 21:11:05158 // Verify that the value hasn't already been declared. We want each value
159 // to be declared only once.
160 //
161 // The tricky part is that a buildfile can be interpreted multiple times
162 // when used from different toolchains, so we can't just check that we've
[email protected]55a3dd762014-02-18 20:24:40163 // seen it before. Instead, we check that the location matches.
[email protected]60749e1c2013-08-19 21:11:05164 Scope::KeyValueMap::iterator previously_declared =
skyca5cccef2015-03-16 18:06:00165 declared_arguments.find(arg.first);
166 if (previously_declared != declared_arguments.end()) {
brettwd1033b62014-09-30 21:44:05167 if (previously_declared->second.origin() != arg.second.origin()) {
[email protected]60749e1c2013-08-19 21:11:05168 // Declaration location mismatch.
brettwd1033b62014-09-30 21:44:05169 *err = Err(arg.second.origin(),
170 "Duplicate build argument declaration.",
[email protected]60749e1c2013-08-19 21:11:05171 "Here you're declaring an argument that was already declared "
172 "elsewhere.\nYou can only declare each argument once in the entire "
173 "build so there is one\ncanonical place for documentation and the "
174 "default value. Either move this\nargument to the build config "
175 "file (for visibility everywhere) or to a .gni file\nthat you "
176 "\"import\" from the files where you need it (preferred).");
177 err->AppendSubErr(Err(previously_declared->second.origin(),
178 "Previous declaration.",
179 "See also \"gn help buildargs\" for more on how "
[email protected]b8aa81242014-01-05 11:59:51180 "build arguments work."));
[email protected]60749e1c2013-08-19 21:11:05181 return false;
[email protected]60749e1c2013-08-19 21:11:05182 }
183 } else {
skyca5cccef2015-03-16 18:06:00184 declared_arguments.insert(arg);
[email protected]60749e1c2013-08-19 21:11:05185 }
186
brettw8b05f572016-07-13 21:29:23187 // In all the cases below, mark the variable used. If a variable is set
188 // that's only used in one toolchain, we don't want to report unused
189 // variable errors in other toolchains. Also, in some cases it's reasonable
190 // for the build file to overwrite the value with a different value based
191 // on some other condition without dereferencing the value first.
192
tim5662a802016-07-12 00:07:46193 // Check whether this argument has been overridden on the toolchain level
194 // and use the override instead.
195 Scope::KeyValueMap::const_iterator toolchain_override =
196 toolchain_overrides.find(arg.first);
197 if (toolchain_override != toolchain_overrides.end()) {
198 scope_to_set->SetValue(toolchain_override->first,
199 toolchain_override->second,
200 toolchain_override->second.origin());
brettw8b05f572016-07-13 21:29:23201 scope_to_set->MarkUsed(arg.first);
tim5662a802016-07-12 00:07:46202 continue;
[email protected]42b80ef2013-10-29 23:43:57203 }
tim5662a802016-07-12 00:07:46204
205 // Check whether this argument has been overridden and use the override
206 // instead.
207 Scope::KeyValueMap::const_iterator override = overrides_.find(arg.first);
208 if (override != overrides_.end()) {
209 scope_to_set->SetValue(override->first, override->second,
210 override->second.origin());
brettw8b05f572016-07-13 21:29:23211 scope_to_set->MarkUsed(override->first);
tim5662a802016-07-12 00:07:46212 continue;
213 }
214
tim5662a802016-07-12 00:07:46215 scope_to_set->SetValue(arg.first, arg.second, arg.second.origin());
216 scope_to_set->MarkUsed(arg.first);
[email protected]60749e1c2013-08-19 21:11:05217 }
218
219 return true;
220}
221
222bool Args::VerifyAllOverridesUsed(Err* err) const {
223 base::AutoLock lock(lock_);
skyca5cccef2015-03-16 18:06:00224 Scope::KeyValueMap all_overrides(all_overrides_);
225 for (const auto& map_pair : declared_arguments_per_toolchain_)
226 RemoveDeclaredOverrides(map_pair.second, &all_overrides);
[email protected]60749e1c2013-08-19 21:11:05227
skyca5cccef2015-03-16 18:06:00228 if (all_overrides.empty())
229 return true;
[email protected]0aa183b2014-02-06 08:23:40230
skyca5cccef2015-03-16 18:06:00231 *err = Err(
232 all_overrides.begin()->second.origin(), "Build argument has no effect.",
233 "The variable \"" + all_overrides.begin()->first.as_string() +
234 "\" was set as a build argument\nbut never appeared in a " +
brettw12985c02016-04-24 19:03:22235 "declare_args() block in any buildfile.\n\n"
236 "To view possible args, run \"gn args --list <builddir>\"");
skyca5cccef2015-03-16 18:06:00237 return false;
[email protected]60749e1c2013-08-19 21:11:05238}
239
[email protected]60fe5092014-02-13 18:03:43240void Args::MergeDeclaredArguments(Scope::KeyValueMap* dest) const {
241 base::AutoLock lock(lock_);
skyca5cccef2015-03-16 18:06:00242 for (const auto& map_pair : declared_arguments_per_toolchain_) {
243 for (const auto& arg : map_pair.second)
244 (*dest)[arg.first] = arg.second;
245 }
[email protected]60fe5092014-02-13 18:03:43246}
247
[email protected]0aa183b2014-02-06 08:23:40248void Args::SetSystemVarsLocked(Scope* dest) const {
[email protected]60fe5092014-02-13 18:03:43249 lock_.AssertAcquired();
250
[email protected]145e5a12013-10-18 21:57:13251 // Host OS.
tfarina9b636af2014-12-23 00:52:07252 const char* os = nullptr;
[email protected]60749e1c2013-08-19 21:11:05253#if defined(OS_WIN)
[email protected]145e5a12013-10-18 21:57:13254 os = "win";
255#elif defined(OS_MACOSX)
256 os = "mac";
257#elif defined(OS_LINUX)
258 os = "linux";
[email protected]a74ddbc2014-05-13 17:41:06259#elif defined(OS_ANDROID)
260 os = "android";
krytarowskif0c034ea2016-08-02 20:04:17261#elif defined(OS_NETBSD)
262 os = "netbsd";
[email protected]60749e1c2013-08-19 21:11:05263#else
[email protected]145e5a12013-10-18 21:57:13264 #error Unknown OS type.
[email protected]60749e1c2013-08-19 21:11:05265#endif
[email protected]60749e1c2013-08-19 21:11:05266
[email protected]145e5a12013-10-18 21:57:13267 // Host architecture.
[email protected]777ad7f2013-11-22 22:38:39268 static const char kX86[] = "x86";
269 static const char kX64[] = "x64";
thakis3dd547102014-12-17 20:05:02270 static const char kArm[] = "arm";
milko.leporis8ea3910c72016-04-18 07:51:18271 static const char kMips[] = "mipsel";
tfarina9b636af2014-12-23 00:52:07272 const char* arch = nullptr;
thakis3dd547102014-12-17 20:05:02273
dpranke74add9fc2015-02-19 20:21:00274 // Set the host CPU architecture based on the underlying OS, not
[email protected]145e5a12013-10-18 21:57:13275 // whatever the current bit-tedness of the GN binary is.
thakis3dd547102014-12-17 20:05:02276 std::string os_arch = base::SysInfo::OperatingSystemArchitecture();
277 if (os_arch == "x86")
[email protected]777ad7f2013-11-22 22:38:39278 arch = kX86;
thakis3dd547102014-12-17 20:05:02279 else if (os_arch == "x86_64")
280 arch = kX64;
saiarcot895b68180a2016-04-28 22:25:01281 else if (os_arch.substr(0, 3) == "arm")
[email protected]145e5a12013-10-18 21:57:13282 arch = kArm;
milko.leporis8ea3910c72016-04-18 07:51:18283 else if (os_arch == "mips")
284 arch = kMips;
thakis3dd547102014-12-17 20:05:02285 else
286 CHECK(false) << "OS architecture not handled.";
[email protected]60749e1c2013-08-19 21:11:05287
[email protected]dbd915b42013-10-25 22:23:17288 // Save the OS and architecture as build arguments that are implicitly
289 // declared. This is so they can be overridden in a toolchain build args
290 // override, and so that they will appear in the "gn args" output.
dpranke74add9fc2015-02-19 20:21:00291 Value empty_string(nullptr, std::string());
292
293 Value os_val(nullptr, std::string(os));
294 dest->SetValue(variables::kHostOs, os_val, nullptr);
295 dest->SetValue(variables::kTargetOs, empty_string, nullptr);
296 dest->SetValue(variables::kCurrentOs, empty_string, nullptr);
297
298 Value arch_val(nullptr, std::string(arch));
299 dest->SetValue(variables::kHostCpu, arch_val, nullptr);
300 dest->SetValue(variables::kTargetCpu, empty_string, nullptr);
301 dest->SetValue(variables::kCurrentCpu, empty_string, nullptr);
302
skyca5cccef2015-03-16 18:06:00303 Scope::KeyValueMap& declared_arguments(
304 DeclaredArgumentsForToolchainLocked(dest));
305 declared_arguments[variables::kHostOs] = os_val;
306 declared_arguments[variables::kCurrentOs] = empty_string;
307 declared_arguments[variables::kTargetOs] = empty_string;
308 declared_arguments[variables::kHostCpu] = arch_val;
309 declared_arguments[variables::kCurrentCpu] = empty_string;
310 declared_arguments[variables::kTargetCpu] = empty_string;
dpranke74add9fc2015-02-19 20:21:00311
[email protected]145e5a12013-10-18 21:57:13312 // Mark these variables used so the build config file can override them
313 // without geting a warning about overwriting an unused variable.
dpranke74add9fc2015-02-19 20:21:00314 dest->MarkUsed(variables::kHostCpu);
315 dest->MarkUsed(variables::kCurrentCpu);
316 dest->MarkUsed(variables::kTargetCpu);
317 dest->MarkUsed(variables::kHostOs);
318 dest->MarkUsed(variables::kCurrentOs);
319 dest->MarkUsed(variables::kTargetOs);
[email protected]60749e1c2013-08-19 21:11:05320}
321
[email protected]0aa183b2014-02-06 08:23:40322void Args::ApplyOverridesLocked(const Scope::KeyValueMap& values,
323 Scope* scope) const {
[email protected]60fe5092014-02-13 18:03:43324 lock_.AssertAcquired();
tim5662a802016-07-12 00:07:46325
326 const Scope::KeyValueMap& declared_arguments(
327 DeclaredArgumentsForToolchainLocked(scope));
328
329 // Only set a value if it has been declared.
330 for (const auto& val : values) {
331 Scope::KeyValueMap::const_iterator declared =
332 declared_arguments.find(val.first);
333
334 if (declared == declared_arguments.end())
335 continue;
336
brettwd1033b62014-09-30 21:44:05337 scope->SetValue(val.first, val.second, val.second.origin());
tim5662a802016-07-12 00:07:46338 }
[email protected]60749e1c2013-08-19 21:11:05339}
340
[email protected]0aa183b2014-02-06 08:23:40341void Args::SaveOverrideRecordLocked(const Scope::KeyValueMap& values) const {
[email protected]60fe5092014-02-13 18:03:43342 lock_.AssertAcquired();
brettwd1033b62014-09-30 21:44:05343 for (const auto& val : values)
344 all_overrides_[val.first] = val.second;
[email protected]60749e1c2013-08-19 21:11:05345}
skyca5cccef2015-03-16 18:06:00346
347Scope::KeyValueMap& Args::DeclaredArgumentsForToolchainLocked(
348 Scope* scope) const {
349 lock_.AssertAcquired();
350 return declared_arguments_per_toolchain_[scope->settings()];
351}
tim5662a802016-07-12 00:07:46352
353Scope::KeyValueMap& Args::OverridesForToolchainLocked(
354 Scope* scope) const {
355 lock_.AssertAcquired();
356 return toolchain_overrides_[scope->settings()];
357}