cmake详细教程(二)
admin
2024-01-20 18:30:04
0

一、参考资料

CMake 入门实战 | HaHack

Cmake入门和MindsporeLite Cmake文件分析 | 摸黑干活 (fazzie-key.cool)

GitHub - wzpan/cmake-demo: 《CMake入门实战》源码

User Interaction Guide — CMake 3.20.6 Documentation

Home · Wiki · CMake / Community · GitLab (kitware.com)

cmake的一些小经验 - 驭风万里无垠 - C++博客 (cppblog.com)

二、相关介绍

1. CMake预定义变量

CMake中常用的预定义变量

项目示例

D:\MyDocuments\cache\Demo>tree
.
├─build
│  ├─bin
│  └─lib
├─example
└─src├─base├─http└─net

PROJECT_NAME

通过PROJECT指定的项目名称:

project(Demo)

PROJECT_SOURCE_DIR

工程的根目录,项目示例中的Demo目录。

PROJECT_BINARY_DIR

执行cmake命令的目录,一般是在build目录,在此目录执行cmake ..

CMAKE_CURRENT_SOURCE_DIR

当前CMakeLists.txt文件所在目录。

CMAKE_CURRENT_BINARY_DIR

编译目录,可使用ADD_SUBDIRECTORY来修改此变量。

# 添加cmake执行子目录
ADD_SUBDIRECTORY(example)

EXECUTABLE_OUTPUT_PATH

二进制可执行文件输出位置。

# 设置可执行文件的输出路径为 build/bin
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

LIBRARY_OUTPUT_PATH

库文件输出位置。

set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

常用系统信息变量

liulinjun@LAPTOP-4DTD5D42:~$ cmake --version
cmake version 3.11.2

CMAKE_MAJOR_VERSION: cmake的主版本号cmake version 3.11.2中的3
CMAKE_MINOR_VERSION: cmake的次版本号cmake version 3.11.2中的11
CMAKE_PATCH_VERSION: cmake的补丁等级cmake version 3.11.2中的2

CMAKE_SYSTEM: 系统名称,带版本号;
CMAKE_SYSTEM_NAME: 系统名称,不带版本号;
CMAKE_SYSTEM_VERSION: 系统版本号;
CMAKE_SYSTEM_PROCESSOR: 处理器名称;

BUILD_SHARED_LIBS

默认的库编译方式(shared or static),默认为static,一般在ADD_LIBRARY时直接指定编译库的类型。

CMAKE_C_FLAGS

设置C编译选项。

SET(CMAKE_C_FLAGS_PUBLIC "-mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -ffunction-sections -mno-unaligned-access -fno-aggressive-loop-optimizations -mapcs-frame -rdynamic")
SET(CMAKE_C_FLAGS_DEBUG "-Wall -ggdb3 -DNM_DEBUG ${CMAKE_C_FLAGS_PUBLIC}")
SET(CMAKE_C_FLAGS_RELEASE  "-Wall -O3  ${CMAKE_C_FLAGS_PUBLIC}")

CMAKE_CXX_FLAGS

设置C++编译选项。

  • CMAKE_CXX_FLAGS_DEBUG: 设置编译类型为Debug时的编译选项;
  • CMAKE_CXX_FLAGS_RELEASE: 设置编译类型为Release时的编译选项;

CMAKE_CXX_COMPILER

设置C++编译器。

# 设置C++编译器为g++
set(CMAKE_CXX_COMPILER "g++")
# 设置标准库版本为c++17 并开启警告
set(CMAKE_CXX_FLAGS "-std=c++17 -Wall")
# 设置Debug模式下,不开启优化,开启调试,生成更详细的gdb调试信息
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -ggdb")
# 设置Release模式下,开启最高级优化
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

2. CMake语法

STREQUAL

STREQUAL 用于比较字符串,相同返回 true

if(NOT("${X86_64_SIMD}" STREQUAL "sse" OR "${X86_64_SIMD}" STREQUAL "avx" OR "${X86_64_SIMD}" STREQUAL "avx512"))set(KERNEL_SRC_SSE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/fp32/convolution_im2col_sse_fp32.cc${CMAKE_CURRENT_SOURCE_DIR}/fp32/matmul_fp32_sse.cc${CMAKE_CURRENT_SOURCE_DIR}/fp32/convolution_winograd_sse_fp32.cc)list(REMOVE_ITEM KERNEL_SRC ${KERNEL_SRC_SSE_FILE})
endif()

