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 "build/build_config.h" 8 #include "tools/gn/variables.h" 9 10 #if defined(OS_WIN) 11 #include "base/win/windows_version.h" 12 #endif 13 14 const char kBuildArgs_Help[] = 15 "Build Arguments Overview\n" 16 "\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" 20 "How build arguments are set\n" 21 "\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" 26 " - default_os\n" 27 " - os (by default this is the same as \"default_os\")\n" 28 "\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" 33 " gn --args=\"enable_doom_melon=false\" os=\\\"beos\\\"\n" 34 "\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" 44 "How build arguments are used\n" 45 "\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 57 Args::Args() { 58 } 59 60 Args::Args(const Args& other) 61 : overrides_(other.overrides_), 62 all_overrides_(other.all_overrides_), 63 declared_arguments_(other.declared_arguments_) { 64 } 65 66 Args::~Args() { 67 } 68 69 void Args::AddArgOverride(const char* name, const Value& value) { 70 overrides_[base::StringPiece(name)] = value; 71 all_overrides_[base::StringPiece(name)] = value; 72 } 73 74 void Args::AddArgOverrides(const Scope::KeyValueMap& overrides) { 75 for (Scope::KeyValueMap::const_iterator i = overrides.begin(); 76 i != overrides.end(); ++i) { 77 overrides_[i->first] = i->second; 78 all_overrides_[i->first] = i->second; 79 } 80 } 81 82 void 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 90 bool 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 138 // 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)) { 141 scope_to_set->SetValue(i->first, i->second, i->second.origin()); 142 scope_to_set->MarkUsed(i->first); 143 } 144 } 145 146 return true; 147 } 148 149 bool 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 165 void Args::SetSystemVars(Scope* dest) const { 166 // Host OS. 167 const char* os = NULL; 168 #if defined(OS_WIN) 169 os = "win"; 170 #elif defined(OS_MACOSX) 171 os = "mac"; 172 #elif defined(OS_LINUX) 173 os = "linux"; 174 #else 175 #error Unknown OS type. 176 #endif 177 Value os_val(NULL, std::string(os)); 178 dest->SetValue(variables::kBuildOs, os_val, NULL); 179 dest->SetValue(variables::kOs, os_val, NULL); 180 181 // Host architecture. 182 static const char kX86[] = "x86"; 183 static const char kX64[] = "x64"; 184 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: 191 arch = kX86; 192 break; 193 case base::win::OSInfo::X64_ARCHITECTURE: 194 arch = kX64; 195 break; 196 default: 197 CHECK(false) << "Windows architecture not handled."; 198 break; 199 } 200 #else 201 // ...on all other platforms, just use the bit-tedness of the current 202 // process. 203 #if defined(ARCH_CPU_X86_64) 204 arch = kX64; 205 #elif defined(ARCH_CPU_X86) 206 arch = kX86; 207 #elif defined(ARCH_CPU_ARMEL) 208 static const char kArm[] = "arm"; 209 arch = kArm; 210 #else 211 #error Unknown architecture. 212 #endif 213 #endif 214 // Avoid unused var warning. 215 (void)kX86; 216 (void)kX64; 217 218 Value arch_val(NULL, std::string(arch)); 219 dest->SetValue(variables::kBuildCpuArch, arch_val, NULL); 220 dest->SetValue(variables::kCpuArch, arch_val, NULL); 221 222 // 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 // 228 // Mark these variables used so the build config file can override them 229 // without geting a warning about overwriting an unused variable. 230 declared_arguments_[variables::kOs] = os_val; 231 declared_arguments_[variables::kCpuArch] = arch_val; 232 dest->MarkUsed(variables::kCpuArch); 233 dest->MarkUsed(variables::kOs); 234 } 235 236 237 void 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 244 void 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 } 250