这几天研究CMake跨平台项目嘛,用了以下几种编译器:

  1. VS2019(MSVC)

  2. Linux GNU

  3. MinGW

编译之后发现链接动态库发现以下问题:

  1. VS2019中如果直接链接CMakeLists.txt中生成的动态库,编译的时候会发生unreferenced的错误,相同的CMake项目使用MinGW或者Linux GNU进行编译的话则没有问题。

对于这个问题,我回想起了在上一家公司实习的时候,写VS项目的dll要配置导出接口的事情,当时之所以觉得导出接口陌生是因为我在实习前基本上都是用MinGW,所以编译产生的动态库不需要导出接口就可以直接用,当时没有细究这个问题,以为在windows下都是一样的,然后现在就遇到了这个问题。

通过对不同平台以及不同编译器进行测试,我得到了以下结论:

  1. 结论一:MinGW和Linux GNU都是GNU,所以它们编译产生的文件有相似的地方:静态库的后缀名都是.a,但是区别也有,Linux GNU编译动态库产生so,MinGW编译动态库会产生dll(如果使用MSYS2的话确实是编译出so),不过这不重要;
  2. 结论二:MinGW编译动态库除了产生dll外还会产生一个dll.a;
  3. 结论三: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();

MinGW、Linux GNU、MSVC编译和链接动态库的分析的更多相关文章

  1. Linux程序编译链接动态库版本号的问题

    不同版本号的动态库可能会不兼容,假设程序在编译时指定动态库是某个低版本号.执行是用的一个高版本号,可能会导致无法执行. Linux上对动态库的命名採用libxxx.so.a.b.c的格式.当中a代表大 ...

  2. Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别

    昨天在自己的CentOs7.1上写makefile的时候,发现在一个C程序在编译并链接一个已生成好的lib动态库的时候出错.链接命令大概是这样的: [root@typecodes tcpmsg]# g ...

  3. Makefile 编译动态库文件及链接动态库

    本文为原创文章,转载请指明该文链接 文件目录结构如下 dynamiclibapp.c Makefile comm/inc/apue.h comm/errorhandle.c dynamiclib/Ma ...

  4. 在Linux使用GCC编译C语言共享库

    在Linux使用GCC编译C语言共享库 对任何程序员来说库都是必不可少的.所谓的库是指已经编译好的供你使用的代码.它们常常提供一些通用功能,例如链表和二叉树可以用来保存任何数据,或者是一个特定的功能例 ...

  5. gcc编译工具生成动态库和静态库之一----介绍

     1.库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. ...

  6. C++---初识《通过g++ / makefile 编译和调用动态库so文件》(ubuntu)

    C++---初识<通过g++ / makefile  编译和调用动态库so文件>(ubuntu) ------------------------目录------------------- ...

  7. gcc编译工具生成动态库和静态库

    一. 库的分类 1.1. 静态库(.a) 1.1.1. 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大.所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 1. ...

  8. 修改OpenSSL默认编译出的动态库文件名称

    在 Windows 平台上调用动态链接库 dll 文件时,有两种方式:a) 隐式的加载时链接:使用 *.lib (导入库)文件,在 IDE 的链接器相关设置中加入导入库 lib 文件的名称,或在程序中 ...

  9. linux c编程调用系统的动态库时,要使用dlopen等函数吗?

    同问 linux c编程调用系统的动态库时,要使用dlopen等函数吗? 2012-11-27 21:55 提问者: hnwlxyzhl 我来帮他解答 满意回答 2012-12-07 09:08 li ...

  10. 关于Linux静态库和动态库的分析

    关于Linux静态库和动态库的分析 关于Linux静态库和动态库的分析 1.什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可运行代码的二进制形式.能够被操作系统加 ...

随机推荐

  1. redis(14)主从复制

    Redis主从复制 主机数据更新后根据配置和策略, 自动同步到备机的 master/slaver 机制,Master 以写为主,Slave 以读为主,主从复制节点间数据是全量的. 作用: 读写分离,性 ...

  2. centos7中关闭防火墙命令

    1.命令行界面输入命令"systemctl status firewalld.service"并按下回车键. 2.然后在下方可以查看得到"active(running)& ...

  3. cximage函数总结(拷贝)

    链接:   https://blog.csdn.net/flame_007/article/details/89293140 http://t.zoukankan.com/lidabo-p-69233 ...

  4. 将python2.7项目转为Python3问题记录

    将一个Python2.7开发的测试工具项目转化为Python3. 工具:Python自带的2to3.py 将所有.py文件进行转化,生成的python3文件为原文件名,python2文件在后面加.ba ...

  5. Solidity8.0-01

    对应崔棉大师 1-25课程https://www.bilibili.com/video/BV1yS4y1N7yu/?spm_id_from=333.788&vd_source=c81b130b ...

  6. Centos7 MyCat2 安装部署

    部署MyCat2 之前需要搭建好数据库的主从,详看文档:mysql 主次数据库搭建 官网:http://www.mycat.org.cn/ 官方文档: https://www.yuque.com/cc ...

  7. vue部署样式错乱

    1 <style scoped> 2 .el-menu-vertical-demo:not(.el-menu--collapse) { 3 border: none; 4 } 5 .sub ...

  8. vue实现图片上传且实时预览

    <div class="up-img"> <div class="imgList"> <ul> <li v-for=& ...

  9. k8s安装gitlab-ce

    docker镜像打包 根据官方说明:gitlaby docker镜像中已经不包含邮件代理传输,需要重新打包镜像 FROM gitlab/gitlab-ce RUN apt-get update &am ...

  10. iview、render使用方法

    1.<Table size="large" :columns="columns7" :data="labelInput.label" ...