Skip to content

Commit b0f5c39

Browse files
committed
[Driver] Derive '-external-plugin-path'
When the current toolchain is not a Xcode toolchain, derive '-external-plugin-path' poinintng Xcode plugins paths, so we can use plugins in Xcode. rdar://108624128
1 parent 3087afc commit b0f5c39

File tree

3 files changed

+134
-2
lines changed

3 files changed

+134
-2
lines changed

lib/Driver/DarwinToolChains.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,61 @@ static bool findXcodeClangLibPath(const Twine &libName,
212212
return true;
213213
}
214214

215+
static bool findXcodeExecutableDir(llvm::SmallVectorImpl<char> &path) {
216+
assert(path.empty());
217+
218+
auto xcrunPath = llvm::sys::findProgramByName("xcrun");
219+
if (!xcrunPath.getError()) {
220+
// Explicitly ask for the default toolchain so that we don't find a swiftc
221+
// included with an open-source toolchain.
222+
const char *args[] = {"-toolchain", "default", "-f", "swiftc", nullptr};
223+
sys::TaskQueue queue;
224+
queue.addTask(xcrunPath->c_str(), args, /*Env=*/llvm::None,
225+
/*Context=*/nullptr,
226+
/*SeparateErrors=*/true);
227+
queue.execute(nullptr,
228+
[&path](sys::ProcessId PID, int returnCode, StringRef output,
229+
StringRef errors,
230+
sys::TaskProcessInformation ProcInfo,
231+
void *unused) -> sys::TaskFinishedResponse {
232+
if (returnCode == 0) {
233+
output = output.rtrim();
234+
path.append(output.begin(), output.end());
235+
llvm::sys::path::remove_filename(path); // 'swiftc'
236+
}
237+
return sys::TaskFinishedResponse::ContinueExecution;
238+
});
239+
}
240+
241+
return !path.empty();
242+
}
243+
244+
static bool findCurrentSelectedXcodeDir(llvm::SmallVectorImpl<char> &path) {
245+
assert(path.empty());
246+
247+
auto xcodeSelectPath = llvm::sys::findProgramByName("xcode-select");
248+
if (!xcodeSelectPath.getError()) {
249+
const char *args[] = {"-p", nullptr};
250+
sys::TaskQueue queue;
251+
queue.addTask(xcodeSelectPath->c_str(), args, /*Env=*/llvm::None,
252+
/*Context=*/nullptr,
253+
/*SeparateErrors=*/true);
254+
queue.execute(nullptr,
255+
[&path](sys::ProcessId PID, int returnCode, StringRef output,
256+
StringRef errors,
257+
sys::TaskProcessInformation ProcInfo,
258+
void *unused) -> sys::TaskFinishedResponse {
259+
if (returnCode == 0) {
260+
output = output.rtrim();
261+
path.append(output.begin(), output.end());
262+
}
263+
return sys::TaskFinishedResponse::ContinueExecution;
264+
});
265+
}
266+
267+
return !path.empty();
268+
}
269+
215270
static void addVersionString(const ArgList &inputArgs, ArgStringList &arguments,
216271
llvm::VersionTuple version) {
217272
llvm::SmallString<8> buf;
@@ -601,6 +656,46 @@ void toolchains::Darwin::addCommonFrontendArgs(
601656
llvm::opt::ArgStringList &arguments) const {
602657
ToolChain::addCommonFrontendArgs(OI, output, inputArgs, arguments);
603658

659+
// Pass -external-plugin-path if the current toolchain is not a Xcode default
660+
// toolchain.
661+
{
662+
// 'xcode-select -p'
663+
SmallString<256> xcodeDir;
664+
if (findCurrentSelectedXcodeDir(xcodeDir) &&
665+
!StringRef(getDriver().getSwiftProgramPath()).starts_with(xcodeDir)) {
666+
667+
// 'xcrun -f swiftc'
668+
SmallString<256> xcodeExecutableDir;
669+
if (findXcodeExecutableDir(xcodeExecutableDir)) {
670+
using namespace llvm::sys;
671+
672+
// '${toolchain}/usr/bin/swift-plugin-server'
673+
SmallString<256> xcodePluginServerPath(xcodeExecutableDir);
674+
path::append(xcodePluginServerPath, "swift-plugin-server");
675+
if (fs::can_execute(xcodePluginServerPath)) {
676+
677+
// '${toolchain}/usr/lib/swift/host/plugins'
678+
SmallString<256> xcodePluginPath(xcodeExecutableDir);
679+
path::remove_filename(xcodePluginPath); // 'bin'
680+
path::append(xcodePluginPath, "lib", "swift", "host", "plugins");
681+
682+
// '${toolchain}/usr/local/lib/swift/host/plugins'
683+
SmallString<256> xcodeLocalPluginPath(xcodeExecutableDir);
684+
path::remove_filename(xcodeLocalPluginPath); // 'bin'
685+
path::append(xcodeLocalPluginPath, "local");
686+
path::append(xcodeLocalPluginPath, "lib", "swift", "host", "plugins");
687+
688+
arguments.push_back("-external-plugin-path");
689+
arguments.push_back(inputArgs.MakeArgString(xcodePluginPath + "#" +
690+
xcodePluginServerPath));
691+
arguments.push_back("-external-plugin-path");
692+
arguments.push_back(inputArgs.MakeArgString(
693+
xcodeLocalPluginPath + "#" + xcodePluginServerPath));
694+
}
695+
}
696+
}
697+
}
698+
604699
if (auto sdkVersion = getTargetSDKVersion(getTriple())) {
605700
arguments.push_back("-target-sdk-version");
606701
arguments.push_back(inputArgs.MakeArgString(sdkVersion->getAsString()));

lib/Driver/ToolChains.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,6 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
377377
}
378378

379379
// Add plugin path options.
380-
inputArgs.AddAllArgs(arguments, options::OPT_plugin_path);
381-
382380
{
383381
SmallString<64> pluginPath;
384382
auto programPath = getDriver().getSwiftProgramPath();
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// REQUIRES: OS=macosx
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: split-file %s %t
5+
6+
//# Prepare dummy Xcode.app
7+
// RUN: mkdir -p %t/Xcode.app/Contents/Develoer
8+
// RUN: mkdir -p %t/Xcode.app/Contents/Developer/usr/bin
9+
// RUN: mkdir -p %t/Xcode.app/Contents/Developer/usr/lib/swift/host/plugins
10+
// RUN: mkdir -p %t/Xcode.app/Contents/Developer/usr/local/lib/swift/host/plugins
11+
// RUN: touch %t/Xcode.app/Contents/Developer/usr/bin/swiftc
12+
// RUN: touch %t/Xcode.app/Contents/Developer/usr/bin/swift-plugin-server
13+
// RUN: chmod +x %t/Xcode.app/Contents/Developer/usr/bin/swiftc
14+
// RUN: chmod +x %t/Xcode.app/Contents/Developer/usr/bin/swift-plugin-server
15+
16+
//# Prepare dummy 'xcode-select' and 'xcrun'
17+
// RUN: mkdir -p %t/usr/bin
18+
// RUN: sed 's;TMPDIR;%t;' %t/xcode-select > %t/usr/bin/xcode-select
19+
// RUN: sed 's;TMPDIR;%t;' %t/xcrun > %t/usr/bin/xcrun
20+
// RUN: chmod +x %t/usr/bin/xcode-select
21+
// RUN: chmod +x %t/usr/bin/xcrun
22+
23+
// RUN: env PATH=%t/usr/bin %swift_driver_plain -### %t/test.swift | %FileCheck %s
24+
25+
// CHECK: -plugin-path BUILD_DIR/lib/swift/host/plugins
26+
// CHECK-SAME: -plugin-path BUILD_DIR/local/lib/swift/host/plugins
27+
// CHECK-SAME: -external-plugin-path BUILD_DIR/{{[^#]+}}/Xcode.app/Contents/Developer/usr/lib/swift/host/plugins#BUILD_DIR/{{[^#]+}}/Xcode.app/Contents/Developer/usr/bin/swift-plugin-server
28+
// CHECK-SAME: -external-plugin-path BUILD_DIR/{{[^#]+}}/Xcode.app/Contents/Developer/usr/local/lib/swift/host/plugins#BUILD_DIR/{{[^#]+}}/Xcode.app/Contents/Developer/usr/bin/swift-plugin-server
29+
30+
//--- xcrun
31+
#!/bin/sh
32+
echo TMPDIR/Xcode.app/Contents/Developer/usr/bin/swiftc
33+
34+
//--- xcode-select
35+
#!/bin/sh
36+
echo TMPDIR/Xcode.app/Contents/Developer
37+
38+
//--- test.swift
39+
print(1)

0 commit comments

Comments
 (0)