@@ -15,6 +15,7 @@ import protocol Build.Toolchain
15
15
16
16
#if os(macOS)
17
17
private let whichClangArgs = [ " xcrun " , " --find " , " clang " ]
18
+ private let whichDefaultSDKArgs = [ " xcrun " , " --sdk " , " macosx " , " --show-sdk-path " ]
18
19
#else
19
20
private let whichClangArgs = [ " which " , " clang " ]
20
21
#endif
@@ -38,24 +39,75 @@ struct UserToolchain: Toolchain {
38
39
#endif
39
40
40
41
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) " )
56
102
}
57
- } catch POSIX . Error . exitStatus {
58
- throw Error . invalidToolchain
59
103
}
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
60
112
}
61
113
}
0 commit comments