Skip to content

[5.9][Macros] Plugin search options group #66678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 13 additions & 24 deletions include/swift/AST/PluginLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,19 @@ class PluginLoader {
void setRegistry(PluginRegistry *newValue);
PluginRegistry *getRegistry();

/// Lookup a library plugin that can handle \p moduleName and return the path
/// to it from `-load-plugin-library`.
/// The path returned can be loaded by 'loadLibraryPlugin' method.
llvm::Optional<std::string>
lookupExplicitLibraryPluginByModuleName(Identifier moduleName);

/// Lookup a library plugin that can handle \p moduleName and return the path
/// to it from `-plugin-path`.
/// The path returned can be loaded by 'loadLibraryPlugin' method.
llvm::Optional<std::string>
lookupLibraryPluginInSearchPathByModuleName(Identifier moduleName);

/// Lookup an executable plugin that is declared to handle \p moduleName
/// module by '-load-plugin-executable'.
/// The path returned can be loaded by 'loadExecutablePlugin' method.
llvm::Optional<StringRef>
lookupExecutablePluginByModuleName(Identifier moduleName);

/// Look for dynamic libraries in paths from `-external-plugin-path` and
/// return a pair of `(library path, plugin server executable)` if found.
/// These paths are valid within the VFS, use `FS.getRealPath()` for their
/// underlying path.
llvm::Optional<std::pair<std::string, std::string>>
lookupExternalLibraryPluginByModuleName(Identifier moduleName);
/// Lookup a plugin that can handle \p moduleName and return the path(s) to
/// it. The path returned can be loaded by 'load(Library|Executable)Plugin()'.
/// The return value is a pair of a "library path" and a "executable path".
///
/// * (libPath: empty, execPath: empty) - plugin not found.
/// * (libPath: some, execPath: empty) - load the library path by
/// 'loadLibraryPlugin()'.
/// * (libPath: empty, execPath: some) - load the executable path by
/// 'loadExecutablePlugin()'.
/// * (libPath: some, execPath: some) - load the executable path by
/// 'loadExecutablePlugin()' and let the plugin load the libPath via IPC.
std::pair<std::string, std::string>
lookupPluginByModuleName(Identifier moduleName);

/// Load the specified dylib plugin path resolving the path with the
/// current VFS. If it fails to load the plugin, a diagnostic is emitted, and
Expand Down
62 changes: 23 additions & 39 deletions include/swift/AST/SearchPathOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "swift/Basic/ArrayRefView.h"
#include "swift/Basic/PathRemapper.h"
#include "swift/Basic/TaggedUnion.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringMap.h"
Expand All @@ -34,7 +35,6 @@ enum class ModuleSearchPathKind {
Framework,
DarwinImplicitFramework,
RuntimeLibrary,
CompilerPlugin,
};

/// A single module search path that can come from different sources, e.g.
Expand Down Expand Up @@ -187,6 +187,26 @@ struct ExternalPluginSearchPathAndServerPath {
std::string ServerPath;
};

namespace PluginSearchOption {
struct LoadPluginLibrary {
std::string LibraryPath;
};
struct LoadPluginExecutable {
std::string ExecutablePath;
std::vector<std::string> ModuleNames;
};
struct PluginPath {
std::string SearchPath;
};
struct ExternalPluginPath {
std::string SearchPath;
std::string ServerPath;
};

using Value = TaggedUnion<LoadPluginLibrary, LoadPluginExecutable, PluginPath,
ExternalPluginPath>;
} // namespace PluginSearchOption

/// Options for controlling search path behavior.
class SearchPathOptions {
/// To call \c addImportSearchPath and \c addFrameworkSearchPath from
Expand Down Expand Up @@ -259,14 +279,6 @@ class SearchPathOptions {
ImportSearchPaths.size() - 1);
}

void addCompilerPluginLibraryPath(StringRef Path, llvm::vfs::FileSystem *FS) {
CompilerPluginLibraryPaths.push_back(Path.str());
Lookup.searchPathAdded(FS, CompilerPluginLibraryPaths.back(),
ModuleSearchPathKind::CompilerPlugin,
/*isSystem=*/false,
CompilerPluginLibraryPaths.size() - 1);
}

