Skip to content

Commit ffa477c

Browse files
authored
Fix search for coverage tools on Windows & cleanup UserToolchain (#2712)
* Improve search for compilers: use LocalFileSystem * Improve search for tools: llvm-cov on Windows & reduce duplication
1 parent 03c10be commit ffa477c

File tree

1 file changed

+22
-42
lines changed

1 file changed

+22
-42
lines changed

Sources/Workspace/UserToolchain.swift

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ import PackageLoading
1414
import SPMBuildCore
1515
import Build
1616

17-
#if !os(macOS)
18-
import class Foundation.FileManager
19-
#endif
20-
2117
#if os(Windows)
2218
private let hostExecutableSuffix = ".exe"
2319
#else
@@ -78,21 +74,27 @@ public final class UserToolchain: Toolchain {
7874

7975
return runtime
8076
}
81-
82-
private static func findProgram(_ name: String, envSearchPaths: [AbsolutePath]) throws -> AbsolutePath {
77+
78+
private static func getTool(_ name: String, binDir: AbsolutePath) throws -> AbsolutePath {
79+
let executableName = "\(name)\(hostExecutableSuffix)"
80+
let toolPath = binDir.appending(component: executableName)
81+
guard localFileSystem.isExecutableFile(toolPath) else {
82+
throw InvalidToolchainDiagnostic("could not find \(name) at expected path \(toolPath)")
83+
}
84+
return toolPath
85+
}
86+
87+
private static func findTool(_ name: String, envSearchPaths: [AbsolutePath]) throws -> AbsolutePath {
8388
#if os(macOS)
8489
let foundPath = try Process.checkNonZeroExit(arguments: ["/usr/bin/xcrun", "--find", name]).spm_chomp()
8590
return try AbsolutePath(validating: foundPath)
8691
#else
87-
let executableName = "\(name)\(hostExecutableSuffix)"
88-
8992
for folder in envSearchPaths {
90-
let path = folder.appending(component: executableName)
91-
if FileManager.default.fileExists(atPath: path.pathString) {
92-
return path
93+
if let toolPath = try? getTool(name, binDir: folder) {
94+
return toolPath
9395
}
9496
}
95-
throw InvalidToolchainDiagnostic("Missing tool \(name)")
97+
throw InvalidToolchainDiagnostic("could not find \(name)")
9698
#endif
9799
}
98100

@@ -116,15 +118,14 @@ public final class UserToolchain: Toolchain {
116118
// We require there is at least one valid swift compiler, either in the
117119
// bin dir or SWIFT_EXEC.
118120
let resolvedBinDirCompiler: AbsolutePath
119-
let binDirCompiler = binDir.appending(component: "swiftc" + hostExecutableSuffix)
120-
if localFileSystem.isExecutableFile(binDirCompiler) {
121+
if let binDirCompiler = try? UserToolchain.getTool("swiftc", binDir: binDir) {
121122
resolvedBinDirCompiler = binDirCompiler
122123
} else if let SWIFT_EXEC = SWIFT_EXEC {
123124
resolvedBinDirCompiler = SWIFT_EXEC
124125
} else {
125126
// Try to lookup swift compiler on the system which is possible when
126127
// we're built outside of the Swift toolchain.
127-
resolvedBinDirCompiler = try UserToolchain.findProgram("swiftc", envSearchPaths: envSearchPaths)
128+
resolvedBinDirCompiler = try UserToolchain.findTool("swiftc", envSearchPaths: envSearchPaths)
128129
}
129130

130131
// The compiler for compilation tasks is SWIFT_EXEC or the bin dir compiler.
@@ -154,15 +155,14 @@ public final class UserToolchain: Toolchain {
154155

155156
// Then, check the toolchain.
156157
do {
157-
let toolPath = destination.binDir.appending(component: "clang" + hostExecutableSuffix)
158-
if localFileSystem.exists(toolPath) {
158+
if let toolPath = try? UserToolchain.getTool("clang", binDir: destination.binDir) {
159159
_clangCompiler = toolPath
160160
return toolPath
161161
}
162162
}
163163

164164
// Otherwise, lookup it up on the system.
165-
let toolPath = try UserToolchain.findProgram("clang", envSearchPaths: envSearchPaths)
165+
let toolPath = try UserToolchain.findTool("clang", envSearchPaths: envSearchPaths)
166166
_clangCompiler = toolPath
167167
return toolPath
168168
}
@@ -180,46 +180,26 @@ public final class UserToolchain: Toolchain {
180180

181181
/// Returns the path to llvm-cov tool.
182182
public func getLLVMCov() throws -> AbsolutePath {
183-
let toolPath = destination.binDir.appending(component: "llvm-cov")
184-
guard localFileSystem.isExecutableFile(toolPath) else {
185-
throw InvalidToolchainDiagnostic("could not find llvm-cov at expected path \(toolPath)")
186-
}
187-
return toolPath
183+
return try UserToolchain.getTool("llvm-cov", binDir: destination.binDir)
188184
}
189185

190186
/// Returns the path to llvm-prof tool.
191187
public func getLLVMProf() throws -> AbsolutePath {
192-
let toolPath = destination.binDir.appending(component: "llvm-profdata")
193-
guard localFileSystem.isExecutableFile(toolPath) else {
194-
throw InvalidToolchainDiagnostic("could not find llvm-profdata at expected path \(toolPath)")
195-
}
196-
return toolPath
188+
return try UserToolchain.getTool("llvm-profdata", binDir: destination.binDir)
197189
}
198190

199191
public func getSwiftAPIDigester() throws -> AbsolutePath {
200192
if let envValue = UserToolchain.lookup(variable: "SWIFT_API_DIGESTER", searchPaths: envSearchPaths) {
201193
return envValue
202194
}
203-
204-
let candidate = swiftCompiler.parentDirectory.appending(component: "swift-api-digester")
205-
if localFileSystem.exists(candidate) {
206-
return candidate
207-
}
208-
209-
throw InvalidToolchainDiagnostic("could not find swift-api-digester")
195+
return try UserToolchain.getTool("swift-api-digester", binDir: swiftCompiler.parentDirectory)
210196
}
211197

212198
public func getSymbolGraphExtract() throws -> AbsolutePath {
213199
if let envValue = UserToolchain.lookup(variable: "SWIFT_SYMBOLGRAPH_EXTRACT", searchPaths: envSearchPaths) {
214200
return envValue
215201
}
216-
217-
let candidate = swiftCompiler.parentDirectory.appending(component: "swift-symbolgraph-extract")
218-
if localFileSystem.exists(candidate) {
219-
return candidate
220-
}
221-
222-
throw InvalidToolchainDiagnostic("could not find swift-api-digester")
202+
return try UserToolchain.getTool("swift-symbolgraph-extract", binDir: swiftCompiler.parentDirectory)
223203
}
224204

225205
public static func deriveSwiftCFlags(triple: Triple, destination: Destination) -> [String] {

0 commit comments

Comments
 (0)