cmake:Windows编译支持HTTPS的curl库及find_package查找CURL时需要注意的问题

curl是一个成熟的HTTP client库,现在windows平台下可以使用cmake在命令行完成编译。

build curl

以下脚本实现Windows CMD下使用cmake及VS2015编译curl

cd curl
mkdir build
cd build
#############################################
# 生成Visual Studio 2015工程文件
cmake .. -G "Visual Studio 14 2015 Win64" ^
	-DCMAKE_INSTALL_PREFIX=J:\curl-vc140-x64 ^
	-DBUILD_SHARED_LIBS=OFF ^
	-DCURL_USE_OPENSSL=ON ^
	-DCMAKE_PREFIX_PATH=J:\skcapmini\dependencies\dist\openssl-1.1.0c\vc140\x64\release\dynamic;J:\skcapmini\dependencies
\dist\zlib-1.2.9\vc140\x64 
# CMAKE_INSTALL_PREFIX 指定安装位置
# BUILD_SHARED_LIBS=OFF 生成curl静态库,如果生成动态库,可以不加此选项
# CURL_USE_OPENSSL=ON 指定使用OPENSSL,如果不需要支持HTTPS,可以不加此选项
# CMAKE_PREFIX_PATH 指定OpenSSL,ZLIB库的安装位置不需要支持HTTPS,可以不加此选项
#############################################
# 编译CURL并安装到CMAKE_INSTALL_PREFIX指定的位置
# 编译Debug版
cmake --build . --target install --config Debug -j 8
# 编译Release版
cmake --build . --target install --config Release -j 8
# - j 8 指定8线程并行编译,以提高编译速度

find_package

上一步已经编译了curl,现在就可以在自己项目的中引用curl库了
一般我们会在cmake脚本中通过find_package查找curl库,

find_package(CURL)

一般来说这样也没问题,但如果你是像博主一样使用自己编译的curl静态库。那么应该以如下方式调用find_package

	# 优先使用CONFIG模式查找
	find_package(CURL CONFIG)
	if(NOT CURL_FOUND)
		# 没找到再用MODULE模式查找
		find_package(CURL)
	endif()

因为cmake本身提供了Module方式查找CURL的脚本,调用find_package时如果不指定CONFIG模式,默认是以MODULE方式调用cmake内置的FindCURL.cmake来查找CURL。
不论是MODULE还是CONFIG模式都能正常找到CURL,你在项目中引用用CURL::libcurl target,能正常编译项目,但如果是要生成动态库或EXE等需要连接的动作时就会报错找不到openssl,zlib,socket通讯相关的函数。因为MODULE模式查找CURL时并没有把CURL静态库所依赖的openssl,zlib等库也加到CURL::libcurl target,所以导致连接失败。
正因为如此,要如上优先使用CONFIG模式查找CURL,没找到再用MODULE模式查找,这样就能确保找到CURL::libcurl target可以在项目正常连接。

CURLTarget.cmake

也许你会想问为什么CONFIG模式能正确找到静态编译的CURL的依赖库?
那么请看看你在第一步编译好的CURL生成的cmake脚本:
curl-vc140-x64\lib\cmake\CURL\CURLTargets.cmake 1
如下是CURLTargets.cmake 中的代码片段

# Create imported target CURL::libcurl
add_library(CURL::libcurl STATIC IMPORTED)

set_target_properties(CURL::libcurl PROPERTIES
  INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "wldap32;winmm;ws2_32;OpenSSL::SSL;OpenSSL::Crypto;ZLIB::ZLIB;advapi32;crypt32"
)

可以看到在CURLTargets.cmake创建了名为CURL::libcurl 的 import target ,并设置了CURL::libcurlINTERFACE_LINK_LIBRARIES 属性为"wldap32;winmm;ws2_32;OpenSSL::SSL;OpenSSL::Crypto;ZLIB::ZLIB;advapi32;crypt32",
这就是定义了CURL::libcurl的所有依赖库。

并且还通过INTERFACE_COMPILE_DEFINITIONS 属性定义了宏CURL_STATICLIB以告诉引用CURL::libcurl的项目使用的是CURL静态库。

那么为什么MODULE模式不能正确找到静态编译的CURL的依赖库?

而cmake内置MODULE方式查找CURL的脚本(cmake-3.17.1-win64-x64/share/cmake-3.17/Modules/FindCURL.cmake)2是按搜索CURL动态库的方式来实现的,在创建CURL::libcurl 时并没有设置INTERFACE_LINK_LIBRARIES ,INTERFACE_COMPILE_DEFINITIONS 属性
只是按常规设置了INTERFACE_INCLUDE_DIRECTORIES(include文件夹位置),IMPORTED_LOCATION_RELEASE(库文件位置)属性
对于CURL动态库,这种方式没有问题,但对于编译的CURL静态库,由于CURL::libcurl imported target不能提供完整的依赖库信息,就会导致在项目编译没问题,但连接的时候会报错找不到符号。


  1. curl-vc140-x64是你指定的安装位置 ↩︎

  2. cmake-3.17.1-win64-x64是你的cmake安装位置 ↩︎

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值