OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/xcode_writer.h" | 5 #include "tools/gn/xcode_writer.h" |
6 | 6 |
7 #include <iomanip> | 7 #include <iomanip> |
8 #include <map> | 8 #include <map> |
9 #include <memory> | 9 #include <memory> |
10 #include <sstream> | 10 #include <sstream> |
11 #include <string> | 11 #include <string> |
12 #include <utility> | 12 #include <utility> |
13 | 13 |
14 #include "base/environment.h" | 14 #include "base/environment.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/sha1.h" | 16 #include "base/sha1.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
19 #include "tools/gn/args.h" | 19 #include "tools/gn/args.h" |
20 #include "tools/gn/build_settings.h" | 20 #include "tools/gn/build_settings.h" |
21 #include "tools/gn/builder.h" | 21 #include "tools/gn/builder.h" |
22 #include "tools/gn/commands.h" | 22 #include "tools/gn/commands.h" |
23 #include "tools/gn/deps_iterator.h" | 23 #include "tools/gn/deps_iterator.h" |
24 #include "tools/gn/filesystem_utils.h" | 24 #include "tools/gn/filesystem_utils.h" |
25 #include "tools/gn/scope.h" | |
25 #include "tools/gn/settings.h" | 26 #include "tools/gn/settings.h" |
26 #include "tools/gn/source_file.h" | 27 #include "tools/gn/source_file.h" |
27 #include "tools/gn/target.h" | 28 #include "tools/gn/target.h" |
28 #include "tools/gn/value.h" | 29 #include "tools/gn/value.h" |
29 #include "tools/gn/variables.h" | 30 #include "tools/gn/variables.h" |
30 #include "tools/gn/xcode_object.h" | 31 #include "tools/gn/xcode_object.h" |
31 | 32 |
32 namespace { | 33 namespace { |
33 | 34 |
34 XcodeWriter::TargetOsType GetTargetOs(const Args& args) { | 35 bool GetTargetOs(const Scope* scope, std::string* target_os, Err* err) { |
35 const Value* target_os_value = args.GetArgOverride(variables::kTargetOs); | 36 const char* variable_names[] = {variables::kTargetOs, variables::kHostOs}; |
36 if (target_os_value) { | 37 for (size_t i = 0; i < arraysize(variable_names); ++i) { |
37 if (target_os_value->type() == Value::STRING) { | 38 const Value* value = scope->GetValue(variable_names[i]); |
38 if (target_os_value->string_value() == "ios") | 39 if (value && value->type() == Value::STRING && |
39 return XcodeWriter::WRITER_TARGET_OS_IOS; | 40 !value->string_value().empty()) { |
41 target_os->assign(value->string_value()); | |
42 return true; | |
40 } | 43 } |
41 } | 44 } |
42 return XcodeWriter::WRITER_TARGET_OS_MACOS; | 45 *err = Err(nullptr, "cannot determine target_os"); |
46 return false; | |
43 } | 47 } |
44 | 48 |
45 std::string GetArchs(const Args& args) { | 49 bool GetTargetCpu(const Scope* scope, std::string* target_cpu, Err* err) { |
46 const Value* target_cpu_value = args.GetArgOverride(variables::kTargetCpu); | 50 const char* variable_names[] = {variables::kTargetCpu, variables::kHostCpu}; |
47 if (target_cpu_value) { | 51 for (size_t i = 0; i < arraysize(variable_names); ++i) { |
48 if (target_cpu_value->type() == Value::STRING) { | 52 const Value* value = scope->GetValue(variable_names[i]); |
49 if (target_cpu_value->string_value() == "x86") | 53 if (value && value->type() == Value::STRING && |
50 return "i386"; | 54 !value->string_value().empty()) { |
51 if (target_cpu_value->string_value() == "x64") | 55 if (value->string_value() == "x86") { |
52 return "x86_64"; | 56 target_cpu->assign("i386"); |
53 if (target_cpu_value->string_value() == "arm") | 57 return true; |
54 return "armv7"; | 58 } |
55 if (target_cpu_value->string_value() == "armv7") | 59 if (value->string_value() == "x64") { |
56 return "armv7"; | 60 target_cpu->assign("x86_64"); |
57 if (target_cpu_value->string_value() == "arm64") | 61 return true; |
58 return "armv64"; | 62 } |
63 if (value->string_value() == "arm") { | |
64 target_cpu->assign("armv7"); | |
65 return true; | |
66 } | |
67 if (value->string_value() == "arm64") { | |
68 target_cpu->assign("arm64"); | |
69 return true; | |
70 } | |
59 } | 71 } |
60 } | 72 } |
61 return "x86_64"; | 73 *err = Err(nullptr, "cannot determine target_cpu"); |
74 return false; | |
75 } | |
76 | |
77 bool GetDeploymentTarget(const Scope* scope, | |
78 const char* variable, | |
79 std::string* deployment_target, | |
80 Err* err) { | |
81 const Value* value = scope->GetValue(variable); | |
82 if (!value || value->type() != Value::STRING) { | |
83 *err = Err(nullptr, "cannot determine deployment target"); | |
84 return false; | |
85 } | |
86 | |
87 deployment_target->assign(value->string_value()); | |
88 return true; | |
62 } | 89 } |
63 | 90 |
64 std::string GetBuildScript(const std::string& target_name, | 91 std::string GetBuildScript(const std::string& target_name, |
65 const std::string& build_path, | 92 const std::string& build_path, |
66 const std::string& ninja_extra_args) { | 93 const std::string& ninja_extra_args) { |
67 std::stringstream script; | 94 std::stringstream script; |
68 script << "echo note: \"Compile and copy " << target_name << " via ninja\"\n" | 95 script << "echo note: \"Compile and copy " << target_name << " via ninja\"\n" |
69 << "exec "; | 96 << "exec "; |
70 if (!build_path.empty()) | 97 if (!build_path.empty()) |
71 script << "env PATH=\"" << build_path << "\" "; | 98 script << "env PATH=\"" << build_path << "\" "; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
140 } // namespace | 167 } // namespace |
141 | 168 |
142 // static | 169 // static |
143 bool XcodeWriter::RunAndWriteFiles(const std::string& workspace_name, | 170 bool XcodeWriter::RunAndWriteFiles(const std::string& workspace_name, |
144 const std::string& root_target_name, | 171 const std::string& root_target_name, |
145 const std::string& ninja_extra_args, | 172 const std::string& ninja_extra_args, |
146 const std::string& dir_filters_string, | 173 const std::string& dir_filters_string, |
147 const BuildSettings* build_settings, | 174 const BuildSettings* build_settings, |
148 Builder* builder, | 175 Builder* builder, |
149 Err* err) { | 176 Err* err) { |
150 const XcodeWriter::TargetOsType target_os = | |
151 GetTargetOs(build_settings->build_args()); | |
152 | |
153 PBXAttributes attributes; | 177 PBXAttributes attributes; |
154 switch (target_os) { | 178 if (!GetProjectsAttributes(build_settings, &attributes, err)) |
155 case XcodeWriter::WRITER_TARGET_OS_IOS: | 179 return false; |
156 attributes["SDKROOT"] = "iphoneos"; | |
157 attributes["TARGETED_DEVICE_FAMILY"] = "1,2"; | |
158 break; | |
159 case XcodeWriter::WRITER_TARGET_OS_MACOS: | |
160 attributes["ARCHS"] = GetArchs(build_settings->build_args()); | |
161 attributes["SDKROOT"] = "macosx10.11"; | |
162 break; | |
163 } | |
164 | 180 |
165 const std::string source_path = | 181 const std::string source_path = |
166 base::FilePath::FromUTF8Unsafe( | 182 base::FilePath::FromUTF8Unsafe( |
167 RebasePath("//", build_settings->build_dir())) | 183 RebasePath("//", build_settings->build_dir())) |
168 .StripTrailingSeparators() | 184 .StripTrailingSeparators() |
169 .AsUTF8Unsafe(); | 185 .AsUTF8Unsafe(); |
170 | 186 |
171 std::string config_name = build_settings->build_dir() | 187 std::string config_name = build_settings->build_dir() |
172 .Resolve(base::FilePath()) | 188 .Resolve(base::FilePath()) |
173 .StripTrailingSeparators() | 189 .StripTrailingSeparators() |
174 .BaseName() | 190 .BaseName() |
175 .AsUTF8Unsafe(); | 191 .AsUTF8Unsafe(); |
176 DCHECK(!config_name.empty()); | 192 DCHECK(!config_name.empty()); |
177 | 193 |
178 std::string::size_type separator = config_name.find('-'); | 194 std::string::size_type separator = config_name.find('-'); |
179 if (separator != std::string::npos) | 195 if (separator != std::string::npos) |
180 config_name = config_name.substr(0, separator); | 196 config_name = config_name.substr(0, separator); |
181 | 197 |
182 std::vector<const Target*> targets; | 198 std::vector<const Target*> targets; |
183 std::vector<const Target*> all_targets = builder->GetAllResolvedTargets(); | 199 std::vector<const Target*> all_targets = builder->GetAllResolvedTargets(); |
184 if (!XcodeWriter::FilterTargets(build_settings, all_targets, | 200 if (!XcodeWriter::FilterTargets(build_settings, all_targets, |
185 dir_filters_string, &targets, err)) { | 201 dir_filters_string, &targets, err)) { |
186 return false; | 202 return false; |
187 } | 203 } |
188 | 204 |
189 XcodeWriter workspace(workspace_name); | 205 XcodeWriter workspace(workspace_name); |
190 workspace.CreateProductsProject(targets, attributes, source_path, config_name, | 206 workspace.CreateProductsProject(targets, attributes, source_path, config_name, |
191 root_target_name, ninja_extra_args, | 207 root_target_name, ninja_extra_args, |
192 build_settings, target_os); | 208 build_settings); |
193 | 209 |
194 workspace.CreateSourcesProject(all_targets, build_settings->build_dir(), | 210 workspace.CreateSourcesProject(all_targets, build_settings->build_dir(), |
195 attributes, source_path, config_name, | 211 attributes, source_path, config_name); |
196 target_os); | |
197 | 212 |
198 return workspace.WriteFiles(build_settings, err); | 213 return workspace.WriteFiles(build_settings, err); |
199 } | 214 } |
200 | 215 |
201 XcodeWriter::XcodeWriter(const std::string& name) : name_(name) { | 216 XcodeWriter::XcodeWriter(const std::string& name) : name_(name) { |
202 if (name_.empty()) | 217 if (name_.empty()) |
203 name_.assign("all"); | 218 name_.assign("all"); |
204 } | 219 } |
205 | 220 |
206 XcodeWriter::~XcodeWriter() {} | 221 XcodeWriter::~XcodeWriter() {} |
207 | 222 |
208 // static | 223 // static |
224 bool XcodeWriter::GetProjectsAttributes(const BuildSettings* build_settings, | |
225 PBXAttributes* attributes, | |
226 Err* err) { | |
227 Settings* null_settings = nullptr; | |
sdefresne
2016/06/14 17:45:10
I'm not sure about this code. Previously the code
| |
228 Scope global_scope(null_settings); | |
229 Scope::KeyValueMap declared_arguments; | |
230 build_settings->build_args().MergeDeclaredArguments(&declared_arguments); | |
231 for (const auto& pair : declared_arguments) { | |
232 global_scope.SetValue(pair.first, pair.second, nullptr); | |
233 } | |
234 build_settings->build_args().SetupRootScope(&global_scope, | |
235 Scope::KeyValueMap()); | |
236 | |
237 std::string target_os; | |
238 if (!GetTargetOs(&global_scope, &target_os, err)) | |
239 return false; | |
240 | |
241 std::string target_cpu; | |
242 if (!GetTargetCpu(&global_scope, &target_cpu, err)) | |
243 return false; | |
244 | |
245 if (target_os == "ios") { | |
246 std::string deployment_target; | |
247 if (!GetDeploymentTarget(&global_scope, "ios_deployment_target", | |
248 &deployment_target, err)) | |
249 return false; | |
250 | |
251 attributes->insert(std::make_pair("SDKROOT", "iphoneos")); | |
252 attributes->insert(std::make_pair("TARGETED_DEVICE_FAMILY", "1,2")); | |
253 attributes->insert( | |
254 std::make_pair("IPHONEOS_DEPLOYMENT_TARGET", deployment_target)); | |
255 } else { | |
256 std::string deployment_target; | |
257 if (!GetDeploymentTarget(&global_scope, "mac_deployment_target", | |
258 &deployment_target, err)) | |
259 return false; | |
260 | |
261 attributes->insert(std::make_pair("ARCHS", target_cpu)); | |
262 attributes->insert(std::make_pair("SDKROOT", "macosx")); | |
263 attributes->insert( | |
264 std::make_pair("MACOSX_DEPLOYMENT_TARGET", deployment_target)); | |
265 } | |
266 | |
267 return true; | |
268 } | |
269 | |
270 // static | |
209 bool XcodeWriter::FilterTargets(const BuildSettings* build_settings, | 271 bool XcodeWriter::FilterTargets(const BuildSettings* build_settings, |
210 const std::vector<const Target*>& all_targets, | 272 const std::vector<const Target*>& all_targets, |
211 const std::string& dir_filters_string, | 273 const std::string& dir_filters_string, |
212 std::vector<const Target*>* targets, | 274 std::vector<const Target*>* targets, |
213 Err* err) { | 275 Err* err) { |
214 // Filter targets according to the semicolon-delimited list of label patterns, | 276 // Filter targets according to the semicolon-delimited list of label patterns, |
215 // if defined, first. | 277 // if defined, first. |
216 targets->reserve(all_targets.size()); | 278 targets->reserve(all_targets.size()); |
217 if (dir_filters_string.empty()) { | 279 if (dir_filters_string.empty()) { |
218 *targets = all_targets; | 280 *targets = all_targets; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 return true; | 321 return true; |
260 } | 322 } |
261 | 323 |
262 void XcodeWriter::CreateProductsProject( | 324 void XcodeWriter::CreateProductsProject( |
263 const std::vector<const Target*>& targets, | 325 const std::vector<const Target*>& targets, |
264 const PBXAttributes& attributes, | 326 const PBXAttributes& attributes, |
265 const std::string& source_path, | 327 const std::string& source_path, |
266 const std::string& config_name, | 328 const std::string& config_name, |
267 const std::string& root_target, | 329 const std::string& root_target, |
268 const std::string& ninja_extra_args, | 330 const std::string& ninja_extra_args, |
269 const BuildSettings* build_settings, | 331 const BuildSettings* build_settings) { |
270 TargetOsType target_os) { | |
271 std::unique_ptr<PBXProject> main_project( | 332 std::unique_ptr<PBXProject> main_project( |
272 new PBXProject("products", config_name, source_path, attributes)); | 333 new PBXProject("products", config_name, source_path, attributes)); |
273 | 334 |
274 std::string build_path; | 335 std::string build_path; |
275 std::unique_ptr<base::Environment> env(base::Environment::Create()); | 336 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
276 env->GetVar("PATH", &build_path); | 337 env->GetVar("PATH", &build_path); |
277 | 338 |
278 main_project->AddAggregateTarget( | 339 main_project->AddAggregateTarget( |
279 "All", GetBuildScript(root_target, build_path, ninja_extra_args)); | 340 "All", GetBuildScript(root_target, build_path, ninja_extra_args)); |
280 | 341 |
342 const auto iter = attributes.find("SDKROOT"); | |
343 const bool skip_executable_targets = | |
344 iter != attributes.end() && iter->second == "iphoneos"; | |
345 | |
281 for (const Target* target : targets) { | 346 for (const Target* target : targets) { |
282 switch (target->output_type()) { | 347 switch (target->output_type()) { |
283 case Target::EXECUTABLE: | 348 case Target::EXECUTABLE: |
284 if (target_os == XcodeWriter::WRITER_TARGET_OS_IOS) | 349 if (skip_executable_targets) |
285 continue; | 350 continue; |
286 | 351 |
287 main_project->AddNativeTarget( | 352 main_project->AddNativeTarget( |
288 target->label().name(), "compiled.mach-o.executable", | 353 target->label().name(), "compiled.mach-o.executable", |
289 target->output_name().empty() ? target->label().name() | 354 target->output_name().empty() ? target->label().name() |
290 : target->output_name(), | 355 : target->output_name(), |
291 "com.apple.product-type.tool", | 356 "com.apple.product-type.tool", |
292 GetBuildScript(target->label().name(), build_path, | 357 GetBuildScript(target->label().name(), build_path, |
293 ninja_extra_args)); | 358 ninja_extra_args)); |
294 break; | 359 break; |
(...skipping 19 matching lines...) Expand all Loading... | |
314 } | 379 } |
315 | 380 |
316 projects_.push_back(std::move(main_project)); | 381 projects_.push_back(std::move(main_project)); |
317 } | 382 } |
318 | 383 |
319 void XcodeWriter::CreateSourcesProject( | 384 void XcodeWriter::CreateSourcesProject( |
320 const std::vector<const Target*>& targets, | 385 const std::vector<const Target*>& targets, |
321 const SourceDir& root_build_dir, | 386 const SourceDir& root_build_dir, |
322 const PBXAttributes& attributes, | 387 const PBXAttributes& attributes, |
323 const std::string& source_path, | 388 const std::string& source_path, |
324 const std::string& config_name, | 389 const std::string& config_name) { |
325 TargetOsType target_os) { | |
326 std::vector<SourceFile> sources; | 390 std::vector<SourceFile> sources; |
327 for (const Target* target : targets) { | 391 for (const Target* target : targets) { |
328 if (!target->settings()->is_default()) | 392 if (!target->settings()->is_default()) |
329 continue; | 393 continue; |
330 | 394 |
331 for (const SourceFile& source : target->sources()) { | 395 for (const SourceFile& source : target->sources()) { |
332 if (source.is_system_absolute()) | 396 if (source.is_system_absolute()) |
333 continue; | 397 continue; |
334 | 398 |
335 if (IsStringInOutputDir(root_build_dir, source.value())) | 399 if (IsStringInOutputDir(root_build_dir, source.value())) |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 for (const auto& object : pair.second) { | 489 for (const auto& object : pair.second) { |
426 object->Print(out, 2); | 490 object->Print(out, 2); |
427 } | 491 } |
428 out << "/* End " << ToString(pair.first) << " section */\n"; | 492 out << "/* End " << ToString(pair.first) << " section */\n"; |
429 } | 493 } |
430 | 494 |
431 out << "\t};\n" | 495 out << "\t};\n" |
432 << "\trootObject = " << project->Reference() << ";\n" | 496 << "\trootObject = " << project->Reference() << ";\n" |
433 << "}\n"; | 497 << "}\n"; |
434 } | 498 } |
OLD | NEW |