概述
- 从
vcpkg安装了libcurl的静态库,把该静态库拷贝到了项目同级目录,并在项目中引用了这个libcurl.lib
问题
现象
- 编译出
test.exe的时候发现,同时会多出两个文件libcurl.dllzlib1.dll
分析
- 在项目同级目录放进去的是静态库,也在项目中附近库目录指定了静态库所在路径,也在附加依赖项里面指定了
libcurl.lib - 先明确表示使用静态库
- 发现不生成
libcurl.dll了
- 发现不生成
|
1 |
#define CURL_STATICLIB // 告诉头文件你在用静态库 |
- 但是出现了无法解析的外部符号, 类似
__imp__getsockopt__imp_前缀=链接器在找DLL导入版本 的winsock函数,说明:- 可能还在链接旧的动态版
libcurl.lib(没换成静态版) - 而静态版
curl需要手动附加Windows依赖库(动态版会自动处理,静态版不会)
- 于是,附加静态链接所需的
Windows依赖库- 动态
libcurl.dll→ 内部已经链接好winsock,你不用管 - 静态
libcurl.lib→ 所有依赖都要你自己显式告诉链接器
- 动态
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// 项目属性 → 链接器 → 输入 → 附加依赖项 ws2_32.lib wldap32.lib crypt32.lib normaliz.lib 或者 #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "wldap32.lib") #pragma comment(lib, "crypt32.lib") #pragma comment(lib, "normaliz.lib") ws2_32.lib //Winsock2,getsockopt 等 socket 函数 wldap32.lib //LDAP 支持 crypt32.lib //SSL/TLS 证书相关 normaliz.lib //IDN 国际域名支持 |
- 不报
libcurl相关的LNK2001错误了- 但是,还是会生成
zlib1.dll - 说明
libcurl已经静态链接成功了,但项目里还有一个额外的动态zlib引用残留
- 但是,还是会生成
- 用
dumpbin检查依赖- 没有
libcurl.dll / zlib1.dll✅
- 没有
|
1 |
dumpbin /dependents test.exe |
- 验证
zlib.lib- 发现没有输出,说明是静态库
- 如果有
__imp_输出 → 还是导入库 - 结果是没有输出
|
1 |
dumpbin /symbols zlib.lib | findstr "__imp_" |
- 确认
zlib1.dll是真的被链接了,还是别的原因- 输出里没有
zlib1.dll→ 说明exe本身不依赖它,是别的原因 - 输出里有
zlib1.dll→ 说明libcurl.lib本身是用动态zlib编译的 - 可以看到有
zlib1.dll,说明可能libcurl.lib本身编译时用的是动态zlib
- 输出里没有
|
1 |
dumpbin /dependents test.exe |
|
1 2 3 4 5 6 7 8 9 10 |
File Type: EXECUTABLE IMAGE Image has the following dependencies: KERNEL32.dll USER32.dll ADVAPI32.dll zlib1.dll SHLWAPI.dll bcrypt.dll WS2_32.dll CRYPT32.dll |
- 再验证一下
libcurl.lib本身编译时用的是不是动态zlib- 结果是没有看到任何输出
|
1 |
dumpbin /symbols libs\libcurl.lib | findstr "__imp_z" |
|
1 2 3 4 5 |
D:\code_proj\EasyRecycle_proj\EasyUpdate\libs>dumpbin /symbols libs\libcurl.lib | findstr "__imp_z" D:\code_proj\EasyRecycle_proj\EasyUpdate\libs>dumpbin /symbols libcurl.lib | findstr "__imp_z" D:\code_proj\EasyRecycle_proj\EasyUpdate\libs>cd ../Release |
- 换个思路,看看
exe具体从zlib1.dll导入了哪些函数- 发现确实导入了
- 说明链接器找的
inflate实现不是来自静态zlib.lib
|
1 |
dumpbin /imports test.exe |
|
1 2 3 4 5 6 7 8 9 10 |
zlib1.dll 4A633C Import Address Table 4C96A0 Import Name Table 0 time date stamp 0 Index of first forwarder reference 45 inflateInit2_ 46 inflateInit_ 4A inflateReset2 42 inflateEnd 3C inflate |
- 在链接器选项里临时加上
/VERBOSE:LIB,重新编译:- 让链接器自己说出在找哪个
- 观察到确实在搜索
zlib1,而且路径是vcpkg的路径
|
1 2 |
项目属性 → 链接器 → 命令行 → 附加选项 /VERBOSE:LIB |
- 于是在
vs项目设置里面关掉了使用vcpkg - 问题解决了
其他
MT和静态库
/MT只管MSVC运行时(CRT)的链接方式,和 库本身是静态还是动态无关- 所以说,并不是在项目里设置了
mt,项目就会自动链接所有的静态库
- 所以说,并不是在项目里设置了
声明:本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ libcurl简述11/20
- ♥ Windows开发相关简记二:exe和dll双形态09/30
- ♥ COM组件_303/07
- ♥ Macos编译x86_64相关二09/05
- ♥ WindowsHOOK相关03/17
- ♥ COM组件_403/07