我编写的软件带有可以在编译时启用或禁用的插件。在其源文件中,插件通过声明一个静态const注册表变量来注册自己,该变量的构造函数将插件的创建者添加到表中。程序的主要部分不直接调用插件的方法。
例如,在PluginRegistry.cpp
struct PluginDesc {
PluginDesc(std::string_view name,
std::string_view desc): mName(name), mDesc(desc) {
regPlugin(this); // add instance to table
}
std::string_view name;
std::string_view desc;
}
和插件文件PluginA.cpp
static const desc = PluginDesc("pluginA", "a plugin"); // try to register itself
但是我不能创建任何插件,即使Ninja显示它已经编译,除非我包含插件的头文件并使用其中声明的一些函数。这是链接器优化的结果吗?如果我必须包括所有插件的头,它是不可插拔的了。我该怎么修理它?
:如果程序链接插件库为静态链接,创建总是会失败,但动态链接没有问题。
您将插件放置在静态库中,而主程序不包含对该库的引用。默认情况下,库不会被链接。
你有几个选项:
- 将插件放在目标文件而不是库中
- 在链接阶段使用gcc标志
-Wl,--whole-archive
,例如这里 - 将插件放在动态库中,并在运行时加载它们
编辑:主程序包含对库的引用,但不包含对库中所需的对象的引用,因此对象(a.o
)没有链接。