3. 缓存变量

CMake语法—缓存变量(Cache Variable)

3.1 CMake缓存变量

  • Normal Variable,普通变量,相当于一个局部变量。在同一个CMake工程中使用,会有作用域限制或区分。

  • Cache Variable,缓存变量,相当于一个全局变量。在同一个CMake工程中任何地方都可以使用。

3.2 定义格式

set( ... CACHE   [FORCE])

参数解释

  • variable:变量名称;
  • value:变量值列表;
  • CACHE:cache变量的标志;
  • type:变量类型,取决于变量的值。类型分为:BOOL、FILEPATH、PATH、STRING、INTERNAL;
  • docstring:必须是字符串,作为变量概要说明;
  • FORCE:强制选项,强制修改变量值;

示例

set(MSLITE_REGISTRY_DEVICE "off" CACHE STRING "Compile Mindspore Lite that supports specific devices, currently supported devices: Hi3516D/Hi3519A/Hi3559A/SD3403")

3. 注意事项

  1. 缓存变量,本质是全局变量,可以把缓存变量当做C、C++中的全局变量理解即可。类比法理解与体会,更易于学习与应用。
  2. 缓存变量,都会存储在CMakeCache.txt文件中,当你确认某个变量是缓存变量时,理论上你一定可以在CMakeCache.txt中找到此变量的记录项。
  3. CMakeCache.txt文件中,还有很多默认的缓存变量,可自行查看与分析研究。
  4. 缓存变量发生问题,一定记得先删除build目录下的CMakeCache.txt文件,然后重新配置项目。

4. 环境变量(ENV)

CMake语法—环境变量(Environment Variable)

4.1 定义格式

set(ENV{} [])

参数解释

  • ENV:环境变量标志性前缀;
  • variable:变量名称;
  • value:变量值;

示例

# 定义环境变量
set(ENV{CMAKE_PATH} "F:/cmake")# 判断CMAKE_PATH环境变量是否定义
if(DEFINED ENV{CMAKE_PATH})message("CMAKE_PATH_1: $ENV{CMAKE_PATH}")
else()message("NOT DEFINED CMAKE_PATH VARIABLES")
endif()

4.2 CMakeLists.txt示例

