为了避免 A/B 问题:最终我想要做的是找出我拥有的 wayfire 插件二进制文件(在我的情况下是 firedecor)是否已使用足够新的 wayfire 版本进行编译,以便插件支持的 API/ABI 版本(可以通过其导出的内容检索getWayfireVersion
)与今天的 wayfire 版本相匹配,或者是否必须根据新的 wayfire 版本重新编译插件。
为了找出我的插件共享库编译时所依据的 wayfire api/abi 版本,以便最终执行所需的比较,我编写了一个简短的 C++ 程序。它dlopen
是插件共享库,并尝试调用并将其输出与当前版本的包含的 wayfire 标头检索到getWayfireVersion()
的值进行比较:WAYFIRE_API_ABI_VERSION
#include <wayfire/plugin.hpp>
#include <errno.h>
#include <dlfcn.h>
#include <stdio.h>
#include <inttypes.h>
int main(int argc, char* argv[]) {
void *handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
if (handle == NULL) {
fprintf(stderr, "dlopen failed: %s\n", dlerror());
return 1;
}
uint32_t (*version_func)() = (uint32_t (*)())dlsym(handle, "getWayfireVersion");
if (version_func == NULL) {
perror("dlsym failed");
dlclose(handle);
return 1;
}
int32_t plugin_abi_version = version_func();
if (WAYFIRE_API_ABI_VERSION != plugin_abi_version) {
fprintf(stderr, "API/ABI version mismatch:\n");
fprintf(stderr, "wayfire is: %" PRIu32 "\n", WAYFIRE_API_ABI_VERSION);
fprintf(stderr, "plugin is: %" PRIu32 "\n", plugin_abi_version);
dlclose(handle);
return 1;
}
fprintf(stderr, "wayfire is: %" PRIu32 "\n", WAYFIRE_API_ABI_VERSION);
fprintf(stderr, "plugin is: %" PRIu32 "\n", plugin_abi_version);
dlclose(handle);
return 0;
}
我编译它:
$ g++ test.cc -o test -Wall -ldl $(pkg-config --cflags pixman-1) -DWLR_USE_UNSTABLE
但是当我运行它时我得到:
$ ./test /usr/lib/aarch64-linux-gnu/wayfire/libfiredecor.so
dlopen failed: /usr/lib/aarch64-linux-gnu/wayfire/libfiredecor.so: undefined symbol: _ZTIN2wf3txn20transaction_object_tE
观察libfiredecor.so
确实nm
发现,这_ZTIN2wf3txn20transaction_object_tE
是未定义的:
0000000000045b70 V _ZTIN2wf28view_geometry_changed_signalE
00000000000457a8 V _ZTIN2wf36view_decoration_state_updated_signalE
U _ZTIN2wf3txn20transaction_object_tE
00000000000457b8 V _ZTIN2wf3txn22new_transaction_signalE
0000000000045988 V _ZTIN2wf5scene17render_instance_tE
但既然它是一个插件,那就没问题了,因为它应该从加载它的可执行文件中获取符号。现在我的问题是:如何修改我的test.cc
或我的g++
调用,以便test
二进制文件包含 typeinfo wf::txn::transaction_object_t
?
使用虚拟值应该足够了,因为getWayfireVersion
我的插件定义如下:
uint32_t getWayfireVersion() { return WAYFIRE_API_ABI_VERSION; }
更改RTLD_NOW
为RTLD_LAZY
indlopen
只会造成执行时不显示错误消息,dlopen
而仅稍后调用该函数时才显示。
我联系了 wayfire 开发人员征求他们的意见,但他们也不知道:https://github.com/WayfireWM/wayfire/issues/2499
解决此问题的另一种方法是在构建插件时对 wayfire api/abi 版本进行硬编码,并将结果存储在文件中,稍后查询该文件并将其与 的当前值进行比较WAYFIRE_API_ABI_VERSION
。但由于该解决方案不是最佳的,而且这已经变成了一个 c++ 问题,所以我在这里寻求帮助。也许有人知道如何让我的test.cc
包含插件所需的(虚拟)符号,谢谢!
编辑1:
您可以通过下载并解压 Debian 包来获取您自己的 libfiredecor.so 版本,如下所示:
$ curl http://ftp.debian.org/debian/pool/main/r/reform-firedecor/reform-firedecor_2023-10-23-5_amd64.deb | dpkg-deb --fsys-tarfile - | tar --to-stdout -x ./usr/lib/x86_64-linux-gnu/wayfire/libfiredecor.so > libfiredecor.so
编辑2:
使用选项编译插件时,程序test.cc
成功运行。这是正确的解决方案吗?gold
--weak-unresolved-symbols