From c5204ba3a04d600e3f073de1cc6757d89871d9cb Mon Sep 17 00:00:00 2001 From: Creeperxie Date: Fri, 28 Feb 2025 21:14:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=94=A8Boost.DLL=E4=BB=8E=E6=8C=87?= =?UTF-8?q?=E5=AE=9A=E7=9B=AE=E5=BD=95=E7=94=A8=E5=8A=A0=E8=BD=BD=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E9=93=BE=E6=8E=A5=E5=BA=93=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +++ README.md | 16 ++++++++++ include/interface.hpp | 11 +++++++ justfile | 5 +++ main.cpp | 61 +++++++++++++++++++++++++++++++++++++ meson.build | 13 ++++++++ plugins/command/meson.build | 4 +++ plugins/command/plugin.cpp | 17 +++++++++++ plugins/command/plugin.hpp | 18 +++++++++++ plugins/meson.build | 1 + 10 files changed, 150 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 include/interface.hpp create mode 100644 justfile create mode 100644 main.cpp create mode 100644 meson.build create mode 100644 plugins/command/meson.build create mode 100644 plugins/command/plugin.cpp create mode 100644 plugins/command/plugin.hpp create mode 100644 plugins/meson.build diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..12c5639 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# clangd的缓存目录 +.cache +# 为clangd创建的compile_commands.json符号链接 +compile_commands.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..cc6a819 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# loader + +将`/usr/lib/loader`和`/usr/local/lib/loader`里的动态链接库作为插件加载! + +可以通过`LOADER_PLUGIN_DIRS`覆盖默认插件目录! +Linux下用`:`分割路径,Windows下用`;`分割路径。 + +为了方便测试,用 +[just](https://github.com/casey/just) +封装了meson! + +```console +$ meson setup builddir +$ just install +$ /usr/local/bin/loader +``` diff --git a/include/interface.hpp b/include/interface.hpp new file mode 100644 index 0000000..562d9b2 --- /dev/null +++ b/include/interface.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include + +class BOOST_SYMBOL_VISIBLE Interface { +public: + virtual const std::string name() const = 0; + virtual ~Interface() {} +}; diff --git a/justfile b/justfile new file mode 100644 index 0000000..dd820b9 --- /dev/null +++ b/justfile @@ -0,0 +1,5 @@ +build: + meson compile -C builddir + +install: build + meson install -C builddir diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..e7391b9 --- /dev/null +++ b/main.cpp @@ -0,0 +1,61 @@ +#include + +#include +#include +#include + +#include +#include +#include + +#include "interface.hpp" + +using std::string; +using std::vector; + +namespace fs = boost::filesystem; +namespace dll = boost::dll; + +const vector &get_plugin_dirs() { + static vector result; + if (!result.empty()) { + return result; + } + +#ifdef _WIN32 + const string delimiter = ";"; +#else + const string delimiter = ":"; +#endif + const char *plugin_dirs = std::getenv("LOADER_PLUGIN_DIRS"); + if (plugin_dirs != nullptr && *plugin_dirs != '\0') { + boost::split(result, plugin_dirs, boost::is_any_of(delimiter)); + } + + if (result.empty()) { + result.push_back("/usr/lib/loader"); + result.push_back("/usr/local/lib/loader"); + } + + return result; +} + +int main() { + const vector &plugin_dirs = get_plugin_dirs(); + for (const auto &plugin_dir : plugin_dirs) { + fs::path plugin_path(plugin_dir); + + if (!fs::is_directory(plugin_path)) { + continue; + } + for (fs::recursive_directory_iterator dir(plugin_path), end; dir != end; ++dir) { + boost::shared_ptr plugin; + plugin = dll::import_symbol( + dir->path(), + "plugin", + dll::load_mode::rtld_lazy + ); + std::cout << "loading plugin: " << plugin->name() << std::endl; + } + } +} diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..26c862c --- /dev/null +++ b/meson.build @@ -0,0 +1,13 @@ +project('loader', 'cpp', + default_options: ['cpp_std=c++20']) + +inc = include_directories('include') +plugin_dep = declare_dependency(include_directories : inc) + +boost_dep = dependency('boost', modules : ['filesystem']) +executable('loader', 'main.cpp', + include_directories : inc, + dependencies : boost_dep, + install : true) + +subdir('plugins') diff --git a/plugins/command/meson.build b/plugins/command/meson.build new file mode 100644 index 0000000..a3ea19b --- /dev/null +++ b/plugins/command/meson.build @@ -0,0 +1,4 @@ +command = shared_library('command', 'plugin.cpp', + dependencies : plugin_dep, + install : true, + install_dir : 'lib/loader') diff --git a/plugins/command/plugin.cpp b/plugins/command/plugin.cpp new file mode 100644 index 0000000..8626494 --- /dev/null +++ b/plugins/command/plugin.cpp @@ -0,0 +1,17 @@ +#include "plugin.hpp" + +#include +#include + +using std::string; + +namespace loader { + +const string Command::name() const { + return "command"; +} +Command::~Command() { + std::cout << "destructing command" << std::endl; +} + +} diff --git a/plugins/command/plugin.hpp b/plugins/command/plugin.hpp new file mode 100644 index 0000000..d8345ce --- /dev/null +++ b/plugins/command/plugin.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "interface.hpp" + +namespace loader { + +class Command : public Interface { +public: + const std::string name() const; + ~Command(); +}; + +extern "C" BOOST_SYMBOL_EXPORT Command plugin; +Command plugin; + +} diff --git a/plugins/meson.build b/plugins/meson.build new file mode 100644 index 0000000..1d860bd --- /dev/null +++ b/plugins/meson.build @@ -0,0 +1 @@ +subdir('command')