1 option命令:
形式:option(<variable> "<help_text>" [value])
简介:cmake中option起到编译开关的作用,CMakeLists.txt中option以前的语句,变量按未定义处理,option之后的语句,变量才被定义。另外,注意,option命令定义的变量不影响c或c++源码中#ifdef或者#ifndef逻辑判断
2 MESSAGE("text"):
在make的时候向控制台输出的提示信息命令语句
3 add_definitions的用法
功能描述:其功能与C/C++中的#define一样
实例如下:
源文件main.cpp
#include <iostream> int main() { #ifdef TEST_IT_CMAKE std::cout<<"in ifdef"<<std::endl; #endif std::cout<<"not in ifdef"<<std::endl; }
CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(optiontest) add_executable(optiontest main.cpp) option(TEST_IT_CMAKE "test" ON) message(${TEST_IT_CMAKE}) if(TEST_IT_CMAKE) message("itis" ${TEST_IT_CMAKE}) add_definitions(-DTEST_IT_CMAKE) endif()
运行编译
// 第一种编译运行方法 mkdir build&& cd build cmake ../ -DTEST_IT_CMAKE=OFF make ./optiontest // 第二种编译运行方法 mkdir build&& cd build cmake ../ -DTEST_IT_CMAKE=ON make ./optiontest
分析运行输出结果,就可以明白该指令的用法。
4 编译选项设置
两种设置方式
(1)通过
add_compile_options
命令
add_compile_options
命令添加的编译选项是针对所有编译器的(包括c和c++编译器)#判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX) add_compile_options(-std=c++11) message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX)
(2)通过set命令修改
CMAKE_CXX_FLAGS
或CMAKE_C_FLAGS
set命令设置
CMAKE_C_FLAGS
或CMAKE_CXX_FLAGS
变量则是分别只针对c和c++编译器#判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX)
5 list的用法总结
list(LENGTH <list><output variable>) list(GET <list> <elementindex> [<element index> ...]<output variable>) list(APPEND <list><element> [<element> ...]) list(FIND <list> <value><output variable>) list(INSERT <list><element_index> <element> [<element> ...]) list(REMOVE_ITEM <list> <value>[<value> ...]) list(REMOVE_AT <list><index> [<index> ...]) list(REMOVE_DUPLICATES <list>) list(REVERSE <list>) list(SORT <list>)
LENGTH 返回list的长度
GET 返回list中index的element到value中
APPEND 添加新element到list中
FIND 返回list中element的index,没有找到返回-1
INSERT 将新element插入到list中index的位置
REMOVE_ITEM 从list中删除某个element
REMOVE_AT 从list中删除指定index的element
REMOVE_DUPLICATES 从list中删除重复的element
REVERSE 将list的内容反转
SORT 将list按字母顺序排序
6 cmake中find_package用法
参考如下链接find_package原理简介以及使用说明
cmake本身不提供任何关于搜索库的便捷方法,也不会对库本身的环境变量进行设置。它仅仅是按照优先级顺序在指定的搜索路径进行查找Findxxx.cmake文件和xxxConfig.cmake文件(其中xxx代表库的名字,特别注意的是有大小写之分),这两个文件大体上是没有区别的,cmake能够找到这两个文件中的任何一个,我们都能成功使用该库,也就是我们可以用库的内置好了Cmake变量。包含了库的头文件和库文件的路径信息,虽然库的作者一般会提供这两个文件,但是也会遇到安装完毕后找不到的情况。当我们在cmake..命令之后,Cmake 会读取执行CMakeLists.txt中的代码,当执行find_package()这条命令后,Cmake 就会从某些路径中找这Findxxx.cmake文件或者xxxConfig.cmake文件,Cmake找到任意一个之后就会执行这个文件,然后这个文件执行后就会设置好一些Cmake变量。比如下面的变量(NAME表示库的名字 比如可以用Opencv 代表Opencv库):
<NAME>_FOUND <NAME>_INCLUDE_DIRS or <NAME>_INCLUDES <NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS <NAME>_DEFINITIONS
一般常用的就是xxx_FOUND 、xxx_INCLUDE_DIRS、xxx_LIBS,分别代表是否找到库的标志、库的头文件路径、库文件路径。find_package()有两种模式:Module模式和Config模式,分别对应上面的Findxxx.cmake 和xxxConfig.cmake两个文件。cmake默认优先Module模式,而Config模式是备选项。
Module模式(仅仅查找Findxxx.cmake文件):
Cmake会优先搜索CMAKE_MODULE_PATH指定的路径,如果在CMakeLists.txt中没有设置CMAKE_MODULE_PATH为存储Findxxx.cmake的路径,也就是说没有下面的指令:
set(CMAKE_MODULE_PATH "Findxxx.cmake文件所在的路径")那么Cmake不会搜索CMAKE_MODULE_PATH指定的路径,此时Cmake会搜索第二优先级的路径,也就是<CMAKE_ROOT>/share/cmake-x.y/Mdodules (注意:x.y表示版本号。我的是3.10)。其中CMAKE_ROOT是你在安装Cmake的时候的系统路径,因为我并没有指定安装路径,所以是系统默认的路径,在我的系统中(ubuntu16.04)系统的默认路径是/usr/loacl,如果你在安装的过程中使用了
cmake -DCMAKE_INSTALL_PREFIX=自己dir路径 ,那么此时CMAKE_ROOT就代表那个你写入的路径 。刚刚说道第一优先级的路径搜索没有找到Findxxx.cmake文件,就会到第二优先级的路径下搜索。如果Cmake在两个路径下都没有找到Findxxx.cmake文件。那么Cmake就会进入Config模式。Config模式(仅仅查找xxxConfig.cmake文件):
Cmake会优先搜索xxx_DIR 指定的路径。如果在CMakeLists.txt中没有设置这个cmake变量。也就是说没有下面的指令:
set(xxx_DIR "xxxConfig.cmkae文件所在的路径")那么Cmake就不会搜索xxx_DIR指定的路径,此时Cmake 就会自动到第二优先级的路径下搜索,也就是/usr/local/lib/cmake/xxx/中的xxxConfig.cmake文件。
查看find_package()的结果
find_package(but_velodyne REQUIRED) if (but_velodyne_FOUND) MESSAGE (STATUS "@@@@@@dern: ${ButVELODYNE_DEFINITIONS}") MESSAGE (STATUS "@@@@@@dern: ${ButVELODYNE_INCLUDE_DIRS}") MESSAGE (STATUS "@@@@@@dern: ${ButVELODYNE_LIBRARY_DIRS}") else() MESSAGE (STATUS "@@@@@@dern: but_velodyne not found") endif(but_velodyne_FOUND)
7 include_directions和find_package
参考链接:include_directories与find_package的联系与区别
include_directories
是用来提供找头文件路径的,打个比方,我现在想要#include"cv.h",但是这个cv.h的路径是/usr/local/include/opencv,那么我总不能在主函数头前写
#include “/usr/local/include/opencv/cv.h”吧,这个时候就用到include_directories了,它提供了一个搜索头文件暂时的根目录,即你可以在cmakelists中写上
include_directories(/usr/local/include)来让库文件搜索以/usr/local/include为基础,即在main函数前写上#include “opencv/cv.h"即可find_package():可参考6
也就是只要找到了*.CMAKE,我们就能够给上图底部的几个变量赋路径
最后,记得将找到的库连接到我们的可执行文件上
target_link_libraries( imageBasics ${OpenCV_LIBS} )
图像增强代码的CMakeLists.txt
cmake_minimum_required( VERSION 2.8 )//版本要求 project( imageBasics )//工程名 set( CMAKE_CXX_FLAGS "-std=c++11" )//添加c++ 11标准支持 find_package( OpenCV 3 REQUIRED )//寻找OpenCV.CMakeLists,以此找到包,并赋值各库相关变量 include_directories( ${OpenCV_INCLUDE_DIRS} )//OpenCV_INCLUDE_DIRS是关于find_package的变量, //包含了一个路径,这样可以在代码中的#include做根目录 include_directories(/usr/local/include)//同上,找根目录 add_executable( imageBasics test_transform2.cpp )//添加对主函数的可执行文件 target_link_libraries( imageBasics ${OpenCV_LIBS} )//链接OpenCV库,OpenCV_LIBS为代表库可执行文件的变量 //$为取出变量中的值
在有的时候会出现find_package找不到 __Config.cmake, _-config.cmake
的情况,解决办法非常简单,因为这两个文件都是包含了package所需的所有路径变量,非常重要,没有它们find_package不会起效果,所以直接去根目录下搜到这两个文件,路径复制后,直接设置,如
$set(OpenCV_DIR /opt/ros/kinetic/share/OpenCV-3.3.1-dev)
_DIR其实就是这两个文件所存在的位置,设置好后直接就得到所有路径变量了还有就是find_package请和include_directories(${OpenCV_INCLUDE_DIRS}) target_link_libraries( test ${OpenCV_LIBS})配合食用,三步走
find_package(OpenCV 3.3.1 REQUIRED)中间写版本可以在多个版本包共存的条件下拿到自己想要的包的Config.cmake文件的路径