Chromium Code Reviews| 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 |