前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >cmake:Windows编译支持HTTPS的curl库及find_package查找CURL时需要注意的问题

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

作者头像
10km
发布2022-04-13 11:08:11
1.5K0
发布2022-04-13 11:08:11
举报
文章被收录于专栏:10km的专栏10km的专栏

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

build curl

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

代码语言:javascript
复制
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库,

代码语言:javascript
复制
find_package(CURL)

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

代码语言:javascript
复制
	# 优先使用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 中的代码片段

代码语言:javascript
复制
# 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安装位置 ↩︎
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-02-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • build curl
  • find_package
  • CURLTarget.cmake
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档