这几天研究CMake跨平台项目嘛,用了以下几种编译器:
-
VS2019(MSVC)
-
Linux GNU
-
MinGW
编译之后发现链接动态库发现以下问题:
- VS2019中如果直接链接CMakeLists.txt中生成的动态库,编译的时候会发生unreferenced的错误,相同的CMake项目使用MinGW或者Linux GNU进行编译的话则没有问题。
对于这个问题,我回想起了在上一家公司实习的时候,写VS项目的dll要配置导出接口的事情,当时之所以觉得导出接口陌生是因为我在实习前基本上都是用MinGW,所以编译产生的动态库不需要导出接口就可以直接用,当时没有细究这个问题,以为在windows下都是一样的,然后现在就遇到了这个问题。
通过对不同平台以及不同编译器进行测试,我得到了以下结论:
- 结论一:MinGW和Linux GNU都是GNU,所以它们编译产生的文件有相似的地方:静态库的后缀名都是.a,但是区别也有,Linux GNU编译动态库产生so,MinGW编译动态库会产生dll(如果使用MSYS2的话确实是编译出so),不过这不重要;
- 结论二:MinGW编译动态库除了产生dll外还会产生一个dll.a;
- 结论三:VS项目的函数如果使用函数导出接口修饰的话,编译动态库也会产生一个与dll同名的lib。
然后编写lua的C包的时候也发现了:
lua在require或者loadlib一个C模块的时候,如果模块是用VS编译产生的话,函数必须具有导出接口,而如果模块是用MinGW编译产生的话,则不需要,也就是说MinGW编译生成动态库时,动态库中的函数默认具有导出接口,这部分我应该开一篇新文,在这里只是题外话。
然后再进行测试,我发现MinGW编译动态库产生的dll可以直接进行动态库链接,结论2中产生的dll.a这个引导库也许是为了和在Windows下使用动态库一致,但是由于MinGW生成动态库时一定会生成dll.a所以我没办法判断MinGW链接动态库的时候是链接dll还是链接dll.a,反正在lua的例子中可以知道MinGW生成的动态库中所有函数都是具有导出接口的;而VS编译动态库产生的dll必须需要有一个引导库文件来帮助完成链接工作。
在cmake中进行动态库链接的话:
target_link_libraries(main testlib_shared)
#这一行代码在MinGW、Linux GNU上cmake产生的makefile是可以通过编译的,而如果testlib_shared中用到的函数有使用函数导出接口修饰的话,cmake产生的VS项目也可以通过编译
当然最后得有一个结论:为了让cmake项目能够跨平台,链接的动态库中使用到的函数应该使用函数导出接口修饰或者直接链接静态库,这样项目才能够在VS上通过编译,而代码中添加函数导出接口修饰的话需要用宏_WIN32去判断是不是VS项目:
#ifndef _WIN32 //如果没有_WIN32的宏,说明不是MSVC项目,自然就不用导出接口
#define TEST_DLL_API
#endif
#ifndef TEST_DLL_API
#define TEST_DLL_API __declspec(dllexport)
#endif
#include <stdio.h>
TEST_DLL_API int hello();
标签:GNU,导出,dll,编译,MinGW,Linux,动态,链接
From: https://www.cnblogs.com/thankvincisdaily/p/17106131.html