mirror of https://github.com/exaloop/codon.git
Update plugins
parent
3914b44a7d
commit
24df3dce6c
|
@ -114,7 +114,7 @@ ProcessResult processSource(const std::vector<const char *> &args) {
|
|||
std::vector<std::string> disabledOptsVec(disabledOpts);
|
||||
auto pm =
|
||||
std::make_unique<codon::ir::transform::PassManager>(isDebug, disabledOptsVec);
|
||||
auto plm = std::make_unique<codon::PluginManager>(pm.get(), isDebug);
|
||||
auto plm = std::make_unique<codon::PluginManager>();
|
||||
|
||||
LOG_TIME("[T] ir-setup = {:.1f}",
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
|
@ -124,22 +124,13 @@ ProcessResult processSource(const std::vector<const char *> &args) {
|
|||
|
||||
// load other plugins
|
||||
for (const auto &dsl : dsls) {
|
||||
auto result = plm->load(dsl);
|
||||
switch (result) {
|
||||
case codon::PluginManager::NONE:
|
||||
break;
|
||||
case codon::PluginManager::NOT_FOUND:
|
||||
codon::compilationError("DSL '" + dsl + "' not found");
|
||||
break;
|
||||
case codon::PluginManager::NO_ENTRYPOINT:
|
||||
codon::compilationError("DSL '" + dsl + "' has no entry point");
|
||||
break;
|
||||
case codon::PluginManager::UNSUPPORTED_VERSION:
|
||||
codon::compilationError("DSL '" + dsl + "' version incompatible");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
std::string errMsg;
|
||||
if (!plm->load(dsl, &errMsg))
|
||||
codon::compilationError(errMsg);
|
||||
}
|
||||
// add all IR passes
|
||||
for (const auto *plugin : *plm) {
|
||||
plugin->dsl->addIRPasses(pm.get(), isDebug);
|
||||
}
|
||||
t = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
|
|
@ -9,28 +9,33 @@
|
|||
|
||||
namespace codon {
|
||||
namespace {
|
||||
bool isVersionSupported(const std::string &versionRange, int major, int minor,
|
||||
int patch) {
|
||||
try {
|
||||
return semver::range::satisfies(semver::version(major, minor, patch), versionRange);
|
||||
} catch (const std::invalid_argument &) {
|
||||
return false;
|
||||
}
|
||||
bool error(const std::string &msg, std::string *errMsg) {
|
||||
if (!msg.empty() && errMsg)
|
||||
*errMsg = msg;
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
typedef std::unique_ptr<DSL> LoadFunc();
|
||||
} // namespace
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
PluginManager::Error PluginManager::load(const std::string &path) {
|
||||
bool PluginManager::load(const std::string &path, std::string *errMsg) {
|
||||
#if __APPLE__
|
||||
const std::string libExt = "dylib";
|
||||
#else
|
||||
const std::string libExt = "so";
|
||||
#endif
|
||||
|
||||
fs::path tomlPath = path;
|
||||
auto tml = toml::parse_file(path);
|
||||
fs::path tomlPath = fs::path(path) / "plugin.toml";
|
||||
toml::parse_result tml;
|
||||
try {
|
||||
tml = toml::parse_file(tomlPath.string());
|
||||
} catch (const toml::parse_error &e) {
|
||||
return error(
|
||||
fmt::format("[toml::parse_file(\"{}\")] {}", tomlPath.string(), e.what()),
|
||||
errMsg);
|
||||
}
|
||||
auto about = tml["about"];
|
||||
auto library = tml["library"];
|
||||
|
||||
|
@ -51,34 +56,45 @@ PluginManager::Error PluginManager::load(const std::string &path) {
|
|||
about["version"].value_or(""), about["url"].value_or(""),
|
||||
about["supported"].value_or(""), stdlibPath};
|
||||
|
||||
if (!isVersionSupported(info.supported, CODON_VERSION_MAJOR, CODON_VERSION_MINOR,
|
||||
CODON_VERSION_PATCH))
|
||||
return Error::UNSUPPORTED_VERSION;
|
||||
bool versionOk = false;
|
||||
try {
|
||||
versionOk = semver::range::satisfies(
|
||||
semver::version(CODON_VERSION_MAJOR, CODON_VERSION_MINOR, CODON_VERSION_PATCH),
|
||||
info.supported);
|
||||
} catch (const std::invalid_argument &e) {
|
||||
return error(fmt::format("[semver::range::satisfies(..., \"{}\")] {}",
|
||||
info.supported, e.what()),
|
||||
errMsg);
|
||||
}
|
||||
if (!versionOk)
|
||||
return error(fmt::format("unsupported version {} (supported: {})", CODON_VERSION,
|
||||
info.supported),
|
||||
errMsg);
|
||||
|
||||
if (!dylibPath.empty()) {
|
||||
std::string errMsg;
|
||||
auto handle =
|
||||
llvm::sys::DynamicLibrary::getPermanentLibrary(dylibPath.c_str(), &errMsg);
|
||||
std::string libLoadErrorMsg;
|
||||
auto handle = llvm::sys::DynamicLibrary::getPermanentLibrary(dylibPath.c_str(),
|
||||
&libLoadErrorMsg);
|
||||
if (!handle.isValid())
|
||||
return Error::NOT_FOUND;
|
||||
return error(
|
||||
fmt::format(
|
||||
"[llvm::sys::DynamicLibrary::getPermanentLibrary(\"{}\", ...)] {}",
|
||||
dylibPath, libLoadErrorMsg),
|
||||
errMsg);
|
||||
|
||||
auto *entry = (LoadFunc *)handle.getAddressOfSymbol("load");
|
||||
if (!entry)
|
||||
return Error::NO_ENTRYPOINT;
|
||||
return error(
|
||||
fmt::format("could not find 'load' in plugin shared library: {}", dylibPath),
|
||||
errMsg);
|
||||
|
||||
auto dsl = (*entry)();
|
||||
plugins.push_back(std::make_unique<Plugin>(std::move(dsl), info, handle));
|
||||
return load(plugins.back()->dsl.get());
|
||||
} else {
|
||||
plugins.push_back(std::make_unique<Plugin>(std::make_unique<DSL>(), info,
|
||||
llvm::sys::DynamicLibrary()));
|
||||
return Error::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
PluginManager::Error PluginManager::load(DSL *dsl) {
|
||||
dsl->addIRPasses(pm, debug);
|
||||
return Error::NONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace codon
|
||||
|
|
|
@ -27,22 +27,12 @@ struct Plugin {
|
|||
/// Manager for loading, applying and unloading plugins.
|
||||
class PluginManager {
|
||||
private:
|
||||
/// pass manager with which to register plugin IR passes
|
||||
ir::transform::PassManager *pm;
|
||||
/// vector of loaded plugins
|
||||
std::vector<std::unique_ptr<Plugin>> plugins;
|
||||
/// true if compiling in debug mode
|
||||
bool debug;
|
||||
|
||||
public:
|
||||
/// Error codes when loading plugins
|
||||
enum Error { NONE = 0, NOT_FOUND, NO_ENTRYPOINT, UNSUPPORTED_VERSION };
|
||||
|
||||
/// Constructs a plugin manager from a given IR pass manager
|
||||
/// @param pm the IR pass manager to register IR passes with
|
||||
/// @param debug true if compining in debug mode
|
||||
explicit PluginManager(ir::transform::PassManager *pm, bool debug = false)
|
||||
: pm(pm), plugins(), debug(debug) {}
|
||||
/// Constructs a plugin manager
|
||||
PluginManager() : plugins() {}
|
||||
|
||||
/// @return iterator to the first plugin
|
||||
auto begin() { return ir::util::raw_ptr_adaptor(plugins.begin()); }
|
||||
|
@ -54,9 +44,10 @@ public:
|
|||
auto end() const { return ir::util::const_raw_ptr_adaptor(plugins.end()); }
|
||||
|
||||
/// Loads the plugin at the given load path.
|
||||
Error load(const std::string &path);
|
||||
/// Loads the given DSL
|
||||
Error load(DSL *dsl);
|
||||
/// @param path path to plugin directory containing "plugin.toml" file
|
||||
/// @param errMsg where to store potential error messages, if non-null
|
||||
/// @return true if the plugin was loaded successfully, false otherwise
|
||||
bool load(const std::string &path, std::string *errMsg = nullptr);
|
||||
};
|
||||
|
||||
} // namespace codon
|
||||
|
|
Loading…
Reference in New Issue