cmake:Windows编译支持HTTPS的curl库及find_package查找CURL时需要注意的问题
Posted 10km
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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::libcurl
的INTERFACE_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不能提供完整的依赖库信息,就会导致在项目编译没问题,但连接的时候会报错找不到符号。
以上是关于cmake:Windows编译支持HTTPS的curl库及find_package查找CURL时需要注意的问题的主要内容,如果未能解决你的问题,请参考以下文章
使用 cmake (windows) 构建时不显示 Qt 资源
vscode 中增加文件后缀类型的支持: 设置cpp支持.cu等后缀