本文是 cmake 使用的第八篇,主要介绍如何使用 cmake 导入已经编译好的第三方库。
上一篇的链接为:https://blog.csdn.net/QCZL_CC/article/details/119826435,主要介绍如何设置编译标志,以便于在代码中使用预编译宏。
目录结构如下:
qczl@DESKTOP-HP-ZHAN:~$ tree httpTool
httpTool
├── CMakeLists.txt
├── cJSON
│ ├── cJSON.c
│ └── cJSON.h
├── src
│ ├── common.h
│ ├── debug.h
│ ├── http.c
│ ├── http.h
│ ├── mtime.c
│ ├── mtime.h
│ ├── pstring.c
│ ├── pstring.h
│ ├── safe.c
│ ├── safe.h
│ ├── url_parse.c
│ ├── url_parse.h
│ ├── util.c
│ └── util.h
└── tests
├── get_mac_info.c
├── get_mac_info.h
└── main.c
以上是我写的一个小工具。httpTool/cJSON/ 中的代码我准备编译一个静态库。然后这套代码还依赖第三方库(openssl),接下来我将演示如何用 cmake 语法引入 openssl 库。我将 openssl 安装在了 /home/qczl/openSourceCode/install 目录。
CMakeLists.txt 规则如下:
# cmake 最低版本号
cmake_minimum_required(VERSION 3.14)
# CMake 提供的默认构建类型不包含用于优化的编译器标志。
# 对于某些项目,您可能希望设置默认构建类型,这样您就不必记住设置它。
# cmake 提供的级别有:
# Release - 添加 -O3 -DNDEBUG 标志
# Debug - 添加 -g 标志
# MinSizeRel - 添加 -Os -DNDEBUG
# RelWithDebInfo - 添加 -O2 -g -DNDEBUG 标志
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message("Setting build type to 'RelWithDebInfo' as none was specified.")
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
"MinSizeRel" "RelWithDebInfo")
endif()
# 项目名称
project(http_tools)
################################################
# 导入第三方库信息
################################################
# 自定义一个库,名称为 openssl
add_library(openssl INTERFACE IMPORTED)
# 为 openssl 设置其库文件的所在目录(.so 文件目录)
target_link_directories(openssl
INTERFACE
/home/qczl/openSourceCode/install/lib
)
# 为 openssl 设置其头文件的所在目录(.h 文件目录)
target_include_directories(openssl
INTERFACE
/home/qczl/openSourceCode/install/include
)
# 为 openssl 设置依赖。openssl 有 libssl.so 和 libcrtypto.so 2个动态库文件
target_link_libraries(openssl
INTERFACE
crypto
ssl
)
################################################
# 创建 cSJON 静态库
################################################
# 从库源生成静态库
add_library(cJSON STATIC
cJSON/cJSON.c
)
# 为 cJSON 库添加 -lm
target_link_libraries(cJSON
PUBLIC
m
)
# 为库添加头文件
target_include_directories(cJSON
PUBLIC
${PROJECT_SOURCE_DIR}/cJSON
)
# 创建可执行文件
add_executable(tool
src/http.c
src/mtime.c
src/pstring.c
src/safe.c
src/url_parse.c
src/util.c
tests/get_mac_info.c
tests/main.c
)
# 为可执行文件添加头文件
target_include_directories(tool
PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/tests
)
# 可执行文件链接库
target_link_libraries(tool
PUBLIC
cJSON
openssl # 上面我们自定义的库名称,此处将引入 openssl 依赖的 libssl.so 和 libcrypto.so
)
构建过程:
1:mkdir build 创建该目录的目的是为了将编译产物和源文件分离
2:cd build && cmake .. cmake 后面第一个参数应该是 CMakeLists.txt 文件所在目录。此实例中 CMakeLists.txt 在 build 目录的上一级,所以使用 cmake ..
3:make VERBOSE=1 加上 VERBOSE=1 可以看到编译的详细过程
可以看到最终生成可执行文件时链接了我们设置的第三方库:
我的实验环境是 ubuntu-20.04(WSL) 加 cmake 3.16
然后我遇到了问题。最终生成的可执行文件运行时报错。错误日志如下:提示找不到符号 EVP_idea_cbc
./tool: symbol lookup error: /home/qczl/openSourceCode/install/lib/libssl.so.1.1: undefined symbol: EVP_idea_cbc, version OPENSSL_1_1_0
而我编译出的 openssl 库中是有这个符号的:
然后我 ldd tool 查看我的可执行文件,发现 libcrypto.so.1.1 还是使用的系统目录中的,而不是我在CMakeLists.txt 规则中指定 /home/qczl/openSourceCode/install/lib/ 目录中的。
然后我又在 ubuntu-16.04 和 cmake 3.14 的环境下试了一下,发现是正常的。
如下图所示,在 ubuntu-16.04 和 cmake 3.14 的环境下 libssl 和 libcrypto 都正确的指向了我的自定义目录(/home/qczl/openSourceCode/install/lib/)
再然后我又在 ubuntu-20.04(WSL) 加 cmake 3.14 的环境下 测试了下,现象和 ubuntu-20.04(WSL) 加 cmake 3.16 环境一样。所以和难道是 ubuntu-20.04(WSL) 的问题。