Skip to content

Commit 037a8cf

Browse files
committed
Add support to custom toolchains
Signed-off-by: Lucas Marçal <[email protected]>
1 parent d78f143 commit 037a8cf

File tree

7 files changed

+83
-56
lines changed

7 files changed

+83
-56
lines changed

tools/generators/legacy/src/Extensions/XCScheme+Extensions.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ extension XCScheme {
3535
.first
3636
{
3737
otherPreActions.append(
38-
.symlinkDefaultToolchainUsrLibDirectory(
38+
.symlinkToolchainUsrLibDirectory(
3939
buildableReference: launchableTarget.targetInfo
4040
.buildableReference
4141
)
@@ -201,10 +201,10 @@ touch "$BUILD_MARKER_FILE"
201201
)
202202
}
203203

204-
/// Symlinks `$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib` to
204+
/// Symlinks `$TOOLCHAIN_DIR/usr/lib` to
205205
/// `$(BAZEL_INTEGRATION_DIR)/../lib` so that Xcode can copy sanitizers'
206206
/// dylibs.
207-
static func symlinkDefaultToolchainUsrLibDirectory(
207+
static func symlinkToolchainUsrLibDirectory(
208208
buildableReference: XCScheme.BuildableReference
209209
) -> XCScheme.ExecutionAction {
210210
return .init(
@@ -215,9 +215,12 @@ if [[ "${ENABLE_ADDRESS_SANITIZER:-}" == "YES" || \
215215
"${ENABLE_THREAD_SANITIZER:-}" == "YES" || \
216216
"${ENABLE_UNDEFINED_BEHAVIOR_SANITIZER:-}" == "YES" ]]
217217
then
218-
# TODO: Support custom toolchains once clang.sh supports them
219218
cd "$INTERNAL_DIR" || exit 1
220-
ln -shfF "$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib" lib
219+
if [[ -n "${TOOLCHAIN_DIR:-}" ]]; then
220+
ln -shfF "$TOOLCHAIN_DIR/usr/lib" lib
221+
else
222+
ln -shfF "$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib" lib
223+
fi
221224
fi
222225
"""#,
223226
title: "Prepare BazelDependencies",

tools/generators/legacy/test/CreateAutogeneratedXCSchemesTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class CreateAutogeneratedXCSchemesTests: XCTestCase {
178178
expectedTargetInfo.productType.isLaunchable
179179
{
180180
expectedBuildPreActions.append(
181-
.symlinkDefaultToolchainUsrLibDirectory(
181+
.symlinkToolchainUsrLibDirectory(
182182
buildableReference: expectedTargetInfo.buildableReference
183183
)
184184
)

tools/generators/xcschemes/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Here is an example output:
7878
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
7979
<ActionContent
8080
title = "Prepare BazelDependencies"
81-
scriptText = "mkdir -p &quot;$PROJECT_DIR&quot;&#10;&#10;if [[ &quot;${ENABLE_ADDRESS_SANITIZER:-}&quot; == &quot;YES&quot; || \&#10; &quot;${ENABLE_THREAD_SANITIZER:-}&quot; == &quot;YES&quot; || \&#10; &quot;${ENABLE_UNDEFINED_BEHAVIOR_SANITIZER:-}&quot; == &quot;YES&quot; ]]&#10;then&#10; # TODO: Support custom toolchains once clang.sh supports them&#10; cd &quot;$INTERNAL_DIR&quot; || exit 1&#10; ln -shfF &quot;$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib&quot; lib&#10;fi&#10;">
81+
scriptText = "mkdir -p &quot;$PROJECT_DIR&quot;&#10;&#10;if [[ &quot;${ENABLE_ADDRESS_SANITIZER:-}&quot; == &quot;YES&quot; || \&#10; &quot;${ENABLE_THREAD_SANITIZER:-}&quot; == &quot;YES&quot; || \&#10; &quot;${ENABLE_UNDEFINED_BEHAVIOR_SANITIZER:-}&quot; == &quot;YES&quot; ]]&#10;then&#10; $INTERNAL_DIR&quot; || exit 1&#10; ln -shfF &quot;$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib&quot; lib&#10;fi&#10;">
8282
<EnvironmentBuildable>
8383
<BuildableReference
8484
BuildableIdentifier = "primary"

tools/generators/xcschemes/src/Generator/CreateScheme.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,9 +478,12 @@ if [[ "${ENABLE_ADDRESS_SANITIZER:-}" == "YES" || \
478478
"${ENABLE_THREAD_SANITIZER:-}" == "YES" || \
479479
"${ENABLE_UNDEFINED_BEHAVIOR_SANITIZER:-}" == "YES" ]]
480480
then
481-
# TODO: Support custom toolchains once clang.sh supports them
482481
cd "$INTERNAL_DIR" || exit 1
483-
ln -shfF "$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib" lib
482+
if [[ -n "${TOOLCHAIN_DIR:-}" ]]; then
483+
ln -shfF "$TOOLCHAIN_DIR/usr/lib" lib
484+
else
485+
ln -shfF "$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib" lib
486+
fi
484487
fi
485488
486489
"""#.schemeXmlEscaped

tools/swiftc_stub/main.swift

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -138,39 +138,38 @@ func runSubProcess(executable: String, args: [String]) throws -> Int32 {
138138
}
139139

140140
func handleXcodePreviewThunk(args: [String], paths: [PathKey: URL]) throws -> Never {
141-
guard let sdkPath = paths[PathKey.sdk]?.path else {
142-
fputs(
143-
"error: No such argument '-sdk'. Using /usr/bin/swiftc.",
144-
stderr
145-
)
146-
exit(1)
141+
var swiftcPath: String?
142+
143+
if let toolchainDir = ProcessInfo.processInfo.environment["TOOLCHAIN_DIR"] {
144+
swiftcPath = "\(toolchainDir)/usr/bin/swiftc"
145+
} else {
146+
guard let sdkPath = paths[PathKey.sdk]?.path else {
147+
fputs("error: No such argument '-sdk'. Using /usr/bin/swiftc.", stderr)
148+
exit(1)
149+
}
150+
151+
// We could produce this file at the start of the build?
152+
let fullRange = NSRange(sdkPath.startIndex..., in: sdkPath)
153+
let matches = try NSRegularExpression(
154+
pattern: #"(.*?/Contents/Developer)/.*"#
155+
).matches(in: sdkPath, range: fullRange)
156+
guard let match = matches.first,
157+
let range = Range(match.range(at: 1), in: sdkPath)
158+
else {
159+
fputs("error: Failed to parse DEVELOPER_DIR from '-sdk'. Using /usr/bin/swiftc.", stderr)
160+
exit(1)
161+
}
162+
let developerDir = sdkPath[range]
163+
164+
swiftcPath = "\(developerDir)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc"
147165
}
148166

149-
// TODO: Make this work with custom toolchains
150-
// We could produce this file at the start of the build?
151-
let fullRange = NSRange(sdkPath.startIndex..., in: sdkPath)
152-
let matches = try NSRegularExpression(
153-
pattern: #"(.*?/Contents/Developer)/.*"#
154-
).matches(in: sdkPath, range: fullRange)
155-
guard let match = matches.first,
156-
let range = Range(match.range(at: 1), in: sdkPath)
157-
else {
158-
fputs(
159-
"""
160-
error: Failed to parse DEVELOPER_DIR from '-sdk'. Using /usr/bin/swiftc.
161-
""",
162-
stderr
163-
)
167+
guard let swiftcPath else {
168+
fputs("error: Failed to determine swiftc path", stderr)
164169
exit(1)
165170
}
166-
let developerDir = sdkPath[range]
167-
168-
try exit(runSubProcess(
169-
executable: """
170-
\(developerDir)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc
171-
""",
172-
args: Array(args.dropFirst())
173-
))
171+
172+
try exit(runSubProcess(executable: swiftcPath, args: Array(args.dropFirst())))
174173
}
175174

176175
// MARK: - Main
@@ -183,21 +182,31 @@ if args.count == 2, args.last == "--version" || args.last == "-v" {
183182
exit(1)
184183
}
185184

186-
// /Applications/Xcode-15.0.0-Beta.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin -> /Applications/Xcode-15.0.0-Beta.app/Contents/Developer/usr/bin
187-
let pathComponents = path.split(separator: ":", maxSplits: 1)
188-
let xcodeBinPath = pathComponents[0]
189-
guard xcodeBinPath.hasSuffix("/Contents/Developer/usr/bin") else {
190-
fputs("error: Xcode based bin PATH not set", stderr)
191-
exit(1)
185+
var swiftcPath: String?
186+
187+
if let toolchainDir = ProcessInfo.processInfo.environment["TOOLCHAIN_DIR"] {
188+
swiftcPath = """
189+
\(toolchainDir)/usr/bin/swiftc
190+
"""
191+
} else {
192+
// /Applications/Xcode-15.0.0-Beta.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin -> /Applications/Xcode-15.0.0-Beta.app/Contents/Developer/usr/bin
193+
let pathComponents = path.split(separator: ":", maxSplits: 1)
194+
let xcodeBinPath = pathComponents[0]
195+
guard xcodeBinPath.hasSuffix("/Contents/Developer/usr/bin") else {
196+
fputs("error: Xcode based bin PATH not set", stderr)
197+
exit(1)
198+
}
199+
// /Applications/Xcode-15.0.0-Beta.app/Contents/Developer/usr/bin -> /Applications/Xcode-15.0.0-Beta.app/Contents/Developer
200+
let developerDir = xcodeBinPath.dropLast(8)
201+
swiftcPath = """
202+
\(developerDir)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc
203+
"""
192204
}
193205

194-
// /Applications/Xcode-15.0.0-Beta.app/Contents/Developer/usr/bin -> /Applications/Xcode-15.0.0-Beta.app/Contents/Developer
195-
let developerDir = xcodeBinPath.dropLast(8)
196-
197-
// TODO: Make this work with custom toolchains
198-
let swiftcPath = """
199-
\(developerDir)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc
200-
"""
206+
guard let swiftcPath else {
207+
fputs("error: Failed to determine swiftc path", stderr)
208+
exit(1)
209+
}
201210

202211
// args.last allows passing in -v (Xcode < 16b3) and --version (>= 16b3)
203212
try exit(runSubProcess(executable: swiftcPath, args: [args.last!]))

xcodeproj/internal/bazel_integration_files/clang.sh

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@ do
1717
break
1818
;;
1919
-v)
20-
# TODO: Make this work with custom toolchains
21-
DEV_DIR_PREFIX=$(awk '{ sub(/.*-isysroot /, ""); sub(/.Contents\/Developer.*/, ""); print}' <<< "${@:1}")
22-
clang="$DEV_DIR_PREFIX/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"
20+
if [[ -n "${TOOLCHAIN_DIR:-}" ]]; then
21+
# Use the toolchain's clang
22+
clang="$TOOLCHAIN_DIR/usr/bin/clang"
23+
else
24+
# Use default Xcode default toolchain if no toolchain is provided
25+
DEV_DIR_PREFIX=$(awk '{ sub(/.*-isysroot /, ""); sub(/.Contents\/Developer.*/, ""); print}' <<< "${@:1}")
26+
clang="$DEV_DIR_PREFIX/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"
27+
fi
28+
2329
"$clang" "${@:1}"
2430
break
2531
;;

xcodeproj/internal/bazel_integration_files/ld

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ do
2222

2323
*.preview-thunk.dylib)
2424
# Pass through for SwiftUI Preview thunk compilation
25-
# TODO: Make this work with custom toolchains
26-
exec "$developer_dir/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" "${passthrough_args[@]}"
25+
if [[ -n "${TOOLCHAIN_DIR:-}" ]]; then
26+
# Use the toolchain's ld
27+
ld="$TOOLCHAIN_DIR/usr/bin/ld"
28+
else
29+
# Use default Xcode default toolchain if no toolchain is provided
30+
ld="$developer_dir/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld"
31+
fi
32+
exec "$ld" "${passthrough_args[@]}"
2733
;;
2834
esac
2935
shift

0 commit comments

Comments
 (0)