我正在尝试制作一个特殊的 .cpp 文件,它有一个 const char* version
,包含包版本,然后在编译后链接到库和可执行文件包裹。库和可执行文件将其引用为 extern
符号,如下所示:
版本.cpp
const char* version=VERSION_STRING;
版本.h
extern const char* version;
库和可执行文件中的代码有
#include "version.h"
现在,问题是可执行文件必须询问库版本的库,但由于符号是 extern
,其实例名称冲突,结果是即使库版本是不同,可执行文件认为它是相同的。
我尝试使用 -fvisibility=hidden
gcc 选项或相应的 __attribute__
来避免这种情况(事实上,它在 glib 中的包装器:G_GNUC_INTERNAL
),它可以工作,但令我困扰的是它根本不可移植,也就是说,我不确定这在 Windows 中如何工作。
所以问题是:在不牺牲可移植性的情况下,有什么更简洁的方法可以在更改版本时避免过多的重新编译并且仍然没有外部可见(给定二进制文件之外)的版本符号?
最佳答案
或者:
- 可执行文件必须向库“询问”版本(在这种情况下,符号不是应该是extern,库应该只提供一些
const char *lib_get_version()
功能) - 或者符号应该是外部的并且对可执行文件直接可见,在这种情况下它应该仅由库提供。也就是说,version.cpp 将链接到库而不是可执行文件,因此库将符号提供给最终的可执行文件。
第一个选项可能是最简单和最便携的。
对于两个版本,可能不一样:
- 创建两个单独的文件,比如
lib_version.cpp
和bin_version.cpp
,导出const char *get_lib_version()
和const char *get_bin_version()
分别 - 将第一个cpp文件编译到lib中,将第二个cpp文件编译到bin中。
如果版本控制是相同的,比如 bin 和 lib 具有不同版本的某些 API,则创建两个 cpp 文件使用的私有(private) header
// header_impl.h #define VERSION_STRING "1.2.3" // lib_version.h const char *get_lib_version(); // lib_version.cpp (linked only in lib) #include <version_impl.h> const char *get_lib_version() { return VERSION_STRING; } // bin_version.h const char *get_bin_version(); // bin_version.cpp (linked only in bin) #include <version_impl.h> const char *get_bin_version() { return VERSION_STRING; }
现在,lib 和 bin 都包含版本的快照,来自 version_impl header ,在它们被编译时。您可以在没有链接器冲突的情况下获得这两个值。
关于c++ - 外部符号的可见性和可移植性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21572184/