cmake_minimum_required(VERSION 3.18)# 设置工程名称
set(PROJECT_NAME KAIZEN)# 设置工程版本号
set(PROJECT_VERSION "1.0.0.10" CACHE STRING "默认版本号")# 工程定义
project(${PROJECT_NAME}LANGUAGES CXX CVERSION ${PROJECT_VERSION}
)# 打印开始日志
message(STATUS "\n########## BEGIN_TEST_ENV_VARIABLE")# 判断JAVA_HOME变量是否定义
if(DEFINED ENV{JAVA_HOME})message("JAVA_HOME: $ENV{JAVA_HOME}")
else()message("NOT DEFINED JAVA_HOME VARIABLES")
endif()# 定义环境变量
set(ENV{CMAKE_PATH} "F:/cmake")# 判断CMAKE_PATH环境变量是否定义
if(DEFINED ENV{CMAKE_PATH})message("CMAKE_PATH_1: $ENV{CMAKE_PATH}")
else()message("NOT DEFINED CMAKE_PATH VARIABLES")
endif()# 定义测试函数,在函数中新定义环境变量
function(test_env_variable)# 访问环境变量CMAKE_PATHmessage("CMAKE_PATH_2: $ENV{CMAKE_PATH}")# 函数内定义环境变量set(ENV{CMAKE_FUNC} "F:/cmake/dir")# 判断CMAKE_FUNC环境变量是否定义if(DEFINED ENV{CMAKE_FUNC})message("CMAKE_FUNC_1: $ENV{CMAKE_FUNC}")else()message("NOT DEFINED CMAKE_FUNC_1 VARIABLES")endif()
endfunction()# 调用函数
test_env_variable()# 判断CMAKE_FUNC环境变量是否定义
if(DEFINED ENV{CMAKE_FUNC})message("CMAKE_FUNC_2: $ENV{CMAKE_FUNC}")
else()message("NOT DEFINED CMAKE_FUNC_2 VARIABLES")
endif()# 如果没有参数值
set(ENV{CMAKE_FUNC})# 判断CMAKE_FUNC环境变量是否定义
if(DEFINED ENV{CMAKE_FUNC})message("CMAKE_FUNC_3: $ENV{CMAKE_FUNC}")
else()message("NOT DEFINED CMAKE_FUNC_3 VARIABLES")
endif()# 定义测试宏,在函数中新定义环境变量
macro(test_env_var)# 访问环境变量CMAKE_PATHmessage("CMAKE_PATH_3: $ENV{CMAKE_PATH}")# 宏内定义环境变量set(ENV{CMAKE_MACRO} "F:/cmake/macro")# 判断CMAKE_MACRO环境变量是否定义if(DEFINED ENV{CMAKE_MACRO})message("CMAKE_MACRO_1: $ENV{CMAKE_MACRO}")else()message("NOT DEFINED CMAKE_MACRO_1 VARIABLES")endif()
endmacro()# 调用宏
test_env_var()# 判断CMAKE_MACRO环境变量是否定义
if(DEFINED ENV{CMAKE_MACRO})message("CMAKE_MACRO_2: $ENV{CMAKE_MACRO}")
else()message("NOT DEFINED CMAKE_MACRO_2 VARIABLES")
endif()# 如果多个参数值
set(ENV{CMAKE_FILE} "F:/cmake/cmake1.txt" "F:/cmake/cmake2.txt")# 判断CMAKE_FILE环境变量是否定义
if(DEFINED ENV{CMAKE_FILE})message("CMAKE_FILE: $ENV{CMAKE_FILE}")
else()message("NOT DEFINED CMAKE_FILE VARIABLES")
endif()# 打印结束日志
message(STATUS "########## END_TEST_ENV_VARIABLE\n")

输出结果

-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.17763.
-- The CXX compiler identification is MSVC 19.0.24245.0
-- The C compiler identification is MSVC 19.0.24245.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
--
########## BEGIN_TEST_ENV_VARIABLE
JAVA_HOME: C:\Program Files\Java\jdk1.8.0_201
CMAKE_PATH_1: F:/cmake
CMAKE_PATH_2: F:/cmake
CMAKE_FUNC_1: F:/cmake/dir
CMAKE_FUNC_2: F:/cmake/dir
NOT DEFINED CMAKE_FUNC_3 VARIABLES
CMAKE_PATH_3: F:/cmake
CMAKE_MACRO_1: F:/cmake/macro
CMAKE_MACRO_2: F:/cmake/macro
CMake Warning (dev) at CMakeLists.txt:98 (set):Only the first value argument is used when setting an environment variable.Argument 'F:/cmake/cmake2.txt' and later are unused.
This warning is for project developers.  Use -Wno-dev to suppress it.CMAKE_FILE: F:/cmake/cmake1.txt
-- ########## END_TEST_ENV_VARIABLE-- Configuring done
-- Generating done
-- Build files have been written to: F:/learn_cmake/build
请按任意键继续. . .

5. gcc/g++编译(无CMake)

5.1 单文件编译

对于单文件"hello.cpp",
生成hello(hello.exe)所需要执行的bash命令:

gcc -v -o hello hello.c

5.2 多文件编译(无依赖)

但当涉及多文件编译时,我们的命令会十分复杂,比如一个main.cpp文件依赖于Foo1.cpp,Foo2.cpp,…Foo10,我们需要先将这10个文件编译成.o文件,再将各.o文件和main.o进行链接,代码如下:

