Skip to content

Commit b3024df

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 b3024df

File tree

3 files changed

+136
-2
lines changed

3 files changed

+136
-2
lines changed

lib/Driver/DarwinToolChains.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,63 @@ 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 Clang
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 xcrunPath = llvm::sys::findProgramByName("xcode-select");
248+
if (!xcrunPath.getError()) {
249+
// Explicitly ask for the default toolchain so that we don't find a Clang
250+
// included with an open-source toolchain.
251+
const char *args[] = {"-p", nullptr};
252+
sys::TaskQueue queue;
253+
queue.addTask(xcrunPath->c_str(), args, /*Env=*/llvm::None,
254+
/*Context=*/nullptr,
255+
/*SeparateErrors=*/true);
256+
queue.execute(nullptr,
257+
[&path](sys::ProcessId PID, int returnCode, StringRef output,
258+
StringRef errors,
259+
sys::TaskProcessInformation ProcInfo,
260+
void *unused) -> sys::TaskFinishedResponse {
261+
if (returnCode == 0) {
262+
output = output.rtrim();
263+
path.append(output.begin(), output.end());
264+
}
265+
return sys::TaskFinishedResponse::ContinueExecution;
266+
});
267+
}
268+
269+
return !path.empty();
270+
}
271+
215272
static void addVersionString(const ArgList &inputArgs, ArgStringList &arguments,
216273
llvm::VersionTuple version) {
217274
llvm::SmallString<8> buf;
@@ -601,6 +658,46 @@ void toolchains::Darwin::addCommonFrontendArgs(
601658
llvm::opt::ArgStringList &arguments) const {
602659
ToolChain::addCommonFrontendArgs(OI, output, inputArgs, arguments);
603660

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