[email protected] | 60749e1c | 2013-08-19 21:11:05 | [diff] [blame^] | 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. |
| 4 | |
| 5 | #include "tools/gn/args.h" |
| 6 | |
| 7 | #include "tools/gn/variables.h" |
| 8 | |
| 9 | const char kBuildArgs_Help[] = |
| 10 | "Build Arguments Overview.\n" |
| 11 | "\n" |
| 12 | " Build arguments are variables passed in from outside of the build\n" |
| 13 | " that build files can query to determine how the build works.\n" |
| 14 | "\n" |
| 15 | "How build arguments are set:\n" |
| 16 | "\n" |
| 17 | " First, system default arguments are set based on the current system.\n" |
| 18 | " The built-in arguments are:\n" |
| 19 | " - is_linux\n" |
| 20 | " - is_mac\n" |
| 21 | " - is_posix (set for Linux and Mac)\n" |
| 22 | " - is_win\n" |
| 23 | "\n" |
| 24 | " Second, arguments specified on the command-line via \"--args\" are\n" |
| 25 | " applied. These can override the system default ones, and add new ones.\n" |
| 26 | " These are whitespace-separated. For example:\n" |
| 27 | "\n" |
| 28 | " gn --args=\"teleportation_level=3 is_win=1 is_evil=0\"\n" |
| 29 | "\n" |
| 30 | " Third, toolchain overrides are applied. These are specified in the\n" |
| 31 | " toolchain_args section of a toolchain definition. The use-case for\n" |
| 32 | " this is that a toolchain may be building code for a different\n" |
| 33 | " platform, and that it may want to always specify Posix, for example.\n" |
| 34 | " See \"gn help toolchain_args\" for more.\n" |
| 35 | "\n" |
| 36 | " It is an error to specify an override for a build argument that never\n" |
| 37 | " appears in a \"declare_args\" call.\n" |
| 38 | "\n" |
| 39 | "How build arguments are used:\n" |
| 40 | "\n" |
| 41 | " If you want to use an argument, you use declare_args() and specify\n" |
| 42 | " default values. These default values will apply if none of the steps\n" |
| 43 | " listed in the \"How build arguments are set\" section above apply to\n" |
| 44 | " the given argument, but the defaults will not override any of these.\n" |
| 45 | "\n" |
| 46 | " Often, the root build config file will declare global arguments that\n" |
| 47 | " will be passed to all buildfiles. Individual build files can also\n" |
| 48 | " specify arguments that apply only to those files. It is also usedful\n" |
| 49 | " to specify build args in an \"import\"-ed file if you want such\n" |
| 50 | " arguments to apply to multiple buildfiles.\n"; |
| 51 | |
| 52 | Args::Args() { |
| 53 | } |
| 54 | |
| 55 | Args::~Args() { |
| 56 | } |
| 57 | |
| 58 | void Args::SwapInArgOverrides(Scope::KeyValueMap* overrides) { |
| 59 | DCHECK(overrides_.empty()); |
| 60 | overrides_.swap(*overrides); |
| 61 | for (Scope::KeyValueMap::const_iterator i = overrides_.begin(); |
| 62 | i != overrides_.end(); ++i) |
| 63 | all_overrides_.insert(*i); |
| 64 | } |
| 65 | |
| 66 | void Args::SetupRootScope(Scope* dest, |
| 67 | const Scope::KeyValueMap& toolchain_overrides) const { |
| 68 | SetSystemVars(dest); |
| 69 | ApplyOverrides(overrides_, dest); |
| 70 | ApplyOverrides(toolchain_overrides, dest); |
| 71 | SaveOverrideRecord(toolchain_overrides); |
| 72 | } |
| 73 | |
| 74 | bool Args::DeclareArgs(const Scope::KeyValueMap& args, |
| 75 | Scope* scope_to_set, |
| 76 | Err* err) const { |
| 77 | base::AutoLock lock(lock_); |
| 78 | |
| 79 | for (Scope::KeyValueMap::const_iterator i = args.begin(); |
| 80 | i != args.end(); ++i) { |
| 81 | // Verify that the value hasn't already been declared. We want each value |
| 82 | // to be declared only once. |
| 83 | // |
| 84 | // The tricky part is that a buildfile can be interpreted multiple times |
| 85 | // when used from different toolchains, so we can't just check that we've |
| 86 | // seen it before. Instead, we check that the location matches. We |
| 87 | // additionally check that the value matches to prevent people from |
| 88 | // declaring defaults based on other parameters that may change. The |
| 89 | // rationale is that you should have exactly one default value for each |
| 90 | // argument that we can display in the help. |
| 91 | Scope::KeyValueMap::iterator previously_declared = |
| 92 | declared_arguments_.find(i->first); |
| 93 | if (previously_declared != declared_arguments_.end()) { |
| 94 | if (previously_declared->second.origin() != i->second.origin()) { |
| 95 | // Declaration location mismatch. |
| 96 | *err = Err(i->second.origin(), "Duplicate build arg declaration.", |
| 97 | "Here you're declaring an argument that was already declared " |
| 98 | "elsewhere.\nYou can only declare each argument once in the entire " |
| 99 | "build so there is one\ncanonical place for documentation and the " |
| 100 | "default value. Either move this\nargument to the build config " |
| 101 | "file (for visibility everywhere) or to a .gni file\nthat you " |
| 102 | "\"import\" from the files where you need it (preferred)."); |
| 103 | err->AppendSubErr(Err(previously_declared->second.origin(), |
| 104 | "Previous declaration.", |
| 105 | "See also \"gn help buildargs\" for more on how " |
| 106 | "build args work.")); |
| 107 | return false; |
| 108 | } else if (previously_declared->second != i->second) { |
| 109 | // Default value mismatch. |
| 110 | *err = Err(i->second.origin(), |
| 111 | "Non-constant default value for build arg.", |
| 112 | "Each build arg should have one default value so we report it " |
| 113 | "nicely in the\n\"gn args\" command. Please make this value " |
| 114 | "constant."); |
| 115 | return false; |
| 116 | } |
| 117 | } else { |
| 118 | declared_arguments_.insert(*i); |
| 119 | } |
| 120 | |
| 121 | // Only set on the current scope to the new value if it hasn't been already |
| 122 | // set. |
| 123 | if (!scope_to_set->GetValue(i->first)) |
| 124 | scope_to_set->SetValue(i->first, i->second, i->second.origin()); |
| 125 | } |
| 126 | |
| 127 | return true; |
| 128 | } |
| 129 | |
| 130 | bool Args::VerifyAllOverridesUsed(Err* err) const { |
| 131 | base::AutoLock lock(lock_); |
| 132 | |
| 133 | for (Scope::KeyValueMap::const_iterator i = all_overrides_.begin(); |
| 134 | i != all_overrides_.end(); ++i) { |
| 135 | if (declared_arguments_.find(i->first) == declared_arguments_.end()) { |
| 136 | *err = Err(i->second.origin(), "Build arg has no effect.", |
| 137 | "The value \"" + i->first.as_string() + "\" was set a build " |
| 138 | "argument\nbut never appeared in a declare_args() block in any " |
| 139 | "buildfile."); |
| 140 | return false; |
| 141 | } |
| 142 | } |
| 143 | return true; |
| 144 | } |
| 145 | |
| 146 | void Args::SetSystemVars(Scope* dest) const { |
| 147 | #if defined(OS_WIN) |
| 148 | Value is_win(NULL, 1); |
| 149 | Value is_posix(NULL, 0); |
| 150 | #else |
| 151 | Value is_win(NULL, 0); |
| 152 | Value is_posix(NULL, 1); |
| 153 | #endif |
| 154 | dest->SetValue(variables::kIsWin, is_win, NULL); |
| 155 | dest->SetValue(variables::kIsPosix, is_posix, NULL); |
| 156 | declared_arguments_[variables::kIsWin] = is_win; |
| 157 | declared_arguments_[variables::kIsPosix] = is_posix; |
| 158 | |
| 159 | #if defined(OS_MACOSX) |
| 160 | Value is_mac(NULL, 1); |
| 161 | #else |
| 162 | Value is_mac(NULL, 0); |
| 163 | #endif |
| 164 | dest->SetValue(variables::kIsMac, is_mac, NULL); |
| 165 | declared_arguments_[variables::kIsMac] = is_mac; |
| 166 | |
| 167 | #if defined(OS_LINUX) |
| 168 | Value is_linux(NULL, 1); |
| 169 | #else |
| 170 | Value is_linux(NULL, 0); |
| 171 | #endif |
| 172 | dest->SetValue(variables::kIsLinux, is_linux, NULL); |
| 173 | declared_arguments_[variables::kIsLinux] = is_linux; |
| 174 | } |
| 175 | |
| 176 | void Args::ApplyOverrides(const Scope::KeyValueMap& values, |
| 177 | Scope* scope) const { |
| 178 | for (Scope::KeyValueMap::const_iterator i = values.begin(); |
| 179 | i != values.end(); ++i) |
| 180 | scope->SetValue(i->first, i->second, i->second.origin()); |
| 181 | } |
| 182 | |
| 183 | void Args::SaveOverrideRecord(const Scope::KeyValueMap& values) const { |
| 184 | base::AutoLock lock(lock_); |
| 185 | for (Scope::KeyValueMap::const_iterator i = values.begin(); |
| 186 | i != values.end(); ++i) |
| 187 | all_overrides_[i->first] = i->second; |
| 188 | } |