g++ -std=c++17 -O2 -o Foo1.o -c Foo1.cpp
g++ -std=c++17 -O2 -o Foo2.o -c Foo2.cpp
g++ -std=c++17 -O2 -o Foo3.o -c Foo3.cpp
g++ -std=c++17 -O2 -o Foo4.o -c Foo4.cpp
g++ -std=c++17 -O2 -o Foo5.o -c Foo5.cpp
g++ -std=c++17 -O2 -o Foo6.o -c Foo6.cpp
g++ -std=c++17 -O2 -o Foo7.o -c Foo7.cpp
g++ -std=c++17 -O2 -o Foo8.o -c Foo8.cpp
g++ -std=c++17 -O2 -o Foo9.o -c Foo9.cpp
g++ -std=c++17 -O2 -o Foo10.o -c Foo10.cpp
g++ -std=c++17 -O2 -o main.o -c main.cpp
g++ -std=c++17 -O2 main.o Foo1.o Foo2.o Foo3.o Foo4.o Foo5.o Foo6.o Foo7.o Foo8.o Foo9.o Foo10.o -o main

5.3 多文件编译(有依赖)

上述编译过程还算简单,因为各子文件还不相互依赖,但如果子文件有相互依赖关系,比如foo1.cpp依赖于foo10.cpp我们编译的顺序有必须更改,在文件数目更大的工程中,一行一行输入命令进行编译是不现实的,所以我们引入了Makefile,对于上述编译任务,我们的MakeFile如下,我们只需输入make一句命令即可完成编译。

COMPILER = g++ -std=c++17 -O2 -I./include  
OBJECTS = Foo1.o Foo2.o Foo3.o Foo4.o Foo5.o Foo6.o Foo7.o Foo8.o Foo9.o Foo10.o main.o
TARGET = main$(TARGET): $(OBJECTS)$(COMPILER) -o $@ $^ -lprotobuf
$(OBJECTS): %.o: %.cpp$(COMPILER) -o $@ -c $<
$(DEPENDENCIES): %.d: %.cpp$(COMPILER) -o $@ -MM $

5.4 总结

Makefile 规定了一套编译规则,使用什么编译器,编译器使用什么样的编译选项,每个文件都有什么依赖关系。在编译的时候,能够直接根据 makefile 来确定哪些文件依赖于其他的哪些文件,从而把编译顺序、需不需要重新编译以及链接都自动检测出来。在Linux环境下,MakeFile本身可以看做一个shell脚本。

三、CMake编译

1. 问题引入

既然我们有了MakeFile,又为什么需要Cmake工具?对于不同环境下的编译,有着多种Make工具,例如 GNU Make ,QT 的 qmake ,微软的 MS nmake,BSD Make(pmake),Makepp,等等。这些 Make 工具遵循着不同的规范和标准,所执行的 Makefile 格式也千差万别。这样就带来了一个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用上面的 Make 工具,就得为每一种标准写一次 Makefile,这将是一件让人抓狂的工作。

CMake 就是针对上面问题所设计的工具:它首先允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。显然,CMake 是一个比上述几种 make 更高级的编译配置工具。一些使用 CMake 作为项目架构系统的知名开源项目有 VTK、ITK、KDE、OpenCV、OSG 等 [1]。

对于深度学习框架而言,跨平台是一件非常重要的事,因为深度学习模型可能在不同的环境下运行,可能是x86的Linux或者Windows,也可能是ARM,涉及到跨平台交叉编译。

2. CMake流程

在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:

  1. 编写 CMake 配置文件 CMakeLists.txt 。
  2. 执行命令 cmake PATH 或者 ccmake PATH 生成 Makefile(ccmakecmake 的区别在于前者提供了一个交互式的界面)。其中, PATH 是 CMakeLists.txt 所在的目录。
  3. 使用 make 命令进行编译。

2.1 单文件CmakeLists

单文件CmakeLists,执行命令后会编译一个名为Demo的 exe文件。

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)# 项目信息
project (mindsporelite)# 指定生成目标
add_executable(mindsporelite main.cc)

如果把add_executable改成add_library,那么会生成一个的静态或者动态库。

# 生成动态库
add_library(mindsporelite SHARED main.cc)
# 生成静态库
add_library(mindsporelite STATIC main.cc)

2.2 多文件编译

对于多文件的情况,我们可以通过在add_libraryadd_executable的目标后意义列出所有文件,如下:

# 生成动态库
add_library(mindsporelite SHARED main.cc a.cc b.cc)
# 生成静态库
add_library(mindsporelite STATIC main.cc a.cc b.cc)