/// Add a single framework search path. Must only be called from
/// \c ASTContext::addSearchPath.
void addFrameworkSearchPath(FrameworkSearchPath NewPath,
Expand Down Expand Up @@ -355,27 +367,6 @@ class SearchPathOptions {
Lookup.searchPathsDidChange();
}

void setCompilerPluginLibraryPaths(
std::vector<std::string> NewCompilerPluginLibraryPaths) {
CompilerPluginLibraryPaths = NewCompilerPluginLibraryPaths;
Lookup.searchPathsDidChange();
}

ArrayRef<std::string> getCompilerPluginLibraryPaths() const {
return CompilerPluginLibraryPaths;
}

void setCompilerPluginExecutablePaths(
std::vector<PluginExecutablePathAndModuleNames> &&newValue) {
CompilerPluginExecutablePaths = std::move(newValue);
Lookup.searchPathsDidChange();
}

ArrayRef<PluginExecutablePathAndModuleNames>
getCompilerPluginExecutablePaths() const {
return CompilerPluginExecutablePaths;
}

/// Path(s) to virtual filesystem overlay YAML files.
std::vector<std::string> VFSOverlayFiles;

Expand All @@ -391,15 +382,8 @@ class SearchPathOptions {
/// preference.
std::vector<std::string> RuntimeLibraryPaths;

/// Paths that contain compiler plugins loaded on demand for, e.g.,
/// macro implementations.
std::vector<std::string> PluginSearchPaths;

/// Pairs of external compiler plugin search paths and the corresponding
/// plugin server executables.
/// e.g. {"/path/to/usr/lib/swift/host/plugins",
/// "/path/to/usr/bin/plugin-server"}
std::vector<ExternalPluginSearchPathAndServerPath> ExternalPluginSearchPaths;
/// Plugin search path options.
std::vector<PluginSearchOption::Value> PluginSearchOpts;

/// Don't look in for compiler-provided modules.
bool SkipRuntimeLibraryImportPaths = false;
Expand Down
8 changes: 0 additions & 8 deletions include/swift/Frontend/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,6 @@ class CompilerInvocation {
SearchPathOpts.VFSOverlayFiles = Overlays;
}

void setCompilerPluginLibraryPaths(const std::vector<std::string> &Paths) {
SearchPathOpts.setCompilerPluginLibraryPaths(Paths);
}

ArrayRef<std::string> getCompilerPluginLibraryPaths() {
return SearchPathOpts.getCompilerPluginLibraryPaths();
}

void setExtraClangArgs(const std::vector<std::string> &Args) {
ClangImporterOpts.ExtraArgs = Args;
}
Expand Down
24 changes: 13 additions & 11 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,6 @@ def I : JoinedOrSeparate<["-"], "I">,
def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption, ArgumentIsPath]>,
Alias<I>;

def plugin_path : Separate<["-"], "plugin-path">,
Flags<[FrontendOption, ArgumentIsPath, SwiftAPIExtractOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
HelpText<"Add directory to the plugin search path">;

def external_plugin_path : Separate<["-"], "external-plugin-path">,
Flags<[FrontendOption, ArgumentIsPath, SwiftAPIExtractOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
HelpText<"Add directory to the plugin search path with a plugin server executable">,
MetaVarName<"<path>#<plugin-server-path>">;

def import_underlying_module : Flag<["-"], "import-underlying-module">,
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Implicitly imports the Objective-C half of a module">;
Expand Down Expand Up @@ -1807,15 +1798,26 @@ def nostartfiles:

// END ONLY SUPPORTED IN NEW DRIVER

def plugin_search_Group : OptionGroup<"<plugin search options>">;

def plugin_path : Separate<["-"], "plugin-path">, Group<plugin_search_Group>,
Flags<[FrontendOption, ArgumentIsPath, SwiftAPIExtractOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
HelpText<"Add directory to the plugin search path">;

def external_plugin_path : Separate<["-"], "external-plugin-path">, Group<plugin_search_Group>,
Flags<[FrontendOption, ArgumentIsPath, SwiftAPIExtractOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
HelpText<"Add directory to the plugin search path with a plugin server executable">,
MetaVarName<"<path>#<plugin-server-path>">;

def load_plugin_library:
Separate<["-"], "load-plugin-library">,
Separate<["-"], "load-plugin-library">, Group<plugin_search_Group>,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
HelpText<"Path to a dynamic library containing compiler plugins such as "
"macros">,
MetaVarName<"<path>">;

def load_plugin_executable:
Separate<["-"], "load-plugin-executable">,
Separate<["-"], "load-plugin-executable">, Group<plugin_search_Group>,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
HelpText<"Path to an executable compiler plugins and providing module names "
"such as macros">,
Expand Down
11 changes: 4 additions & 7 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,10 @@ llvm::StringRef swift::getProtocolName(KnownProtocolKind kind) {
}

namespace {
enum class SearchPathKind : uint8_t {
Import = 1 << 0,
Framework = 1 << 1,
CompilerPlugin = 1 << 2
};
enum class SearchPathKind : uint8_t {
Import = 1 << 0,
Framework = 1 << 1,
};
} // end anonymous namespace

using AssociativityCacheType =
Expand Down Expand Up @@ -688,8 +687,6 @@ ASTContext::ASTContext(
getImpl().SearchPathsSet[path] |= SearchPathKind::Import;
for (const auto &framepath : SearchPathOpts.getFrameworkSearchPaths())
getImpl().SearchPathsSet[framepath.Path] |= SearchPathKind::Framework;
for (StringRef path : SearchPathOpts.getCompilerPluginLibraryPaths())
getImpl().SearchPathsSet[path] |= SearchPathKind::CompilerPlugin;

// Register any request-evaluator functions available at the AST layer.
registerAccessRequestFunctions(evaluator);
Expand Down
112 changes: 52 additions & 60 deletions lib/AST/PluginLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
using namespace swift;

void PluginLoader::createModuleToExecutablePluginMap() {
for (auto &arg : Ctx.SearchPathOpts.getCompilerPluginExecutablePaths()) {
// Create a moduleName -> pluginPath mapping.
assert(!arg.ExecutablePath.empty() && "empty plugin path");
StringRef pathStr = Ctx.AllocateCopy(arg.ExecutablePath);
for (auto moduleName : arg.ModuleNames) {
ExecutablePluginPaths[Ctx.getIdentifier(moduleName)] = pathStr;
for (auto &elem : Ctx.SearchPathOpts.PluginSearchOpts) {
if (auto *arg = elem.dyn_cast<PluginSearchOption::LoadPluginExecutable>()) {
// Create a moduleName -> pluginPath mapping.
assert(!arg->ExecutablePath.empty() && "empty plugin path");
StringRef pathStr = Ctx.AllocateCopy(arg->ExecutablePath);
for (auto moduleName : arg->ModuleNames) {
ExecutablePluginPaths[Ctx.getIdentifier(moduleName)] = pathStr;
}
}
}
}
Expand All @@ -46,69 +48,59 @@ PluginRegistry *PluginLoader::getRegistry() {
return Registry;
}

llvm::Optional<std::string>
PluginLoader::lookupExplicitLibraryPluginByModuleName(Identifier moduleName) {
// Look for 'lib${module name}(.dylib|.so)'.
SmallString<64> expectedBasename;
expectedBasename.append("lib");
expectedBasename.append(moduleName.str());
expectedBasename.append(LTDL_SHLIB_EXT);

// Try '-load-plugin-library'.
for (const auto &libPath :
Ctx.SearchPathOpts.getCompilerPluginLibraryPaths()) {
if (llvm::sys::path::filename(libPath) == expectedBasename) {
return libPath;
}
}
return None;
}
std::pair<std::string, std::string>
PluginLoader::lookupPluginByModuleName(Identifier moduleName) {
auto fs = Ctx.SourceMgr.getFileSystem();

llvm::Optional<std::string>
PluginLoader::lookupLibraryPluginInSearchPathByModuleName(
Identifier moduleName) {
// Look for 'lib${module name}(.dylib|.so)'.
SmallString<64> expectedBasename;
expectedBasename.append("lib");
expectedBasename.append(moduleName.str());
expectedBasename.append(LTDL_SHLIB_EXT);

// Try '-plugin-path'.
auto fs = Ctx.SourceMgr.getFileSystem();
for (const auto &searchPath : Ctx.SearchPathOpts.PluginSearchPaths) {
SmallString<128> fullPath(searchPath);
llvm::sys::path::append(fullPath, expectedBasename);
if (fs->exists(fullPath)) {
return std::string(fullPath);
// FIXME: Shared library prefix might be different between platforms.
SmallString<64> pluginLibBasename;
pluginLibBasename.append("lib");
pluginLibBasename.append(moduleName.str());
pluginLibBasename.append(LTDL_SHLIB_EXT);

// FIXME: Should we create a lookup table keyed by module name?
for (auto &entry : Ctx.SearchPathOpts.PluginSearchOpts) {
using namespace PluginSearchOption;
// Try '-load-plugin-library'.
if (auto *val = entry.dyn_cast<LoadPluginLibrary>()) {
if (llvm::sys::path::filename(val->LibraryPath) == pluginLibBasename) {
return {val->LibraryPath, ""};
}
continue;
}
}

return None;
}

Optional<std::pair<std::string, std::string>>
PluginLoader::lookupExternalLibraryPluginByModuleName(Identifier moduleName) {
auto fs = Ctx.SourceMgr.getFileSystem();
// Try '-load-plugin-executable'.
if (auto *v = entry.dyn_cast<LoadPluginExecutable>()) {
auto found = ExecutablePluginPaths.find(moduleName);
if (found != ExecutablePluginPaths.end()) {
return {"", std::string(found->second)};
}
continue;
}

for (auto &pair : Ctx.SearchPathOpts.ExternalPluginSearchPaths) {
SmallString<128> fullPath(pair.SearchPath);
llvm::sys::path::append(fullPath,
"lib" + moduleName.str() + LTDL_SHLIB_EXT);
// Try '-plugin-path'.
if (auto *v = entry.dyn_cast<PluginPath>()) {
SmallString<128> fullPath(v->SearchPath);
llvm::sys::path::append(fullPath, pluginLibBasename);
if (fs->exists(fullPath)) {
return {std::string(fullPath), ""};
}
continue;
}

if (fs->exists(fullPath)) {
return {{std::string(fullPath), pair.ServerPath}};
// Try '-external-plugin-path'.
if (auto *v = entry.dyn_cast<ExternalPluginPath>()) {
SmallString<128> fullPath(v->SearchPath);
llvm::sys::path::append(fullPath, pluginLibBasename);
if (fs->exists(fullPath)) {
return {std::string(fullPath), v->ServerPath};
}
continue;
}
}
return None;
}

Optional<StringRef>
PluginLoader::lookupExecutablePluginByModuleName(Identifier moduleName) {
auto &execPluginPaths = ExecutablePluginPaths;
auto found = execPluginPaths.find(moduleName);
if (found == execPluginPaths.end())
return None;
return found->second;
return {};
}

LoadedLibraryPlugin *PluginLoader::loadLibraryPlugin(StringRef path) {
Expand Down
6 changes: 0 additions & 6 deletions lib/AST/SearchPathOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,6 @@ void ModuleSearchPathLookup::rebuildLookupTable(const SearchPathOptions *Opts,
/*isSystem=*/true, Entry.index());
}

for (auto Entry : llvm::enumerate(Opts->getCompilerPluginLibraryPaths())) {
addFilesInPathToLookupTable(FS, Entry.value(),
ModuleSearchPathKind::CompilerPlugin,
/*isSystem=*/false, Entry.index());
}

State.FileSystem = FS;
State.IsOSDarwin = IsOSDarwin;
State.Opts = Opts;
Expand Down
Loading