CMake构建实战读书笔记06-onnx查找模块
本篇来学习CMake的查找功能,并以onnxruntime库为例,来查找需要的文件。
涉及到的查找指令有:
- find_path:查找路径
- find_library:查找库文件
- find_file:查找文件
- find_package_handle_standard_args:用于在自定义模块中判断结果变量是否都已正确赋值
# 1 onnxruntime简介与下载
## 1.1 onnxruntime简介
ONNX Runtime 是一个跨平台的推理和训练机器学习加速器。
ONNX 运行时推理可以实现更快的客户体验并降低成本,支持来自深度学习框架(如 PyTorch 和 TensorFlow/Keras)的模型,以及经典的机器学习库(如 scikit-learn、LightGBM、XGBoost 等)。ONNX 运行时与不同的硬件、驱动程序和操作系统兼容,并通过利用硬件加速器(如果适用)以及图形优化和转换来提供最佳性能。
ONNX 运行时训练可以通过为现有 PyTorch 训练脚本添加一行代码,从而加快转换器模型的多节点 NVIDIA GPU 上的模型训练时间。
## 1.2 onnxruntime下载
在GitHub中onnxruntime项目的Release页面(https://github.com/microsoft/onnxruntime/releases)下载预编译包,我的是在Ununtu中测试,因此下载Linux版本的包。
下载后解压要测试代码的目录即可。
# 2 代码分析
## 2.1 Findonnxruntime.cmake
这里将此cmake分成两部分来分析,先来看第一部分:
```cmake
find_path(onnxruntime_INCLUDE_DIR onnxruntime_c_api.h
HINTS ENV onnxruntime_ROOT
PATH_SUFFIXES include)
find_library(onnxruntime_LIBRARY
NAMES onnxruntime
HINTS ENV onnxruntime_ROOT
PATH_SUFFIXES lib)
find_file(onnxruntime_VERSION_FILE VERSION_NUMBER
HINTS ENV onnxruntime_ROOT)
if(onnxruntime_VERSION_FILE)
file(STRINGS ${onnxruntime_VERSION_FILE} onnxruntime_VERSION LIMIT_COUNT 1)
endif()
```
- find_path来查找onnxruntime库中的onnxruntime_c_api.h文件路径,并将查找结果存入onnxruntime_INCLUDE_DIR缓存变量中;环境变量onnxruntime_ROOT的值作为候选路径,include目录作为查找子目录
- find_library来查找onnxruntime库中的onnxruntime库文件,并将查找结果存入onnxruntime_LIBRARY缓存变量中;环境变量onnxruntime_ROOT的值作为候选路径,lib目录作为查找子目录
- find_file来查找onnxruntime库的版本号。版本号是在一个名为VERSION_NUMBER的文件中的,将查找的结果存入onnxruntime_VERSION_FILE缓存变量中;onnxruntime_ROOT的值作为候选路径
如果找到了版本号,再通过file指令,来读取其中的版本值,限制读取的行数为1,并将其保存在onnxruntime_VERSION缓存变量中
再来看第二部分:
```cmake
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(onnxruntime
REQUIRED_VARS onnxruntime_LIBRARY onnxruntime_INCLUDE_DIR
VERSION_VAR onnxruntime_VERSION
HANDLE_VERSION_RANGE)
if(onnxruntime_FOUND)
set(onnxruntime_INCLUDE_DIRS ${onnxruntime_INCLUDE_DIR})
set(onnxruntime_LIBRARIES ${onnxruntime_LIBRARY})
add_library(onnxruntime::onnxruntime SHARED IMPORTED)
target_include_directories(onnxruntime::onnxruntime INTERFACE ${onnxruntime_INCLUDE_DIRS})
if(WIN32)
set_target_properties(onnxruntime::onnxruntime PROPERTIES
IMPORTED_IMPLIB "${onnxruntime_LIBRARY}")
else()
set_target_properties(onnxruntime::onnxruntime PROPERTIES
IMPORTED_LOCATION "${onnxruntime_LIBRARY}")
endif()
endif()
```
FindPackageHandleStandardArgs是一个CMake预置的功能模块,通过find_package_handle_standard_args指令,来检查模块中的结果变量是否已经被正确赋值。
- 第一个参数onnxruntime是软件包名
- REQUIRED_VARS是待检查的变量,这里要检查onnxruntime_LIBRARY和onnxruntime_INCLUDE_DIR,即库文件和头文件
- VERSION_VAR是检测版本号,这里要检查onnxruntime_VERSION;若要检查版本号是否满足区间形式,加上参数HANDLE_VERSION_RANGE
经过检查之后,onnxruntime_FOUND会根据检查结果,被赋值为真或假。若为真:
- 设置onnxruntime_INCLUDE_DIRS变量为查找到的头文件目录
- 设置onnxruntime_LIBRARIES变量为查找到的库文件目录
- 调用add_library命令为项目添加动态库
- 调用target_include_directories命令为项目指定头文件目录
- 调用set_target_properties命令设置linux中动态库的导入属性为导致动态库文件自身
## 2.2 main.cpp
测试onnxruntime运行环境是否可用的代码如下:
```cpp
#include <onnxruntime_cxx_api.h>
int main() {
Ort::Env env;
Ort::Session session(env, ORT_TSTR(""), Ort::SessionOptions(nullptr));
return 0;
}
```
测试的内容仅仅是从一个非法的空路径中加载模型文件。
## 2.3 CMakeLists.txt
下面来看下用于构建项目的CMakeLists.txt:
```cmake
cmake_minimum_required(VERSION 3.20)
project(find-onnxruntime)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR};${CMAKE_MODULE_PATH}")
set(CMAKE_CXX_STANDARD 11) # 设置C++标准为11
set(onnx_version 1.10.0) # 根据下载的版本进行设置,本例使用1.10.0版本
# 请下载onnxruntime库的压缩包,并解压至该目录中
if("$ENV{onnxruntime_ROOT}" STREQUAL "")
if(WIN32)
set(ENV{onnxruntime_ROOT} "${CMAKE_CURRENT_LIST_DIR}/onnxruntime-win-x64-${onnx_version}")
elseif(APPLE)
set(ENV{onnxruntime_ROOT} "${CMAKE_CURRENT_LIST_DIR}/onnxruntime-osx-universal2-${onnx_version}")
else()
set(ENV{onnxruntime_ROOT} "${CMAKE_CURRENT_LIST_DIR}/onnxruntime-linux-x64-${onnx_version}")
endif()
endif()
find_package(onnxruntime 1.10) # 指定依赖的最小版本
add_executable(main main.cpp)
target_link_libraries(main onnxruntime::onnxruntime)
target_compile_definitions(main PRIVATE ORT_NO_EXCEPTIONS)
```
开头是指定CMake的最低版本和项目名称
然后通过set指令设置一些变量:
- 设置CMAKE_MODULE_PATH
- 设置CMAKE_CXX_STANDARD为C++11标准
- 设置onnx_version版本
- 设置onnxruntime_ROOT的目录
然后查找版本1.10的onnxruntime包
调用add_executable添加目标,调用target_link_libraries来链接库
# 3 运行结果
在项目目录中新建一个build目录,通过cmake编译
```sh
mkdir build
cd build
camke ..
camke --build .
```
运行结果如下:
# 4 总结
本篇学习了CMake的查找功能,包括查找头文件、库文件、版本号等,并以onnxruntime库为例,来测试CMake的查找功能。 <p>用起来还是好复杂</p>
页:
[1]