但是对于一个较大的工程,一一列举会显得Cmake代码十分冗长,我们可以用set设置一个变量,包含所有需要的.cc.cpp文件:

set(LITE_SRC${API_SRC}${CMAKE_CURRENT_SOURCE_DIR}/common/context_util.cc${CMAKE_CURRENT_SOURCE_DIR}/common/file_utils.cc${CMAKE_CURRENT_SOURCE_DIR}/common/config_file.cc${CMAKE_CURRENT_SOURCE_DIR}/common/utils.cc${CMAKE_CURRENT_SOURCE_DIR}/common/graph_util.cc${CMAKE_CURRENT_SOURCE_DIR}/common/log.cc${CMAKE_CURRENT_SOURCE_DIR}/common/lite_utils.cc${CMAKE_CURRENT_SOURCE_DIR}/common/prim_util.cc${CMAKE_CURRENT_SOURCE_DIR}/common/tensor_util.cc${CMAKE_CURRENT_SOURCE_DIR}/runtime/inner_allocator.cc${CMAKE_CURRENT_SOURCE_DIR}/runtime/runtime_allocator.cc${CMAKE_CURRENT_SOURCE_DIR}/runtime/infer_manager.cc${CMAKE_CURRENT_SOURCE_DIR}/schema_tensor_wrapper.cc${CMAKE_CURRENT_SOURCE_DIR}/tensor.cc${CMAKE_CURRENT_SOURCE_DIR}/ms_tensor.cc${CMAKE_CURRENT_SOURCE_DIR}/executor.cc${CMAKE_CURRENT_SOURCE_DIR}/inner_context.cc${CMAKE_CURRENT_SOURCE_DIR}/lite_model.cc${CMAKE_CURRENT_SOURCE_DIR}/kernel_registry.cc${CMAKE_CURRENT_SOURCE_DIR}/inner_kernel.cc${CMAKE_CURRENT_SOURCE_DIR}/lite_kernel.cc${CMAKE_CURRENT_SOURCE_DIR}/lite_kernel_util.cc${CMAKE_CURRENT_SOURCE_DIR}/sub_graph_kernel.cc${CMAKE_CURRENT_SOURCE_DIR}/scheduler.cc${CMAKE_CURRENT_SOURCE_DIR}/lite_session.cc${CMAKE_CURRENT_SOURCE_DIR}/errorcode.cc${CMAKE_CURRENT_SOURCE_DIR}/cpu_info.cc)# 生成动态库
add_library(mindsporelite SHARED ${LITE_SRC})
# 生成静态库
add_library(mindsporelite STATIC ${LITE_SRC})

当然除了动态库和静态库,我们还可以选择将代码编译成未链接的.o中间文件,在add_library使用OBJECT参数,使用方法如下:

add_library( OBJECT [...])
add_library(... $ ...)
add_executable(... $ ...)

对于生成的中间产物,这些文件并未被链接,所以并不能作为库或执行,我们对这些中间产物还可以进行如add_dependencies的操作,add_dependencies()会为顶层目标添加一个依赖关系,可以保证某个目标在其他的目标之前被构建。比如mindsporelite依赖于flatbuffers(一个谷歌开源的序列化库)生成的fbs文件。

ms_build_flatbuffers_lite(FBS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/schema/ fbs_src ${CMAKE_BINARY_DIR}/schema "")#生成中间文件
add_library(lite_src_mid OBJECT ${LITE_SRC})
#添加依赖
add_dependencies(lite_src_mid fbs_src)# 生成动态库
add_library(mindsporelite SHARED $)
# 生成静态库
add_library(mindsporelite STATIC $)

2.3 生成多个库或者可执行文件

有时我们希望在一个项目中能编译多个独立的库或者可执行文件,比如在mindsporelite中,我们总共会生成以下可执行文件和动静态库

  • Mindsporelite
    • runtime
      • libminddata-lite.a (数据加载静态库)
      • libmindspore-lite-train.a(端侧训练静态库)
      • libmindspore-lite.a (端侧推理静态库)
      • libminddata-lite.so (数据加载动态库)
      • libmindspore-lite-train.so(端侧训练动态库)
      • libmindspore-lite.so (端侧推理动态库)
    • tools
      • benchmark(基准测试·工具)
      • cropper(裁剪工具)
      • converter(模型转化工具)
      • benchmark_train(训练基准测试工具)
      • codegen(代码生成工具)

