1 // Copyright 2020 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 "gn/swift_values.h"
6
7 #include <algorithm>
8
9 #include "gn/deps_iterator.h"
10 #include "gn/err.h"
11 #include "gn/settings.h"
12 #include "gn/substitution_writer.h"
13 #include "gn/target.h"
14 #include "gn/tool.h"
15
16 SwiftValues::SwiftValues() = default;
17
18 SwiftValues::~SwiftValues() = default;
19
20 // static
OnTargetResolved(Target * target,Err * err)21 bool SwiftValues::OnTargetResolved(Target* target, Err* err) {
22 if (!target->builds_swift_module())
23 return true;
24
25 return target->swift_values().FillModuleOutputFile(target, err);
26 }
27
GetTool(const Target * target) const28 const Tool* SwiftValues::GetTool(const Target* target) const {
29 DCHECK(target->builds_swift_module());
30 return target->toolchain()->GetToolForSourceType(SourceFile::SOURCE_SWIFT);
31 }
32
GetOutputs(const Target * target,std::vector<OutputFile> * result) const33 void SwiftValues::GetOutputs(const Target* target,
34 std::vector<OutputFile>* result) const {
35 const Tool* tool = GetTool(target);
36
37 // Expand tool's outputs().
38 SubstitutionWriter::ApplyListToLinkerAsOutputFile(target, tool,
39 tool->outputs(), result);
40
41 // Expand tool's partial_outputs() for each .swift source file.
42 for (const SourceFile& source : target->sources()) {
43 if (!source.IsSwiftType()) {
44 continue;
45 }
46
47 SubstitutionWriter::ApplyListToCompilerAsOutputFile(
48 target, source, tool->partial_outputs(), result);
49 }
50 }
51
GetOutputsAsSourceFiles(const Target * target,std::vector<SourceFile> * result) const52 void SwiftValues::GetOutputsAsSourceFiles(
53 const Target* target,
54 std::vector<SourceFile>* result) const {
55 std::vector<OutputFile> outputs;
56 GetOutputs(target, &outputs);
57
58 result->reserve(outputs.size());
59
60 const BuildSettings* build_settings = target->settings()->build_settings();
61 for (const OutputFile& output : outputs) {
62 result->push_back(output.AsSourceFile(build_settings));
63 }
64 }
65
FillModuleOutputFile(Target * target,Err * err)66 bool SwiftValues::FillModuleOutputFile(Target* target, Err* err) {
67 std::vector<OutputFile> outputs;
68 GetOutputs(target, &outputs);
69
70 // Keep only .swiftmodule output files.
71 const BuildSettings* build_settings = target->settings()->build_settings();
72 const auto iter = std::remove_if(
73 outputs.begin(), outputs.end(),
74 [build_settings](const OutputFile& output) -> bool {
75 SourceFile output_as_source_file = output.AsSourceFile(build_settings);
76 return !output_as_source_file.IsSwiftModuleType();
77 });
78 outputs.erase(iter, outputs.end());
79
80 // A target should generate exactly one .swiftmodule file.
81 if (outputs.size() != 1) {
82 const Tool* tool = GetTool(target);
83 *err = Err(tool->defined_from(), "Incorrect outputs for tool",
84 "The outputs of tool " + std::string(tool->name()) +
85 " must list exactly one .swiftmodule file");
86 return false;
87 }
88
89 module_output_file_ = outputs.front();
90 module_output_dir_ =
91 module_output_file_.AsSourceFile(build_settings).GetDir();
92
93 return true;
94 }
95