Files
swift-mirror/include/swift/AST/PluginLoader.h
Steven Wu f96b81975a [Caching][Macro] Make macro plugin options cacheable
Currently, the macro plugin options are included as cache key and the
absolute path of the plugin executable and library will affect cache
hit, even the plugin itself is identical.

Using the new option `-resolved-plugin-validation` flag, the macro
plugin paths are remapped just like the other paths during dependency
scanning. `swift-frontend` will unmap to its original path during the
compilation, make sure the content hasn't changed, and load the plugin.
It also hands few other corner cases for macro plugins:

* Make sure the plugin options in the swift module is prefix mapped.
* Make sure the remarks of the macro loading is not cached, as the
  mesasge includes the absolute path of the plugin, and is not
  cacheable.

rdar://148465899
(cherry picked from commit 3d38d0dd56)
2025-04-10 16:52:15 -07:00

105 lines
3.8 KiB
C++

//===--- PluginLoader.h -----------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_PLUGIN_LOADER_H
#define SWIFT_AST_PLUGIN_LOADER_H
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/PluginRegistry.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include <optional>
namespace swift {
class ASTContext;
/// Compiler plugin loader tied to an ASTContext. This is responsible for:
/// * Find plugins based on the module name
/// * Load plugins resolving VFS paths
/// * Track plugin dependencies
class PluginLoader {
public:
struct PluginEntry {
StringRef libraryPath;
StringRef executablePath;
};
private:
/// Plugin registry. Lazily populated by get/setRegistry().
/// NOTE: Do not reference this directly. Use getRegistry().
PluginRegistry *Registry = nullptr;
/// `Registry` storage if this owns it.
std::unique_ptr<PluginRegistry> OwnedRegistry = nullptr;
ASTContext &Ctx;
DependencyTracker *DepTracker;
const bool disableSandbox;
/// Map a module name to an plugin entry that provides the module.
std::optional<llvm::DenseMap<swift::Identifier, PluginEntry>> PluginMap;
/// Get or lazily create and populate 'PluginMap'.
llvm::DenseMap<swift::Identifier, PluginEntry> &getPluginMap();
/// Resolved plugin path remappings.
std::vector<std::string> PathRemap;
public:
PluginLoader(ASTContext &Ctx, DependencyTracker *DepTracker,
std::optional<std::vector<std::string>> Remap = std::nullopt,
bool disableSandbox = false)
: Ctx(Ctx), DepTracker(DepTracker), disableSandbox(disableSandbox) {
if (Remap)
PathRemap = std::move(*Remap);
}
void setRegistry(PluginRegistry *newValue);
PluginRegistry *getRegistry();
/// 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.
const PluginEntry &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
/// returns a nullptr.
/// NOTE: This method is idempotent. If the plugin is already loaded, the same
/// instance is simply returned.
llvm::Expected<CompilerPlugin *> getInProcessPlugins();
/// Launch the specified executable plugin path resolving the path with the
/// current VFS. If it fails to load the plugin, a diagnostic is emitted, and
/// returns a nullptr.
/// NOTE: This method is idempotent. If the plugin is already loaded, the same
/// instance is simply returned.
llvm::Expected<CompilerPlugin *> loadExecutablePlugin(llvm::StringRef path);
/// Add the specified plugin associated with the module name to the dependency
/// tracker if needed.
void recordDependency(const PluginEntry &plugin, Identifier moduleName);
};
} // namespace swift
#endif // SWIFT_AST_PLUGIN_LOADER_H