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"
11 #include "base/win/windows_version.h"
14 const char kBuildArgs_Help
[] =
15 "Build Arguments Overview\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"
20 "How build arguments are set\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"
27 " - os (by default this is the same as \"default_os\")\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"
33 " gn --args=\"enable_doom_melon=false\" os=\\\"beos\\\"\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"
41 " It is an error to specify an override for a build argument that never\n"
42 " appears in a \"declare_args\" call.\n"
44 "How build arguments are used\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"
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";
60 Args::Args(const Args
& other
)
61 : overrides_(other
.overrides_
),
62 all_overrides_(other
.all_overrides_
),
63 declared_arguments_(other
.declared_arguments_
) {
69 void Args::AddArgOverride(const char* name
, const Value
& value
) {
70 base::AutoLock
lock(lock_
);
72 overrides_
[base::StringPiece(name
)] = value
;
73 all_overrides_
[base::StringPiece(name
)] = value
;
76 void Args::AddArgOverrides(const Scope::KeyValueMap
& overrides
) {
77 base::AutoLock
lock(lock_
);
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
;
86 const Value
* Args::GetArgOverride(const char* name
) const {
87 base::AutoLock
lock(lock_
);
89 Scope::KeyValueMap::const_iterator found
=
90 all_overrides_
.find(base::StringPiece(name
));
91 if (found
== all_overrides_
.end())
93 return &found
->second
;
96 Scope::KeyValueMap
Args::GetAllOverrides() const {
97 base::AutoLock
lock(lock_
);
98 return all_overrides_
;
101 void Args::SetupRootScope(Scope
* dest
,
102 const Scope::KeyValueMap
& toolchain_overrides
) const {
103 base::AutoLock
lock(lock_
);
105 SetSystemVarsLocked(dest
);
106 ApplyOverridesLocked(overrides_
, dest
);
107 ApplyOverridesLocked(toolchain_overrides
, dest
);
108 SaveOverrideRecordLocked(toolchain_overrides
);
111 bool Args::DeclareArgs(const Scope::KeyValueMap
& args
,
114 base::AutoLock
lock(lock_
);
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.
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."));
143 declared_arguments_
.insert(*i
);
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
);
158 bool Args::VerifyAllOverridesUsed(Err
* err
) const {
159 base::AutoLock
lock(lock_
);
160 return VerifyAllOverridesUsed(all_overrides_
, declared_arguments_
, err
);
163 bool Args::VerifyAllOverridesUsed(
164 const Scope::KeyValueMap
& overrides
,
165 const Scope::KeyValueMap
& declared_arguments
,
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.
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();
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
);
193 void Args::MergeDeclaredArguments(Scope::KeyValueMap
* dest
) const {
194 base::AutoLock
lock(lock_
);
196 for (Scope::KeyValueMap::const_iterator i
= declared_arguments_
.begin();
197 i
!= declared_arguments_
.end(); ++i
)
198 (*dest
)[i
->first
] = i
->second
;
201 void Args::SetSystemVarsLocked(Scope
* dest
) const {
202 lock_
.AssertAcquired();
205 const char* os
= NULL
;
208 #elif defined(OS_MACOSX)
210 #elif defined(OS_LINUX)
213 #error Unknown OS type.
215 Value
os_val(NULL
, std::string(os
));
216 dest
->SetValue(variables::kBuildOs
, os_val
, NULL
);
217 dest
->SetValue(variables::kOs
, os_val
, NULL
);
219 // Host architecture.
220 static const char kX86
[] = "x86";
221 static const char kX64
[] = "x64";
222 const char* arch
= NULL
;
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
:
231 case base::win::OSInfo::X64_ARCHITECTURE
:
235 CHECK(false) << "Windows architecture not handled.";
239 // ...on all other platforms, just use the bit-tedness of the current
241 #if defined(ARCH_CPU_X86_64)
243 #elif defined(ARCH_CPU_X86)
245 #elif defined(ARCH_CPU_ARMEL)
246 static const char kArm
[] = "arm";
249 #error Unknown architecture.
252 // Avoid unused var warning.
256 Value
arch_val(NULL
, std::string(arch
));
257 dest
->SetValue(variables::kBuildCpuArch
, arch_val
, NULL
);
258 dest
->SetValue(variables::kCpuArch
, arch_val
, NULL
);
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.
264 // Do not declare the build* variants since these shouldn't be changed.
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
);
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());
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
;