blob: 04ced9f6f7331453f326f9d4a54dd51eb038905f [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
[email protected]145e5a12013-10-18 21:57:137#include "build/build_config.h"
[email protected]60749e1c2013-08-19 21:11:058#include "tools/gn/variables.h"
9
[email protected]145e5a12013-10-18 21:57:1310#if defined(OS_WIN)
11#include "base/win/windows_version.h"
12#endif
13
[email protected]60749e1c2013-08-19 21:11:0514const char kBuildArgs_Help[] =
[email protected]ea3690c2013-09-23 17:59:2215 "Build Arguments Overview\n"
[email protected]60749e1c2013-08-19 21:11:0516 "\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"
[email protected]ea3690c2013-09-23 17:59:2220 "How build arguments are set\n"
[email protected]60749e1c2013-08-19 21:11:0521 "\n"
22 " First, system default arguments are set based on the current system.\n"
23 " The built-in arguments are:\n"
[email protected]145e5a12013-10-18 21:57:1324 " - 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"
[email protected]60749e1c2013-08-19 21:11:0528 "\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"
[email protected]145e5a12013-10-18 21:57:1333 " gn --args=\"enable_doom_melon=false\" os=\\\"beos\\\"\n"
[email protected]60749e1c2013-08-19 21:11:0534 "\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"
[email protected]ea3690c2013-09-23 17:59:2244 "How build arguments are used\n"
[email protected]60749e1c2013-08-19 21:11:0545 "\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
57Args::Args() {
58}
59
[email protected]e3730f812013-10-16 16:46:1460Args::Args(const Args& other)
61 : overrides_(other.overrides_),
62 all_overrides_(other.all_overrides_),
63 declared_arguments_(other.declared_arguments_) {
64}
65
[email protected]60749e1c2013-08-19 21:11:0566Args::~Args() {
67}
68
[email protected]e3730f812013-10-16 16:46:1469void Args::AddArgOverride(const char* name, const Value& value) {
70 overrides_[base::StringPiece(name)] = value;
71 all_overrides_[base::StringPiece(name)] = value;
72}
73
[email protected]0a79fe42013-08-29 21:06:2674void Args::AddArgOverrides(const Scope::KeyValueMap& overrides) {
75 for (Scope::KeyValueMap::const_iterator i = overrides.begin();
76 i != overrides.end(); ++i) {
[email protected]e3730f812013-10-16 16:46:1477 overrides_[i->first] = i->second;
78 all_overrides_[i->first] = i->second;
[email protected]0a79fe42013-08-29 21:06:2679 }
[email protected]60749e1c2013-08-19 21:11:0580}
81
82void 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
90bool 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
[email protected]42b80ef2013-10-29 23:43:57138 // 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)) {
[email protected]60749e1c2013-08-19 21:11:05141 scope_to_set->SetValue(i->first, i->second, i->second.origin());
[email protected]42b80ef2013-10-29 23:43:57142 scope_to_set->MarkUsed(i->first);
143 }
[email protected]60749e1c2013-08-19 21:11:05144 }
145
146 return true;
147}
148
149bool 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
165void Args::SetSystemVars(Scope* dest) const {
[email protected]145e5a12013-10-18 21:57:13166 // Host OS.
167 const char* os = NULL;
[email protected]60749e1c2013-08-19 21:11:05168#if defined(OS_WIN)
[email protected]145e5a12013-10-18 21:57:13169 os = "win";
170#elif defined(OS_MACOSX)
171 os = "mac";
172#elif defined(OS_LINUX)
173 os = "linux";
[email protected]60749e1c2013-08-19 21:11:05174#else
[email protected]145e5a12013-10-18 21:57:13175 #error Unknown OS type.
[email protected]60749e1c2013-08-19 21:11:05176#endif
[email protected]145e5a12013-10-18 21:57:13177 Value os_val(NULL, std::string(os));
178 dest->SetValue(variables::kBuildOs, os_val, NULL);
179 dest->SetValue(variables::kOs, os_val, NULL);
[email protected]60749e1c2013-08-19 21:11:05180
[email protected]145e5a12013-10-18 21:57:13181 // Host architecture.
[email protected]777ad7f2013-11-22 22:38:39182 static const char kX86[] = "x86";
183 static const char kX64[] = "x64";
[email protected]145e5a12013-10-18 21:57:13184 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:
[email protected]777ad7f2013-11-22 22:38:39191 arch = kX86;
[email protected]145e5a12013-10-18 21:57:13192 break;
193 case base::win::OSInfo::X64_ARCHITECTURE:
[email protected]777ad7f2013-11-22 22:38:39194 arch = kX64;
[email protected]145e5a12013-10-18 21:57:13195 break;
196 default:
197 CHECK(false) << "Windows architecture not handled.";
198 break;
199 }
[email protected]60749e1c2013-08-19 21:11:05200#else
[email protected]145e5a12013-10-18 21:57:13201 // ...on all other platforms, just use the bit-tedness of the current
202 // process.
203 #if defined(ARCH_CPU_X86_64)
[email protected]777ad7f2013-11-22 22:38:39204 arch = kX64;
[email protected]145e5a12013-10-18 21:57:13205 #elif defined(ARCH_CPU_X86)
[email protected]777ad7f2013-11-22 22:38:39206 arch = kX86;
[email protected]145e5a12013-10-18 21:57:13207 #elif defined(ARCH_CPU_ARMEL)
208 static const char kArm[] = "arm";
209 arch = kArm;
210 #else
211 #error Unknown architecture.
212 #endif
[email protected]60749e1c2013-08-19 21:11:05213#endif
[email protected]145e5a12013-10-18 21:57:13214 // Avoid unused var warning.
[email protected]777ad7f2013-11-22 22:38:39215 (void)kX86;
216 (void)kX64;
[email protected]60749e1c2013-08-19 21:11:05217
[email protected]145e5a12013-10-18 21:57:13218 Value arch_val(NULL, std::string(arch));
219 dest->SetValue(variables::kBuildCpuArch, arch_val, NULL);
220 dest->SetValue(variables::kCpuArch, arch_val, NULL);
[email protected]145e5a12013-10-18 21:57:13221
[email protected]dbd915b42013-10-25 22:23:17222 // 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 //
[email protected]145e5a12013-10-18 21:57:13228 // Mark these variables used so the build config file can override them
229 // without geting a warning about overwriting an unused variable.
[email protected]dbd915b42013-10-25 22:23:17230 declared_arguments_[variables::kOs] = os_val;
231 declared_arguments_[variables::kCpuArch] = arch_val;
[email protected]145e5a12013-10-18 21:57:13232 dest->MarkUsed(variables::kCpuArch);
233 dest->MarkUsed(variables::kOs);
[email protected]60749e1c2013-08-19 21:11:05234}
235
[email protected]145e5a12013-10-18 21:57:13236
[email protected]60749e1c2013-08-19 21:11:05237void 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
244void 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}