Skip to content

Commit 0a2617e

Browse files
committed
Improved error messages for when swiftc, clang, or sysroot can't be found.
No fix-its yet, but they will come. https://bugs.swift.org/browse/SR-2271
1 parent 389e49b commit 0a2617e

File tree

2 files changed

+72
-20
lines changed

2 files changed

+72
-20
lines changed

Sources/Commands/Error.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import var Utility.stderr
1919

2020
public enum Error: Swift.Error {
2121
case noManifestFound
22-
case invalidToolchain
22+
case invalidToolchain(problem: String)
2323
case buildYAMLNotFound(String)
2424
case repositoryHasChanges(String)
2525
}
@@ -29,8 +29,8 @@ extension Error: FixableError {
2929
switch self {
3030
case .noManifestFound:
3131
return "no \(Manifest.filename) file found"
32-
case .invalidToolchain:
33-
return "invalid inferred toolchain"
32+
case .invalidToolchain(let problem):
33+
return "invalid inferred toolchain: \(problem)"
3434
case .buildYAMLNotFound(let value):
3535
return "no build YAML found: \(value)"
3636
case .repositoryHasChanges(let value):

Sources/Commands/UserToolchain.swift

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import protocol Build.Toolchain
1515

1616
#if os(macOS)
1717
private let whichClangArgs = ["xcrun", "--find", "clang"]
18+
private let whichDefaultSDKArgs = ["xcrun", "--sdk", "macosx", "--show-sdk-path"]
1819
#else
1920
private let whichClangArgs = ["which", "clang"]
2021
#endif
@@ -38,24 +39,75 @@ struct UserToolchain: Toolchain {
3839
#endif
3940

4041
init() throws {
41-
do {
42-
SWIFT_EXEC = getenv("SWIFT_EXEC")
43-
// use the swiftc installed alongside ourselves
44-
?? AbsolutePath(CommandLine.arguments[0], relativeTo: currentWorkingDirectory).parentDirectory.appending(component: "swiftc").asString
45-
46-
clang = try getenv("CC") ?? POSIX.popen(whichClangArgs).chomp()
47-
48-
#if os(macOS)
49-
sysroot = try getenv("SYSROOT") ?? POSIX.popen(["xcrun", "--sdk", "macosx", "--show-sdk-path"]).chomp()
50-
#else
51-
sysroot = nil
52-
#endif
53-
54-
guard !SWIFT_EXEC.isEmpty && !clang.isEmpty && (sysroot == nil || !sysroot!.isEmpty) else {
55-
throw Error.invalidToolchain
42+
let swiftCompiler: AbsolutePath
43+
let clangCompiler: AbsolutePath
44+
let defaultSDK: AbsolutePath?
45+
46+
// Find the Swift compiler, looking first in the environment.
47+
if let value = getenv("SWIFT_EXEC"), !value.isEmpty {
48+
// We have a value, but it could be an absolute or a relative path.
49+
swiftCompiler = AbsolutePath(value, relativeTo: currentWorkingDirectory)
50+
}
51+
else {
52+
// No value in env, so look for `swiftc` alongside our own binary.
53+
swiftCompiler = AbsolutePath(CommandLine.arguments[0], relativeTo: currentWorkingDirectory).parentDirectory.appending(component: "swiftc")
54+
}
55+
56+
// Check that it's valid in the file system.
57+
// FIXME: We should also check that it resolves to an executable file
58+
// (it could be a symlink to such as file).
59+
guard localFileSystem.exists(swiftCompiler) else {
60+
throw Error.invalidToolchain(problem: "could not find `swiftc` at expected path \(swiftCompiler.asString)")
61+
}
62+
63+
// Find the Clang compiler, looking first in the environment.
64+
if let value = getenv("CC"), !value.isEmpty {
65+
// We have a value, but it could be an absolute or a relative path.
66+
clangCompiler = AbsolutePath(value, relativeTo: currentWorkingDirectory)
67+
}
68+
else {
69+
// No value in env, so search for `clang`.
70+
guard let foundPath = try? POSIX.popen(whichClangArgs).chomp(), !foundPath.isEmpty else {
71+
throw Error.invalidToolchain(problem: "could not find `clang`")
72+
}
73+
clangCompiler = AbsolutePath(foundPath, relativeTo: currentWorkingDirectory)
74+
}
75+
76+
// Check that it's valid in the file system.
77+
// FIXME: We should also check that it resolves to an executable file
78+
// (it could be a symlink to such as file).
79+
guard localFileSystem.exists(clangCompiler) else {
80+
throw Error.invalidToolchain(problem: "could not find `clang` at expected path \(clangCompiler.asString)")
81+
}
82+
83+
// Find the default SDK (on macOS only).
84+
#if os(macOS)
85+
if let value = getenv("SYSROOT"), !value.isEmpty {
86+
// We have a value, but it could be an absolute or a relative path.
87+
defaultSDK = AbsolutePath(value, relativeTo: currentWorkingDirectory)
88+
}
89+
else {
90+
// No value in env, so search for it.
91+
guard let foundPath = try? POSIX.popen(whichDefaultSDKArgs).chomp(), !foundPath.isEmpty else {
92+
throw Error.invalidToolchain(problem: "could not find default SDK")
93+
}
94+
defaultSDK = AbsolutePath(foundPath, relativeTo: currentWorkingDirectory)
95+
}
96+
97+
// If we have an SDK, we check that it's valid in the file system.
98+
if let sdk = defaultSDK {
99+
// FIXME: We should probably also check that it is a directory, etc.
100+
guard localFileSystem.exists(sdk) else {
101+
throw Error.invalidToolchain(problem: "could not find default SDK at expected path \(sdk.asString)")
56102
}
57-
} catch POSIX.Error.exitStatus {
58-
throw Error.invalidToolchain
59103
}
104+
#else
105+
defaultSDK = nil
106+
#endif
107+
108+
// Finally set the properties (we will refactor these to paths in the next diff).
109+
SWIFT_EXEC = swiftCompiler.asString
110+
clang = clangCompiler.asString
111+
sysroot = defaultSDK?.asString
60112
}
61113
}

0 commit comments

Comments
 (0)