佛山网站建设公司价格,天坛整装电话,seo排名优化厂家,网站建设 软件 开源CMake指令入门 ——以构建OpenCV项目为例
转自#xff1a;https://blog.csdn.net/sandalphon4869/article/details/100589747
一、安装
sudo apt-get install cmake安装好后#xff0c;输入
cmake -version如果出现了cmake的版本显示#xff0c;那么说明安装成功
二、c…CMake指令入门 ——以构建OpenCV项目为例
转自https://blog.csdn.net/sandalphon4869/article/details/100589747
一、安装
sudo apt-get install cmake安装好后输入
cmake -version如果出现了cmake的版本显示那么说明安装成功
二、cmake编译
cmake的作用就是将在IDE编译器中的编译功能拿出来可以在终端上完成。类似于vim和文本编辑器。
cmake的编译方式 内部构建(in-source-build) 外部构建(out-of-source-build)
两者的区别仅仅是前者将生成的编译文件和源代码、CMakeLists.txt 混杂在一起后者就只是创建了一个文件夹 build 存储生成的编译文件更好删除编译生成的文件而已直接删文件夹。
三、语法
1. 基本语法 指令是大小写无关的参数和变量是大小写相关的。但推荐你全部使用大写指令。 变量使用 ${}方式取值但是在 IF 控制语句中是直接使用变量名。如${SRC_LIST} 指令(参数 1 参数 2…) 参数使用括弧括起参数之间使用空格或分号分开。 如ADD_EXECUTABLE(hello main.c func.c) 或者 ADD_EXECUTABLE(hello main.c;func.c) 。 注释# comment
2. 指令
搞清当前目录的意思 CMakeLists.txt 中的 . 表示当前目录是CMakeLists.txt文件所在的目录而非执行时终端的当前目录。 cmake . 这条终端命令是执行时终端的当前目录。
(1) PROJECT()
PROJECT(projectname [CXX] [C] [Java])总结定义工程名称并可指定工程支持的语言。 定义工程名称如 PROJECT(HELLO) 那么工程的名称就是 HELLO 支持的语言列表支持的语言列表是可以忽略的 默认情况表示支持所有语言。 如指定CPROJECT(HELLO CXX) 这个指令隐式的定义了四个 cmake 变量: projectname_BINARY_DIR 以及 projectname_SOURCE_DIR格式并非实际的变量。对于这个工程就是 HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR (之后就可以直接使用了这两个变量)使用 projectname_BINARY_DIR 这个是无效的。 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR 变量。他们的值分别跟 HELLO_BINARY_DIR 与 HELLO_SOURCE_DIR 一致。区别是这两个会自动根据工程名字的变化而变化。建议以后直接使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR即使修改了工程名称也不会影响这两个变量。如从HELLO该为WORLD那么前者就得写成WORLD_BINARY_DIR 和 WORLD_SOURCE_DIR但后者还是 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR。
(2) CMAKE_MINIMUM_REQUIRED()
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)cmake最低版本
(3) SET()
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])作用定义变量的值
比如 如果有多个源文件也可以定义成SET(SRC_LIST main.c t1.c t2.c) 可以用 来处理包含空格的文件名SET(SRC_LIST hello world.cpp)建议使用方式 使用c11特性set(CMAKE_CXX_FLAGS ${CAMKE_CXX_FLAGS} -stdc11)防止出现因为c11才有的编译错误比如 error: ‘to_string’ is not a member of ‘std’ 设置编译模式 Build Type要加引号不加可能报错。 Debug模式set(CMAKE_BUILD_TYPE Debug)Release模式set(CMAKE_BUILD_TYPE Release)更快。
(4) MESSAGE()
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] message to display)作用在cmake编译过程中向终端输出用户定义的信息。
三种信息类型: SEND_ERROR产生错误生成过程被跳过 STATUS输出前缀为 -- 的信息。 FATAL_ERROR立即终止所有 cmake 过程
输出内容hello ${variant name}
比如
PROJECT(HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS The value of HELLO_SOURCE_DIR is${HELLO_SOURCE_DIR} )
ADD_EXECUTABLE(hello ${SRC_LIST})输出
...
The value of HELLO_SOURCE_DIR is/home/song/code
...ps引号的作用是保留空格 hello world ${HELLO_SOURCE_DIR}输出为 hello world /home hello world ${HELLO_SOURCE_DIR}输出为 helloworld/home
(5) AUX_SOURCE_DIRECTORY()
①基本含义
AUX_SOURCE_DIRECTORY(dir VARIABLE)作用是发现一个目录 dir 下所有的源代码文件并将列表存储在一个变量中这个指令临时被用来自动构建源文件列表。因为目前 cmake 还不能自动发现新添加的源文件。 本目录为CMakeLists.txt所在的目录
比如
AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(main ${SRC_LIST})将本目录下的源代码文件添加到SRC_LIST变量中再将这些文件编译成生成文件。
②子目录
注意如果本目录下有子目录是不会将子目录下的源代码文件添加进去的得手动打出来。比如
# 本目录下的子目录subDir
AUX_SOURCE_DIRECTORY(./subDir SRC_LIST)③可添加多个
这两个一起添加进入 SRL_LIST并不是后者覆盖前者。
AUX_SOURCE_DIRECTORY(./src/text SRC_LIST)
AUX_SOURCE_DIRECTORY(./src/serial SRC_LIST)(6) ADD_SUBDIRECTORY
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])这个指令用于向当前工程添加存放源文件的子目录并可以指定中间二进制和目标二进制存放的位置。
EXCLUDE_FROM_ALL参数的含义将这个目录从编译过程中排除比如工程 的 example可能就需要工程构建完成后再进入 example 目录单独进行构建(当然你 也可以通过定义依赖来解决此类问题)。
比如
将 src 子目录加入工程并指定编译输出(包含编译中间结果)路径为bin 目录。
(7) FIND_PACKAGE()
FIND_PACKAGE(name [major.minor] [QUIET] [NO_MODULE]
[[REQUIRED|COMPONENTS] [componets...]])参数
REQUIRED 参数如果使用了这个参数说明这 个链接库是必备库如果找不到这个链接库则工程不能编译。
功能只找一个名为 name 的包后面都是修饰条件所以如果要找多个包要分多个FIND_PACKAGE() 写。
比如 OpenCV3 find_package(OpenCV REQUIRED)ROS find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)(8) INCLUDE_DIRECTORIES()
include_directories()功能链接头文件
描述可以将要链接的头文件都写在括号里不用分成多个 INCLUDE_DIRECTORIES()写。
比如
OpenCV3${OpenCV_INCLUDE_DIRS}ROS${catkin_INCLUDE_DIRS}
include_directories(${OpenCV_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})(9) ADD_EXECUTABLE()
ADD_EXECUTABLE(hello ${SRC_LIST})生成可执行文件。 相关的源文件是SRC_LIST 中 定义的源文件列表 你也可以直接写成ADD_EXECUTABLE(hello main.c ti.c)。 可以写成 ADD_EXECUTABLE(hello main) cmake 会自动的在本目录查找 main.c 或者 main.cpp等当然最好不要偷这个懒以免这个目录确实存在一个 main.c 和一个 main.cpp hello是最终要执行的可执行文件./hello
(10) TARGET_LINK_LIBRARIES()
TARGET_LINK_LIBRARIES(target library1 debug | optimized library2...)功能这个必须写在 ADD_EXECUTABLE() 之后为生成文件target添加库。
比如
OpenCV3${OpenCV_LIBS}ROS${catkin_LIBRARIES}
3. 总结
添加文件的方式 手动添加set() SET(SRC_LIST main.cpp forest.hpp)
ADD_EXECUTABLE(main ${SRC_LIST})自动添加AUX_SOURCE_DIRECTORY() AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(main ${SRC_LIST})四、构建OpenCV项目
项目结构
为了使整个项目更加条理我们的文件夹采用如下组织方式
bin
build
src
CMakeLists.txt其中bin目录用于放编译生成的可执行文件build目录用于cmake构建项目src用于放源代码。
OpenCV源文件
下面是我们写的一个OpenCV示例代码
#include opencv2/core/core.hpp
#include opencv2/highgui/highgui.hpp
#include opencv2/imgproc/imgproc.hpp
#include iostreamusing namespace std;
using namespace cv;int main(int argc, char** argv)
{if (argc ! 2){cout Usage: opencv_test image path endl;return -1;}char *imgName argv[1];Mat image;image imread(imgName, 1);if (!image.data){cout No image data endl;return -1;}Mat gray_img;cvtColor(image, gray_img, CV_BGR2GRAY);imwrite(images/result.jpg, gray_img);return 0;
}这是一个很简单的例子读取图片然后转化成灰度图。
编写CMakeLists.txt
CMake文件的文件名CMakeLists.txt有严格的大小写要求注意不要写错。
# project name
PROJECT(HELLO)# using C11
set(CMAKE_CXX_FLAGS ${CAMKE_CXX_FLAGS} -stdc11 )# cmake version
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)# find OpenCV
FIND_PACKAGE(OpenCV REQUIRED)# show the message of OpenCV
message(STATUS OpenCV library status:)
message(STATUS version: ${OpenCV_VERSION})
message(STATUS headers: ${OpenCV_INCLUDE_DIRS})
message(STATUS libraries: ${OpenCV_LIBS})# link headers
INCLUDE_DIRECTORIES({OpenCV_INCLUDE_DIRS})# 添加源代码文件到SRC_LIST变量中
AUX_SOURCE_DIRECTORY(. SRC_LIST)# 生成可执行文件
ADD_EXECUTABLE(hello ${SRC_LIST})# after ADD_EXECUTABLE为生成文件target添加库
TARGET_LINK_LIBRARIES(hello ${OpenCV_LIBS})
PROJECT指令的语法是
PROJECT(projectname [CXX] [C] [Java])你可以用这个指令定义工程名称并可指定工程支持的语言支持的语言列表是可以忽略的这个指令隐式的定义了两个cmake变量: projectname_BINARY_DIR 以及projectname_SOURCE_DIR。前者指构建路径后者指工程路径即 CMakeLists.txt 所在的路径。
同时cmake系统也帮助我们预定义了 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR 变量他们的值分别跟 opencv_test_BINARY_DIR 与 opencv_test_SOURCE_DIR 一致。
为了统一起见建议以后直接使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR即使修改了工程名称也不会影响这两个变量。如果使用了projectname_SOURCE_DIR修改工程名称后需要同时修改这些变量。
接下来是设置cmake要求的最低版本号
cmake_minimum_required(VERSION 3.5)SET指令的语法是
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])现阶段你只需要了解SET指令可以用来显式的定义变量即可。这里我们将变量CMAKE_RUNTIME_OUTPUT_DIRECTORY定义为${opencv_test_SOURCE_DIR}/bin也就是工程路径下的bin目录。
下面介绍一个很重要的指令find_package 这个指令以被用来在系统中自动查找配置构建工程所需的程序库。在linux和unix类系统下这个命令尤其有用。CMake自带的模块文件里有大半是对各种常见开源库的 find_package 支持支持库的种类非常多。
当它找到OpenCV程序库之后就会帮助我们预定义几个变量OpenCV_FOUND、OpenCV_INCLUDE_DIRS、OpenCV_LIBRARY_DIRS、OpenCV_LIBRARIES它们分别指是否找到OpenCVOpenCV的头文件目录OpenCV的库文件目录OpenCV的所有库文件列表。接着我们就可以使用这些变量来配置了
include_directories(${OpenCV_INCLUDE_DIRS})上面这个指令用来设置包含的头文件的路径。
link_directories(${OpenCV_LIBRARY_DIRS})上面这个指令用来设置库文件的路径。
target_link_libraries(opencv_test ${OpenCV_LIBS})上面这个指令用来设置需要的库文件它的语法是
TARGET_LINK_LIBRARIES(target library1debug | optimized library2...)其中的target就是前面设置生成的目标文件可执行文件
add_executable(opencv_test src/opencv_test.cpp)这个命令很好理解首先是可执行文件的名字然后是源码的名字。因此这个命令一定要在TARGET_LINK_LIBRARIES之前使用。
现在我们的CMakeLists.txt就介绍完了。
构建项目并运行
mkdir build cd build
cmake ..
make
# 至此构建完成下面运行
./opencv_test