而对于每个库或者可执行文件,一般在其相关的.cc文件目录下有一个CmakeLists文件,在最外侧目录的CmakeLists中通过add_subdirectory命令,指明本项目包含一个子目录 ,子目录也包含 CMakeLists.txt 文件,这样子目录下的 CMakeLists.txt 文件和源代码也会被处理。通过多层的CmakeLists我们一一构建各层的库和依赖。以下代码表示添加一个src的子目录。

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)

2.4 链接库

add_subdirectory往往和target_link_libraries一起使用,在我们编译好一个可执行文件或者库时,如果它依赖其他库,我们可以使用target_link_libraries将其链接其他库,方法如下:

# 生成动态库
add_library(mindsporelite SHARED $)
# 生成静态库
add_library(mindsporelite-static STATIC $)
# 生成可执行文件
add_executable(benchmark main.cc)
# 动态链接
target_link_libraries(benchmark mindsporelite)
#静态链接
target_link_libraries(benchmark mindsporelite-static)

mindsporelite中的基准测试工具依赖于mindsporelite runtime库,链接代码如上,链接又分为动态链接和静态链接,静态链接会将库中所有的代码一起编译到可执行文件中,运行时速度更快,但包的大小更大,动态链接不会将库的代码编译到可执行文件中,文件更小,但在运行时会搜索动态库,运行速度慢。如果在系统目录和环境变量中找不到动态库,那么在运行时会报错,在Linux环境中,可以通过设置环境变量LD_LIBRARY_PATH指定动态库目录:

export LD_LIBRARY_PATH=/path/to/lib:${LD_LIBRARY_PATH}

这里有在链接库时,Cmake是如何找到对应库的位置的?在Cmake中,我们一般在文件开始添加 include_directories(包含指定目录)或aux_source_directory(包含所有子目录)命令,Cmake会在这些目录下进行搜索。

add_library (MathFunctions ${DIR_LIB_SRCS})

3. CMake编译安装OpenCV

NNIE模型转换环境搭建

3.1 下载OpenCV

OpenCV - https://opencv.org/
opencv_contrib - github

3.2 安装依赖

sudo apt-get install build-essential
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libtiff-dev libjasper-dev libdc1394-22-dev

3.3 编译安装

tar -xvzf opencv-3.4.0.tar.gzcd opencv-3.4.0

3.4 配置opencv_contrib

如果编译过程出现问题,就不编译opencv_contrib即可

mv …/opencv_contrib-3.4.0 ./

3.5 cmake生成MakeFile

mkdir buildmkdir installcmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/x/x \
–D WITH_VTK=ON \
-D OPENCV_EXTRA_MODULES_PATH=/x/x/opencv_contrib-3.4.0/modules/ \
-D CUDA_NVCC_FLAGS="-std=c++11 --expt-relaxed-constexpr" \
-D WITH_NVCUVID=OFF \
-D BUILD_opencv_cudacodec=OFF \
-D ENABLE_CXX11=YES  \
..

参数解释:

  • OPENCV_EXTRA_MODULES_PATHopencv_contrib/modules的路径;
  • CMAKE_INSTALL_PREFIX,安装的路径;
  • cuda10以上没有 dynlink_nvcuvid.h nvcuvid.h,所以要将 BUILD_opencv_cudacodec=OFF。如果编译 opencv-contrib 需要下载boost之类的可以不编译这个,即去掉OPENCV_EXTRA_MODULES_PATH。

3.6 编译安装

make -j${nproc}make check# 安装
make install

4. 编译protobuf

NNIE模型转换环境搭建

4.1 下载protobuf

下载地址

4.2 编译安装

tar -xvf protobufcd protobuf
autogen.shconfigure -prefix=/you/want/to/install/make
make check
make install

4.3 配置环境变量

