MinGW、Linux GNU、MSVC编译和链接动态库的分析
这几天研究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();
MinGW、Linux GNU、MSVC编译和链接动态库的分析的更多相关文章
- Linux程序编译链接动态库版本号的问题
不同版本号的动态库可能会不兼容,假设程序在编译时指定动态库是某个低版本号.执行是用的一个高版本号,可能会导致无法执行. Linux上对动态库的命名採用libxxx.so.a.b.c的格式.当中a代表大 ...
- Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别
昨天在自己的CentOs7.1上写makefile的时候,发现在一个C程序在编译并链接一个已生成好的lib动态库的时候出错.链接命令大概是这样的: [root@typecodes tcpmsg]# g ...
- Makefile 编译动态库文件及链接动态库
本文为原创文章,转载请指明该文链接 文件目录结构如下 dynamiclibapp.c Makefile comm/inc/apue.h comm/errorhandle.c dynamiclib/Ma ...
- 在Linux使用GCC编译C语言共享库
在Linux使用GCC编译C语言共享库 对任何程序员来说库都是必不可少的.所谓的库是指已经编译好的供你使用的代码.它们常常提供一些通用功能,例如链表和二叉树可以用来保存任何数据,或者是一个特定的功能例 ...
- gcc编译工具生成动态库和静态库之一----介绍
1.库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. ...
- C++---初识《通过g++ / makefile 编译和调用动态库so文件》(ubuntu)
C++---初识<通过g++ / makefile 编译和调用动态库so文件>(ubuntu) ------------------------目录------------------- ...
- gcc编译工具生成动态库和静态库
一. 库的分类 1.1. 静态库(.a) 1.1.1. 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大.所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 1. ...
- 修改OpenSSL默认编译出的动态库文件名称
在 Windows 平台上调用动态链接库 dll 文件时,有两种方式:a) 隐式的加载时链接:使用 *.lib (导入库)文件,在 IDE 的链接器相关设置中加入导入库 lib 文件的名称,或在程序中 ...
- linux c编程调用系统的动态库时,要使用dlopen等函数吗?
同问 linux c编程调用系统的动态库时,要使用dlopen等函数吗? 2012-11-27 21:55 提问者: hnwlxyzhl 我来帮他解答 满意回答 2012-12-07 09:08 li ...
- 关于Linux静态库和动态库的分析
关于Linux静态库和动态库的分析 关于Linux静态库和动态库的分析 1.什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可运行代码的二进制形式.能够被操作系统加 ...
随机推荐
- 通过反射机制简化 JDBC ResultSet 实体类的注入
提出问题 查询完某个表之后,一般都是把结果的每一个字段注入到一个实体类中.比如,数据库 users 表,查询出来的结果注入到 User 实体类中. 通过 while 遍历 ResultSet,把字段对 ...
- PostGIS之空间索引
1. 概述 PostGIS 是PostgreSQL数据库一个空间数据库扩展,它添加了对地理对象的支持,允许在 SQL 中运行空间查询 PostGIS官网:About PostGIS | PostGIS ...
- LeetCode-2104 子数组范围和
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/sum-of-subarray-ranges 题目描述 给你一个整数数组 nums .nums 中 ...
- element导航栏组件封装递归调用
element导航栏组件封装递归调用: https://blog.csdn.net/qq_21271511/article/details/109889934
- VUE学习-渲染函数
渲染函数 x-template 引入外面组件文件写法 <template> <h1 v-if="level === 1"> <slot>< ...
- js区分图片加载中和加载完成状态
var _ent = document.getElementById("test"); if (_ent.complete) { //图片已经加载完成 _ent.stop(); } ...
- CentOS 镜像官网下载链接
CentOS 镜像官网下载链接: https://www.centos.org/download/mirrors/ http://mirrors.aliyun.com/centos/ https:// ...
- Jenkins添加代理节点
新建linux节点 新建节点 配置远程工作目录和登录方式SSH 如果没有密码需要手动添加(需要在对应的slave节点存在的用户) 保存即可. 验证节点 新建任务 New Item 选择要运行的节点(这 ...
- redis底层数据结构之跳表(skiplist)
跳表(跳跃表, skiplist) 跳跃表(skiplist)是用于有序元素序列快速搜索查找的数据结构,跳表是一个随机化的数据结构,实质是一种可以进行二分查找的.具有层次结构的有序链表 跳表在原有的有 ...
- kafak学习总结
高可用 多副本机制: 主副本和从副本,从副本只负责同步主副本数据,只有主副本进行读写. 高并发 网络结构设计 多路复用 多selector -> 多线程-> 多队列 高性能 写 把数据先写 ...