OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/gn/args.h" | 5 #include "tools/gn/args.h" |
6 | 6 |
7 #include "base/sys_info.h" | 7 #include "base/sys_info.h" |
8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
9 #include "tools/gn/variables.h" | 9 #include "tools/gn/variables.h" |
10 | 10 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
59 " default values. These default values will apply if none of the steps\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" | 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" | 61 " the given argument, but the defaults will not override any of these.\n" |
62 "\n" | 62 "\n" |
63 " Often, the root build config file will declare global arguments that\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" | 64 " will be passed to all buildfiles. Individual build files can also\n" |
65 " specify arguments that apply only to those files. It is also useful\n" | 65 " specify arguments that apply only to those files. It is also useful\n" |
66 " to specify build args in an \"import\"-ed file if you want such\n" | 66 " to specify build args in an \"import\"-ed file if you want such\n" |
67 " arguments to apply to multiple buildfiles.\n"; | 67 " arguments to apply to multiple buildfiles.\n"; |
68 | 68 |
69 namespace { | |
70 | |
71 // Removes all entries in |overrides| that are in |declared_overrides|. | |
72 void 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 | |
69 Args::Args() { | 85 Args::Args() { |
70 } | 86 } |
71 | 87 |
72 Args::Args(const Args& other) | 88 Args::Args(const Args& other) |
73 : overrides_(other.overrides_), | 89 : overrides_(other.overrides_), |
74 all_overrides_(other.all_overrides_), | 90 all_overrides_(other.all_overrides_), |
75 declared_arguments_(other.declared_arguments_) { | 91 declared_arguments_per_toolchain_( |
92 other.declared_arguments_per_toolchain_) { | |
76 } | 93 } |
77 | 94 |
78 Args::~Args() { | 95 Args::~Args() { |
79 } | 96 } |
80 | 97 |
81 void Args::AddArgOverride(const char* name, const Value& value) { | 98 void Args::AddArgOverride(const char* name, const Value& value) { |
82 base::AutoLock lock(lock_); | 99 base::AutoLock lock(lock_); |
83 | 100 |
84 overrides_[base::StringPiece(name)] = value; | 101 overrides_[base::StringPiece(name)] = value; |
85 all_overrides_[base::StringPiece(name)] = value; | 102 all_overrides_[base::StringPiece(name)] = value; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 ApplyOverridesLocked(overrides_, dest); | 134 ApplyOverridesLocked(overrides_, dest); |
118 ApplyOverridesLocked(toolchain_overrides, dest); | 135 ApplyOverridesLocked(toolchain_overrides, dest); |
119 SaveOverrideRecordLocked(toolchain_overrides); | 136 SaveOverrideRecordLocked(toolchain_overrides); |
120 } | 137 } |
121 | 138 |
122 bool Args::DeclareArgs(const Scope::KeyValueMap& args, | 139 bool Args::DeclareArgs(const Scope::KeyValueMap& args, |
123 Scope* scope_to_set, | 140 Scope* scope_to_set, |
124 Err* err) const { | 141 Err* err) const { |
125 base::AutoLock lock(lock_); | 142 base::AutoLock lock(lock_); |
126 | 143 |
144 Scope::KeyValueMap& declared_arguments( | |
145 DeclaredArgumentsForToolchainLocked(scope_to_set)); | |
127 for (const auto& arg : args) { | 146 for (const auto& arg : args) { |
128 // Verify that the value hasn't already been declared. We want each value | 147 // Verify that the value hasn't already been declared. We want each value |
129 // to be declared only once. | 148 // to be declared only once. |
130 // | 149 // |
131 // The tricky part is that a buildfile can be interpreted multiple times | 150 // The tricky part is that a buildfile can be interpreted multiple times |
132 // when used from different toolchains, so we can't just check that we've | 151 // when used from different toolchains, so we can't just check that we've |
133 // seen it before. Instead, we check that the location matches. | 152 // seen it before. Instead, we check that the location matches. |
134 Scope::KeyValueMap::iterator previously_declared = | 153 Scope::KeyValueMap::iterator previously_declared = |
135 declared_arguments_.find(arg.first); | 154 declared_arguments.find(arg.first); |
136 if (previously_declared != declared_arguments_.end()) { | 155 if (previously_declared != declared_arguments.end()) { |
137 if (previously_declared->second.origin() != arg.second.origin()) { | 156 if (previously_declared->second.origin() != arg.second.origin()) { |
138 // Declaration location mismatch. | 157 // Declaration location mismatch. |
139 *err = Err(arg.second.origin(), | 158 *err = Err(arg.second.origin(), |
140 "Duplicate build argument declaration.", | 159 "Duplicate build argument declaration.", |
141 "Here you're declaring an argument that was already declared " | 160 "Here you're declaring an argument that was already declared " |
142 "elsewhere.\nYou can only declare each argument once in the entire " | 161 "elsewhere.\nYou can only declare each argument once in the entire " |
143 "build so there is one\ncanonical place for documentation and the " | 162 "build so there is one\ncanonical place for documentation and the " |
144 "default value. Either move this\nargument to the build config " | 163 "default value. Either move this\nargument to the build config " |
145 "file (for visibility everywhere) or to a .gni file\nthat you " | 164 "file (for visibility everywhere) or to a .gni file\nthat you " |
146 "\"import\" from the files where you need it (preferred)."); | 165 "\"import\" from the files where you need it (preferred)."); |
147 err->AppendSubErr(Err(previously_declared->second.origin(), | 166 err->AppendSubErr(Err(previously_declared->second.origin(), |
148 "Previous declaration.", | 167 "Previous declaration.", |
149 "See also \"gn help buildargs\" for more on how " | 168 "See also \"gn help buildargs\" for more on how " |
150 "build arguments work.")); | 169 "build arguments work.")); |
151 return false; | 170 return false; |
152 } | 171 } |
153 } else { | 172 } else { |
154 declared_arguments_.insert(arg); | 173 declared_arguments.insert(arg); |
155 } | 174 } |
156 | 175 |
157 // Only set on the current scope to the new value if it hasn't been already | 176 // Only set on the current scope to the new value if it hasn't been already |
158 // set. Mark the variable used so the build script can override it in | 177 // set. Mark the variable used so the build script can override it in |
159 // certain cases without getting unused value errors. | 178 // certain cases without getting unused value errors. |
160 if (!scope_to_set->GetValue(arg.first)) { | 179 if (!scope_to_set->GetValue(arg.first)) { |
161 scope_to_set->SetValue(arg.first, arg.second, arg.second.origin()); | 180 scope_to_set->SetValue(arg.first, arg.second, arg.second.origin()); |
162 scope_to_set->MarkUsed(arg.first); | 181 scope_to_set->MarkUsed(arg.first); |
163 } | 182 } |
164 } | 183 } |
165 | 184 |
166 return true; | 185 return true; |
167 } | 186 } |
168 | 187 |
169 bool Args::VerifyAllOverridesUsed(Err* err) const { | 188 bool Args::VerifyAllOverridesUsed(Err* err) const { |
170 base::AutoLock lock(lock_); | 189 base::AutoLock lock(lock_); |
171 return VerifyAllOverridesUsed(all_overrides_, declared_arguments_, err); | 190 Scope::KeyValueMap all_overrides(all_overrides_); |
172 } | 191 for (const auto& map_pair : declared_arguments_per_toolchain_) |
192 RemoveDeclaredOverrides(map_pair.second, &all_overrides); | |
173 | 193 |
174 bool Args::VerifyAllOverridesUsed( | 194 if (all_overrides.empty()) |
175 const Scope::KeyValueMap& overrides, | 195 return true; |
176 const Scope::KeyValueMap& declared_arguments, | |
177 Err* err) { | |
178 for (const auto& override : overrides) { | |
179 if (declared_arguments.find(override.first) == declared_arguments.end()) { | |
180 // Get a list of all possible overrides for help with error finding. | |
181 // | |
182 // It might be nice to do edit distance checks to see if we can find one | |
183 // close to what you typed. | |
184 std::string all_declared_str; | |
185 for (Scope::KeyValueMap::const_iterator cur_str = | |
186 declared_arguments.begin(); | |
187 cur_str != declared_arguments.end(); ++cur_str) { | |
188 if (cur_str != declared_arguments.begin()) | |
189 all_declared_str += ", "; | |
190 all_declared_str += cur_str->first.as_string(); | |
191 } | |
192 | 196 |
193 *err = Err(override.second.origin(), "Build argument has no effect.", | 197 // Get a list of all possible overrides for help with error finding. |
194 "The variable \"" + override.first.as_string() + | 198 // |
195 "\" was set as a build " | 199 // It might be nice to do edit distance checks to see if we can find one close |
196 "argument\nbut never appeared in a declare_args() block in any " | 200 // to what you typed. |
197 "buildfile.\n\nPossible arguments: " + all_declared_str); | 201 std::string all_declared_str; |
198 return false; | 202 for (const auto& map_pair : declared_arguments_per_toolchain_) { |
203 for (const auto& cur_str : map_pair.second) { | |
204 if (!all_declared_str.empty()) | |
205 all_declared_str += ", "; | |
206 all_declared_str += cur_str.first.as_string(); | |
199 } | 207 } |
200 } | 208 } |
201 return true; | 209 |
210 *err = Err( | |
211 all_overrides.begin()->second.origin(), "Build argument has no effect.", | |
212 "The variable \"" + all_overrides.begin()->first.as_string() + | |
213 "\" was set as a build argument\nbut never appeared in a " + | |
sky
2015/03/16 16:20:45
git cl format did this. No idea why it indented he
| |
214 "declare_args() block in any buildfile.\n\nPossible arguments: " + | |
215 all_declared_str); | |
216 return false; | |
202 } | 217 } |
203 | 218 |
204 void Args::MergeDeclaredArguments(Scope::KeyValueMap* dest) const { | 219 void Args::MergeDeclaredArguments(Scope::KeyValueMap* dest) const { |
205 base::AutoLock lock(lock_); | 220 base::AutoLock lock(lock_); |
206 for (const auto& arg : declared_arguments_) | 221 for (const auto& map_pair : declared_arguments_per_toolchain_) { |
207 (*dest)[arg.first] = arg.second; | 222 for (const auto& arg : map_pair.second) |
223 (*dest)[arg.first] = arg.second; | |
224 } | |
208 } | 225 } |
209 | 226 |
210 void Args::SetSystemVarsLocked(Scope* dest) const { | 227 void Args::SetSystemVarsLocked(Scope* dest) const { |
211 lock_.AssertAcquired(); | 228 lock_.AssertAcquired(); |
212 | 229 |
213 // Host OS. | 230 // Host OS. |
214 const char* os = nullptr; | 231 const char* os = nullptr; |
215 #if defined(OS_WIN) | 232 #if defined(OS_WIN) |
216 os = "win"; | 233 os = "win"; |
217 #elif defined(OS_MACOSX) | 234 #elif defined(OS_MACOSX) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 Value os_val(nullptr, std::string(os)); | 267 Value os_val(nullptr, std::string(os)); |
251 dest->SetValue(variables::kHostOs, os_val, nullptr); | 268 dest->SetValue(variables::kHostOs, os_val, nullptr); |
252 dest->SetValue(variables::kTargetOs, empty_string, nullptr); | 269 dest->SetValue(variables::kTargetOs, empty_string, nullptr); |
253 dest->SetValue(variables::kCurrentOs, empty_string, nullptr); | 270 dest->SetValue(variables::kCurrentOs, empty_string, nullptr); |
254 | 271 |
255 Value arch_val(nullptr, std::string(arch)); | 272 Value arch_val(nullptr, std::string(arch)); |
256 dest->SetValue(variables::kHostCpu, arch_val, nullptr); | 273 dest->SetValue(variables::kHostCpu, arch_val, nullptr); |
257 dest->SetValue(variables::kTargetCpu, empty_string, nullptr); | 274 dest->SetValue(variables::kTargetCpu, empty_string, nullptr); |
258 dest->SetValue(variables::kCurrentCpu, empty_string, nullptr); | 275 dest->SetValue(variables::kCurrentCpu, empty_string, nullptr); |
259 | 276 |
260 declared_arguments_[variables::kHostOs] = os_val; | 277 Scope::KeyValueMap& declared_arguments( |
261 declared_arguments_[variables::kCurrentOs] = empty_string; | 278 DeclaredArgumentsForToolchainLocked(dest)); |
262 declared_arguments_[variables::kTargetOs] = empty_string; | 279 declared_arguments[variables::kHostOs] = os_val; |
263 declared_arguments_[variables::kHostCpu] = arch_val; | 280 declared_arguments[variables::kCurrentOs] = empty_string; |
264 declared_arguments_[variables::kCurrentCpu] = empty_string; | 281 declared_arguments[variables::kTargetOs] = empty_string; |
265 declared_arguments_[variables::kTargetCpu] = empty_string; | 282 declared_arguments[variables::kHostCpu] = arch_val; |
283 declared_arguments[variables::kCurrentCpu] = empty_string; | |
284 declared_arguments[variables::kTargetCpu] = empty_string; | |
266 | 285 |
267 // Mark these variables used so the build config file can override them | 286 // Mark these variables used so the build config file can override them |
268 // without geting a warning about overwriting an unused variable. | 287 // without geting a warning about overwriting an unused variable. |
269 dest->MarkUsed(variables::kHostCpu); | 288 dest->MarkUsed(variables::kHostCpu); |
270 dest->MarkUsed(variables::kCurrentCpu); | 289 dest->MarkUsed(variables::kCurrentCpu); |
271 dest->MarkUsed(variables::kTargetCpu); | 290 dest->MarkUsed(variables::kTargetCpu); |
272 dest->MarkUsed(variables::kHostOs); | 291 dest->MarkUsed(variables::kHostOs); |
273 dest->MarkUsed(variables::kCurrentOs); | 292 dest->MarkUsed(variables::kCurrentOs); |
274 dest->MarkUsed(variables::kTargetOs); | 293 dest->MarkUsed(variables::kTargetOs); |
275 } | 294 } |
276 | 295 |
277 void Args::ApplyOverridesLocked(const Scope::KeyValueMap& values, | 296 void Args::ApplyOverridesLocked(const Scope::KeyValueMap& values, |
278 Scope* scope) const { | 297 Scope* scope) const { |
279 lock_.AssertAcquired(); | 298 lock_.AssertAcquired(); |
280 for (const auto& val : values) | 299 for (const auto& val : values) |
281 scope->SetValue(val.first, val.second, val.second.origin()); | 300 scope->SetValue(val.first, val.second, val.second.origin()); |
282 } | 301 } |
283 | 302 |
284 void Args::SaveOverrideRecordLocked(const Scope::KeyValueMap& values) const { | 303 void Args::SaveOverrideRecordLocked(const Scope::KeyValueMap& values) const { |
285 lock_.AssertAcquired(); | 304 lock_.AssertAcquired(); |
286 for (const auto& val : values) | 305 for (const auto& val : values) |
287 all_overrides_[val.first] = val.second; | 306 all_overrides_[val.first] = val.second; |
288 } | 307 } |
308 | |
309 Scope::KeyValueMap& Args::DeclaredArgumentsForToolchainLocked( | |
310 Scope* scope) const { | |
311 lock_.AssertAcquired(); | |
312 return declared_arguments_per_toolchain_[scope->settings()]; | |
313 } | |
OLD | NEW |