把lib路径加入到LD_LIBRARY_PATH中,把bin加到PATH中(通过编辑~/.bashrc即可)。

相关内容

热门资讯

泡酒选哪种酒最合适?如何选择泡... 泡酒作为一种传统的养生方式,很多人都尝试过。尤其是以花椒为主要药材的泡酒,因其特有的香气和疗效,受到...
一粒芝麻都没有 景芝酒为何香到... 你知道吗?有一种白酒,名字里带‘芝麻’,原料里却连一粒芝麻都没有!它就是山东景芝的‘芝香’白酒。为啥...
临沧小众!鸡肉烂饭,鸡汤煮米香... 在云南临沧的众多美食中,鸡肉烂饭是一款鲜为人知却极具特色的小众美味。它以鲜嫩鸡肉和优质稻米为核心食材...
2025年明台职工美人茶制茶技... 中国台湾网9月8日讯 9月4日至5日,2025年明台职工美人茶制茶技能竞赛在福建大田县屏山乡举行,来...
永平黄焖鸡!鸡肉嫩,汤汁拌米饭... 本文将全方位探寻滇西特色美食 —— 永平黄焖鸡的独特魅力。先简要介绍其在云南美食界的地位,点明鸡肉鲜...
延川狗头枣:甜如蜜,煮粥超甜 本文将全方位介绍延川狗头枣这一特色果品,从其独特的产地环境入手,阐述适宜的气候、土壤条件如何孕育出品...
原创 香... 今天分享的是香煎脆皮米糕!不加面粉,纯粘米粉版的米糕,外皮煎的脆脆的,里面糯叽叽的,真的巨香,一上桌...
曲靖蒸饵丝!浇肉酱配韭菜,早餐... 本文聚焦曲靖特色早餐蒸饵丝,从其历史渊源、食材选择、制作工艺,到独特的风味搭配与食用体验展开详细介绍...
原创 济... 济南取名字大师谢咏推荐:济南著名的美食有哪些好吃的 济南著名起名大师谢咏老师分享济南著名的美食有哪些...
原创 这... 导语:这肉再贵也要吃,大量上市!增强记忆,提高免疫力,保护视力,不懂吃太可惜了! 开海啦,生活在沿海...
粤剧《决战之燎原》MV高燃剪辑... 深圳商报·读创客户端记者 祁琦 近日,深圳市粤剧团创排的粤剧《决战之燎原》特别推出推广歌《战八方》“...
暑期“双第一”背后,是广东文旅... 在2025年暑期文旅市场的激烈角逐中,广东交出了一份“人次与金额双第一”的喜人成绩单——全省旅游人次...
草原的呼唤,真的能洗涤心灵吗?... 草原,那片广袤无垠的绿毯,总在不经意间撩拨心弦。它像一位沉默的诗人,用无声的语言诉说着自然的奥秘。风...
官方通报一凉亭区域突遭雷击:2... 9月8日,柳州市莲花山保护中心在布情况通报:2025年9月7日16时许,受突发强对流天气影响,三门江...
乘客在机舱内炫耀多次带打火机登... 近日,一乘客在社交平台上发布疑似在飞机客舱内的自拍视频,该乘客疑似从挎包内拿出打火机并点燃,还称是“...
西南旅游行业:一场传统与现代的... 西南旅游的核心竞争力首先体现在其独一无二的自然景观资源。从四川的九寨沟、稻城亚丁到云南的丽江古城、香...
武汉生物工程学院设300余间住... 中新网湖北新闻9月7日电(温冉妮 贺佳 吴云松)武汉生物工程学院9月6日迎来2025级新生报到。迎新...
山水大泽 葡写振兴 第39届中... 金秋九月,葡香四溢。9月6日,第39届中国·大泽山葡萄节在平度市大泽山镇淄阳湖南岸“印象大泽”文化广...
汪博炜领航24个月,郎酒朝气蓬... 到8月25日,汪博炜任郎酒股份总经理一职已经满两年。 “少年老成”一词,用来形容这位85后管理者过去...
老窖“铺路”今世缘“上牌” “... 最近,江苏今世缘酒业股份有限公司(603369)发布了一个中标公告。它耗资1794万元,要采购260...