diff --git a/include/swift/AST/PluginLoader.h b/include/swift/AST/PluginLoader.h index d2ad612116882..5ef31029af38f 100644 --- a/include/swift/AST/PluginLoader.h +++ b/include/swift/AST/PluginLoader.h @@ -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 - 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 - 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 - 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> - 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 + 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 diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index 74bc7d175af11..be355091b29d6 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -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" @@ -34,7 +35,6 @@ enum class ModuleSearchPathKind { Framework, DarwinImplicitFramework, RuntimeLibrary, - CompilerPlugin, }; /// A single module search path that can come from different sources, e.g. @@ -187,6 +187,26 @@ struct ExternalPluginSearchPathAndServerPath { std::string ServerPath; }; +namespace PluginSearchOption { +struct LoadPluginLibrary { + std::string LibraryPath; +}; +struct LoadPluginExecutable { + std::string ExecutablePath; + std::vector ModuleNames; +}; +struct PluginPath { + std::string SearchPath; +}; +struct ExternalPluginPath { + std::string SearchPath; + std::string ServerPath; +}; + +using Value = TaggedUnion; +} // namespace PluginSearchOption + /// Options for controlling search path behavior. class SearchPathOptions { /// To call \c addImportSearchPath and \c addFrameworkSearchPath from @@ -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, @@ -355,27 +367,6 @@ class SearchPathOptions { Lookup.searchPathsDidChange(); } - void setCompilerPluginLibraryPaths( - std::vector NewCompilerPluginLibraryPaths) { - CompilerPluginLibraryPaths = NewCompilerPluginLibraryPaths; - Lookup.searchPathsDidChange(); - } - - ArrayRef getCompilerPluginLibraryPaths() const { - return CompilerPluginLibraryPaths; - } - - void setCompilerPluginExecutablePaths( - std::vector &&newValue) { - CompilerPluginExecutablePaths = std::move(newValue); - Lookup.searchPathsDidChange(); - } - - ArrayRef - getCompilerPluginExecutablePaths() const { - return CompilerPluginExecutablePaths; - } - /// Path(s) to virtual filesystem overlay YAML files. std::vector VFSOverlayFiles; @@ -391,15 +382,8 @@ class SearchPathOptions { /// preference. std::vector RuntimeLibraryPaths; - /// Paths that contain compiler plugins loaded on demand for, e.g., - /// macro implementations. - std::vector 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 ExternalPluginSearchPaths; + /// Plugin search path options. + std::vector PluginSearchOpts; /// Don't look in for compiler-provided modules. bool SkipRuntimeLibraryImportPaths = false; diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index 04d85157cc19e..501fab05d5071 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -192,14 +192,6 @@ class CompilerInvocation { SearchPathOpts.VFSOverlayFiles = Overlays; } - void setCompilerPluginLibraryPaths(const std::vector &Paths) { - SearchPathOpts.setCompilerPluginLibraryPaths(Paths); - } - - ArrayRef getCompilerPluginLibraryPaths() { - return SearchPathOpts.getCompilerPluginLibraryPaths(); - } - void setExtraClangArgs(const std::vector &Args) { ClangImporterOpts.ExtraArgs = Args; } diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 67f1946e722c4..f8b9ed474bfea 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -304,15 +304,6 @@ def I : JoinedOrSeparate<["-"], "I">, def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption, ArgumentIsPath]>, Alias; -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<"#">; - def import_underlying_module : Flag<["-"], "import-underlying-module">, Flags<[FrontendOption, NoInteractiveOption]>, HelpText<"Implicitly imports the Objective-C half of a module">; @@ -1807,15 +1798,26 @@ def nostartfiles: // END ONLY SUPPORTED IN NEW DRIVER +def plugin_search_Group : OptionGroup<"">; + +def plugin_path : Separate<["-"], "plugin-path">, Group, + Flags<[FrontendOption, ArgumentIsPath, SwiftAPIExtractOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>, + HelpText<"Add directory to the plugin search path">; + +def external_plugin_path : Separate<["-"], "external-plugin-path">, Group, + Flags<[FrontendOption, ArgumentIsPath, SwiftAPIExtractOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>, + HelpText<"Add directory to the plugin search path with a plugin server executable">, + MetaVarName<"#">; + def load_plugin_library: - Separate<["-"], "load-plugin-library">, + Separate<["-"], "load-plugin-library">, Group, Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>, HelpText<"Path to a dynamic library containing compiler plugins such as " "macros">, MetaVarName<"">; def load_plugin_executable: - Separate<["-"], "load-plugin-executable">, + Separate<["-"], "load-plugin-executable">, Group, Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>, HelpText<"Path to an executable compiler plugins and providing module names " "such as macros">, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 0a2b122d693b4..5d680e4732ddb 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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 = @@ -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); diff --git a/lib/AST/PluginLoader.cpp b/lib/AST/PluginLoader.cpp index efae0a6ca2a2c..1bdfc95b1e7ef 100644 --- a/lib/AST/PluginLoader.cpp +++ b/lib/AST/PluginLoader.cpp @@ -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()) { + // 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; + } } } } @@ -46,69 +48,59 @@ PluginRegistry *PluginLoader::getRegistry() { return Registry; } -llvm::Optional -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 +PluginLoader::lookupPluginByModuleName(Identifier moduleName) { + auto fs = Ctx.SourceMgr.getFileSystem(); -llvm::Optional -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()) { + if (llvm::sys::path::filename(val->LibraryPath) == pluginLibBasename) { + return {val->LibraryPath, ""}; + } + continue; } - } - - return None; -} -Optional> -PluginLoader::lookupExternalLibraryPluginByModuleName(Identifier moduleName) { - auto fs = Ctx.SourceMgr.getFileSystem(); + // Try '-load-plugin-executable'. + if (auto *v = entry.dyn_cast()) { + 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()) { + 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()) { + 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 -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) { diff --git a/lib/AST/SearchPathOptions.cpp b/lib/AST/SearchPathOptions.cpp index 4e110ccacd70d..88a1cb56e0548 100644 --- a/lib/AST/SearchPathOptions.cpp +++ b/lib/AST/SearchPathOptions.cpp @@ -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; diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 23823632051e1..4dad18fe954b6 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -236,8 +236,6 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddAllArgs(arguments, options::OPT_I); inputArgs.AddAllArgs(arguments, options::OPT_F, options::OPT_Fsystem); inputArgs.AddAllArgs(arguments, options::OPT_vfsoverlay); - inputArgs.AddAllArgs(arguments, options::OPT_plugin_path); - inputArgs.AddAllArgs(arguments, options::OPT_external_plugin_path); inputArgs.AddLastArg(arguments, options::OPT_AssertConfig); inputArgs.AddLastArg(arguments, options::OPT_autolink_force_load); @@ -325,8 +323,6 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddLastArg(arguments, options::OPT_enable_bare_slash_regex); inputArgs.AddLastArg(arguments, options::OPT_enable_experimental_cxx_interop); inputArgs.AddLastArg(arguments, options::OPT_cxx_interoperability_mode); - inputArgs.AddLastArg(arguments, options::OPT_load_plugin_library); - inputArgs.AddLastArg(arguments, options::OPT_load_plugin_executable); inputArgs.AddLastArg(arguments, options::OPT_enable_builtin_module); // Pass on any build config options @@ -376,9 +372,9 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddAllArgs(arguments, options::OPT_file_compilation_dir); } - // Add plugin path options. - inputArgs.AddAllArgs(arguments, options::OPT_plugin_path); - + // Specify default plugin search path options after explicitly specified + // options. + inputArgs.AddAllArgs(arguments, options::OPT_plugin_search_Group); { SmallString<64> pluginPath; auto programPath = getDriver().getSwiftProgramPath(); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 5db7f2c63d38b..a4aefb13282a7 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1553,18 +1553,56 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, } Opts.setFrameworkSearchPaths(FrameworkSearchPaths); - for (const Arg *A : Args.filtered(OPT_plugin_path)) { - Opts.PluginSearchPaths.push_back(resolveSearchPath(A->getValue())); - } - - for (const Arg *A : Args.filtered(OPT_external_plugin_path)) { - // '#'. - // FIXME: '#' can be used in the paths. - StringRef dylibPath; - StringRef serverPath; - std::tie(dylibPath, serverPath) = StringRef(A->getValue()).split('#'); - Opts.ExternalPluginSearchPaths.push_back( - {resolveSearchPath(dylibPath), resolveSearchPath(serverPath)}); + // All plugin search options, i.e. '-load-plugin-library', + // '-load-plugin-executable', '-plugin-path', and '-external-plugin-path' + // are grouped, and plugins are searched by the order of these options. + // e.g. For '-plugin-path A -load-plugin-library B/libModule.dylib', if + // 'A/libModule.dylib' exists, it's used. + for (const Arg *A : Args.filtered(OPT_plugin_search_Group)) { + switch (A->getOption().getID()) { + case OPT_load_plugin_library: { + Opts.PluginSearchOpts.emplace_back(PluginSearchOption::LoadPluginLibrary{ + resolveSearchPath(A->getValue())}); + break; + } + case OPT_load_plugin_executable: { + // '#' where the module names are + // comma separated. + StringRef path; + StringRef modulesStr; + std::tie(path, modulesStr) = StringRef(A->getValue()).rsplit('#'); + std::vector moduleNames; + for (auto name : llvm::split(modulesStr, ',')) { + moduleNames.emplace_back(name); + } + if (path.empty() || moduleNames.empty()) { + Diags.diagnose(SourceLoc(), diag::error_load_plugin_executable, + A->getValue()); + } else { + Opts.PluginSearchOpts.emplace_back( + PluginSearchOption::LoadPluginExecutable{resolveSearchPath(path), + std::move(moduleNames)}); + } + break; + } + case OPT_plugin_path: { + Opts.PluginSearchOpts.emplace_back( + PluginSearchOption::PluginPath{resolveSearchPath(A->getValue())}); + break; + } + case OPT_external_plugin_path: { + // '#'. + // FIXME: '#' can be used in the paths. + StringRef dylibPath; + StringRef serverPath; + std::tie(dylibPath, serverPath) = StringRef(A->getValue()).split('#'); + Opts.PluginSearchOpts.emplace_back(PluginSearchOption::ExternalPluginPath{ + resolveSearchPath(dylibPath), resolveSearchPath(serverPath)}); + break; + } + default: + llvm_unreachable("unhandled plugin search option"); + } } for (const Arg *A : Args.filtered(OPT_L)) { @@ -1626,36 +1664,6 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, // is called before setTargetTriple() and parseArgs(). // TODO: improve the handling of RuntimeIncludePath. - std::vector CompilerPluginLibraryPaths( - Opts.getCompilerPluginLibraryPaths()); - for (const Arg *A : Args.filtered(OPT_load_plugin_library)) { - CompilerPluginLibraryPaths.push_back(resolveSearchPath(A->getValue())); - } - Opts.setCompilerPluginLibraryPaths(CompilerPluginLibraryPaths); - - std::vector CompilerPluginExecutablePaths( - Opts.getCompilerPluginExecutablePaths()); - for (const Arg *A : Args.filtered(OPT_load_plugin_executable)) { - // 'A' is '#' where the module names are - // comma separated. - StringRef path; - StringRef modulesStr; - std::tie(path, modulesStr) = StringRef(A->getValue()).rsplit('#'); - std::vector moduleNames; - for (auto name : llvm::split(modulesStr, ',')) { - moduleNames.emplace_back(name); - } - if (path.empty() || moduleNames.empty()) { - Diags.diagnose(SourceLoc(), diag::error_load_plugin_executable, - A->getValue()); - } else { - CompilerPluginExecutablePaths.push_back( - {resolveSearchPath(path), std::move(moduleNames)}); - } - } - Opts.setCompilerPluginExecutablePaths( - std::move(CompilerPluginExecutablePaths)); - return false; } diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index d947ca9ec1df1..dcb454b27b76b 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -202,30 +202,35 @@ SerializationOptions CompilerInvocation::computeSerializationOptions( serializationOpts.ExtraClangOptions = getClangImporterOptions().ExtraArgs; } - // '-plugin-path' options. - for (const auto &path : getSearchPathOptions().PluginSearchPaths) { - serializationOpts.PluginSearchPaths.push_back(path); - } - // '-external-plugin-path' options. - for (const ExternalPluginSearchPathAndServerPath &pair : - getSearchPathOptions().ExternalPluginSearchPaths) { - serializationOpts.ExternalPluginSearchPaths.push_back( - pair.SearchPath + "#" + - pair.ServerPath); - } - // '-load-plugin-library' options. - for (const auto &path : - getSearchPathOptions().getCompilerPluginLibraryPaths()) { - serializationOpts.CompilerPluginLibraryPaths.push_back(path); - } - // '-load-plugin-executable' options. - for (const PluginExecutablePathAndModuleNames &pair : - getSearchPathOptions().getCompilerPluginExecutablePaths()) { - std::string optStr = pair.ExecutablePath + "#"; - llvm::interleave( - pair.ModuleNames, [&](auto &name) { optStr += name; }, - [&]() { optStr += ","; }); - serializationOpts.CompilerPluginExecutablePaths.push_back(optStr); + // FIXME: Preserve the order of these options. + for (auto &elem : getSearchPathOptions().PluginSearchOpts) { + // '-plugin-path' options. + if (auto *arg = elem.dyn_cast()) { + serializationOpts.PluginSearchPaths.push_back(arg->SearchPath); + continue; + } + + // '-external-plugin-path' options. + if (auto *arg = elem.dyn_cast()) { + serializationOpts.ExternalPluginSearchPaths.push_back( + arg->SearchPath + "#" + arg->ServerPath); + continue; + } + + // '-load-plugin-library' options. + if (auto *arg = elem.dyn_cast()) { + serializationOpts.CompilerPluginLibraryPaths.push_back(arg->LibraryPath); + continue; + } + + // '-load-plugin-executable' options. + if (auto *arg = elem.dyn_cast()) { + std::string optStr = arg->ExecutablePath + "#"; + llvm::interleave( + arg->ModuleNames, [&](auto &name) { optStr += name; }, + [&]() { optStr += ","; }); + serializationOpts.CompilerPluginExecutablePaths.push_back(optStr); + } } serializationOpts.DisableCrossModuleIncrementalInfo = diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index e4e611a5f218a..14d3dfa315f36 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -345,25 +345,8 @@ CompilerPluginLoadRequest::evaluate(Evaluator &evaluator, ASTContext *ctx, std::string libraryPath; std::string executablePath; - - // '-load-plugin-libarary'. - if (auto found = loader.lookupExplicitLibraryPluginByModuleName(moduleName)) { - libraryPath = found.value(); - } - // '-load-plugin-executable'. - else if (auto found = loader.lookupExecutablePluginByModuleName(moduleName)) { - executablePath = found->str(); - } - // '-plugin-path'. - else if (auto found = - loader.lookupLibraryPluginInSearchPathByModuleName(moduleName)) { - libraryPath = found.value(); - } - // '-external-plugin-path'. - else if (auto found = - loader.lookupExternalLibraryPluginByModuleName(moduleName)) { - std::tie(libraryPath, executablePath) = found.value(); - } + std::tie(libraryPath, executablePath) = + loader.lookupPluginByModuleName(moduleName); if (!executablePath.empty()) { if (LoadedExecutablePlugin *executablePlugin = diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 6b952b96295ae..26706913945b8 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -205,8 +205,7 @@ void SerializedModuleLoaderBase::collectVisibleTopLevelModuleNamesImpl( }); return None; } - case ModuleSearchPathKind::RuntimeLibrary: - case ModuleSearchPathKind::CompilerPlugin: { + case ModuleSearchPathKind::RuntimeLibrary: { // Look for: // (Darwin OS) $PATH/{name}.swiftmodule/{arch}.{extension} // (Other OS) $PATH/{name}.{extension} @@ -660,8 +659,7 @@ bool SerializedModuleLoaderBase::findModule( switch (searchPath->getKind()) { case ModuleSearchPathKind::Import: - case ModuleSearchPathKind::RuntimeLibrary: - case ModuleSearchPathKind::CompilerPlugin: { + case ModuleSearchPathKind::RuntimeLibrary: { isFramework = false; // On Apple platforms, we can assume that the runtime libraries use diff --git a/test/Macros/macro_mixedpluginpath.swift b/test/Macros/macro_mixedpluginpath.swift new file mode 100644 index 0000000000000..ea559a4db9732 --- /dev/null +++ b/test/Macros/macro_mixedpluginpath.swift @@ -0,0 +1,74 @@ +// REQUIRES: swift_swift_parser + +// RUN: %empty-directory(%t/src) +// RUN: %empty-directory(%t/plugins) +// RUN: %empty-directory(%t/plugins_local) + +// RUN: split-file %s %t/src + + +//#-- Prepare the macro dylib plugin. +// RUN: %host-build-swift \ +// RUN: -swift-version 5 \ +// RUN: -emit-library -o %t/plugins/%target-library-name(MacroDefinition) \ +// RUN: -module-name MacroDefinition \ +// RUN: %t/src/MacroDefinition.float.swift \ +// RUN: -g -no-toolchain-stdlib-rpath + +//#-- Prepare the macro dylib plugin. +// RUN: %host-build-swift \ +// RUN: -swift-version 5 \ +// RUN: -emit-library -o %t/plugins_local/%target-library-name(MacroDefinition) \ +// RUN: -module-name MacroDefinition \ +// RUN: %t/src/MacroDefinition.int.swift \ +// RUN: -g -no-toolchain-stdlib-rpath + +//#-- Check '-load-plugin-library' takes precedence over '-plugin-path'. +// RUN: %target-swift-frontend -typecheck -verify -swift-version 5 \ +// RUN: -load-plugin-library %t/plugins_local/%target-library-name(MacroDefinition) \ +// RUN: -plugin-path %t/plugins \ +// RUN: %t/src/test.swift + +//#-- Different argument order changes the search order, hence fail. +// RUN: not %target-swift-frontend -typecheck -verify -swift-version 5 \ +// RUN: -plugin-path %t/plugins \ +// RUN: -load-plugin-library %t/plugins_local/%target-library-name(MacroDefinition) \ +// RUN: %t/src/test.swift + +//--- test.swift +@freestanding(expression) macro constInt() -> Int = #externalMacro(module: "MacroDefinition", type: "ConstMacro") + +func foo() { + let _: Int = #constInt + // If 'MacroDefinition.float.swift' (in '-pluing-path') is loaded, type checking this fails because it expands to '4.2' which is a float literal. +} + +//--- MacroDefinition.float.swift +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros + +public struct ConstMacro: ExpressionMacro { + public static func expansion( + of macro: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) -> ExprSyntax { + + return "4.2" + } +} + +//--- MacroDefinition.int.swift +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros + +public struct ConstMacro: ExpressionMacro { + public static func expansion( + of macro: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) -> ExprSyntax { + + return "42" + } +} diff --git a/test/Macros/macro_plugin_searchorder.swift b/test/Macros/macro_plugin_searchorder.swift index 786630a832eed..562144fa86b48 100644 --- a/test/Macros/macro_plugin_searchorder.swift +++ b/test/Macros/macro_plugin_searchorder.swift @@ -50,39 +50,42 @@ //#-- Expect -load-plugin-library // RUN: %target-build-swift %t/src/test.swift \ -// RUN: -o %t/main1 \ // RUN: -module-name test \ +// RUN: -load-plugin-library %t/lib/tmp/%target-library-name(MacroDefinition) \ // RUN: -plugin-path %t/lib/plugins \ // RUN: -external-plugin-path %t/external#%swift-plugin-server \ -// RUN: -load-plugin-library %t/lib/tmp/%target-library-name(MacroDefinition) \ -// RUN: -load-plugin-executable %t/libexec/MacroDefinitionPlugin#MacroDefinition +// RUN: -load-plugin-executable %t/libexec/MacroDefinitionPlugin#MacroDefinition \ +// RUN: -o %t/main1 // RUN: %target-codesign %t/main1 // RUN: %target-run %t/main1 | %FileCheck --check-prefix=CHECK_LOAD_PLUGIN_LIBRARY %s //#-- Expect -load-plugin-executable // RUN: %target-build-swift %t/src/test.swift \ -// RUN: -o %t/main2 \ // RUN: -module-name test \ +// RUN: -load-plugin-executable %t/libexec/MacroDefinitionPlugin#MacroDefinition \ // RUN: -plugin-path %t/lib/plugins \ // RUN: -external-plugin-path %t/external#%swift-plugin-server \ -// RUN: -load-plugin-executable %t/libexec/MacroDefinitionPlugin#MacroDefinition +// RUN: -o %t/main2 // RUN: %target-codesign %t/main2 // RUN: %target-run %t/main2 | %FileCheck --check-prefix=CHECK_LOAD_PLUGIN_EXECUTABLE %s //#-- Expect -plugin-path // RUN: %target-build-swift %t/src/test.swift \ -// RUN: -o %t/main3 \ // RUN: -module-name test \ // RUN: -plugin-path %t/lib/plugins \ -// RUN: -external-plugin-path %t/external#%swift-plugin-server +// RUN: -load-plugin-library %t/lib/tmp/%target-library-name(MacroDefinition) \ +// RUN: -external-plugin-path %t/external#%swift-plugin-server \ +// RUN: -o %t/main3 // RUN: %target-codesign %t/main3 // RUN: %target-run %t/main3 | %FileCheck --check-prefix=CHECK_PLUGIN_PATH %s //#-- Expect -external-plugin-path // RUN: %target-build-swift %t/src/test.swift \ -// RUN: -o %t/main4 \ // RUN: -module-name test \ -// RUN: -external-plugin-path %t/external#%swift-plugin-server +// RUN: -external-plugin-path %t/external#%swift-plugin-server \ +// RUN: -plugin-path %t/lib/plugins \ +// RUN: -load-plugin-executable %t/libexec/MacroDefinitionPlugin#MacroDefinition \ +// RUN: -o %t/main4 // RUN: %target-codesign %t/main4 // RUN: %target-run %t/main4 | %FileCheck --check-prefix=CHECK_EXTERNAL_PLUGIN_PATH %s diff --git a/test/Macros/serialize_plugin_search_paths.swift b/test/Macros/serialize_plugin_search_paths.swift index 95e901895e42d..ef9c5c8d7ee88 100644 --- a/test/Macros/serialize_plugin_search_paths.swift +++ b/test/Macros/serialize_plugin_search_paths.swift @@ -15,7 +15,6 @@ // CHECK: -plugin-path: {{.*}}plugins // CHECK: -plugin-path: {{.*}}plugins // CHECK: -plugin-path: {{.*}}plugins -// CHECK: -plugin-path: {{.*}}plugins // CHECK: -external-plugin-path: {{.*}}plugins#{{.*}}swift-plugin-server // CHECK: -load-plugin-library: {{.*}}MacroDefinition.{{dylib|so|dll}} // CHECK: -load-plugin-executable: {{.*}}mock-plugin#TestPlugin diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 92b7131214fd1..769fac49fa59e 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -4506,15 +4506,12 @@ int main(int argc, char *argv[]) { } } - for (auto path : options::PluginPath) { - InitInvok.getSearchPathOptions().PluginSearchPaths.push_back(path); - } if (!options::LoadPluginLibrary.empty()) { std::vector paths; for (auto path: options::LoadPluginLibrary) { - paths.push_back(path); + InitInvok.getSearchPathOptions().PluginSearchOpts.emplace_back( + PluginSearchOption::LoadPluginLibrary{path}); } - InitInvok.getSearchPathOptions().setCompilerPluginLibraryPaths(paths); } if (!options::LoadPluginExecutable.empty()) { std::vector pairs; @@ -4526,10 +4523,14 @@ int main(int argc, char *argv[]) { for (auto name : llvm::split(modulesStr, ',')) { moduleNames.emplace_back(name); } - pairs.push_back({std::string(path), std::move(moduleNames)}); + InitInvok.getSearchPathOptions().PluginSearchOpts.emplace_back( + PluginSearchOption::LoadPluginExecutable{std::string(path), + std::move(moduleNames)}); } - - InitInvok.getSearchPathOptions().setCompilerPluginExecutablePaths(std::move(pairs)); + } + for (auto path : options::PluginPath) { + InitInvok.getSearchPathOptions().PluginSearchOpts.emplace_back( + PluginSearchOption::PluginPath{path}); } // Process the clang arguments last and allow them to override previously