之前写过一篇文章,以实例简单介绍了cmake的常用操作,这次写一下稍微提高一些的用法。入门篇请参考CMake:入门篇。
一、常需要设置的几个变量
如果我们是在嵌入式下编程,需要交叉编译,那么下面一些变量可能需要设置一下。
#指定C++的标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
#指定C语言的标准
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
#指定操作系统名称
set(CMAKE_SYSTEM_NAME Linux)
#设置搜索选项
#指定了一个或者多个优先于其他搜索路径的搜索路径
set(CMAKE_FIND_ROOT_PATH /opt/arm /opt/install)
#对FIND_PROGRAM()起作用,有三种取值,NEVER,ONLY,BOTH,
#第一个表示不在你CMAKE_FIND_ROOT_PATH下进行查找,
#第二个表示只在这个路径下查找,第三个表示先查找这个路径,再查找全局路径,
#对于这个变量来说,一般都是调用宿主机的程序,所以一般都设置成NEVER
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
#对FIND_LIBRARY()起作用,表示在链接的时候的库的相关选项,
#因此这里需要设置成ONLY来保证我们的库是在交叉环境中找的
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
#对FIND_PATH()和FIND_FILE()起作用,一般来说也是ONLY
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
#指定编译链
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_C_COMPILER gcc)
set(CMAKE_STRIP strip)
#指定编译标志
set(CMAKE_C_FLAGS "-Wall -g -ggdb")
set(CMAKE_C_FLAGS_RELEASE "-Wall")
set(CMAKE_CXX_FLAGS "-Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "-Wall")
set(CMAKE_EXE_LINKER_FLAGS "-z noexecstack -z now -z relro -pie")
二、cmake中一些预定义变量
PROJECT_SOURCE_DIR
工程的根目录
PROJECT_BINARY_DIR
运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build
CMAKE_INCLUDE_PATH
环境变量,非cmake变量
CMAKE_LIBRARY_PATH
环境变量
CMAKE_SOURCE_DIR
顶级CMakeLists.txt的文件夹
CMAKE_CURRENT_SOURCE_DIR
当前处理的CMakeLists.txt所在的路径
CMAKE_CURRENT_BINARY_DIR
target编译目录
EXECUTABLE_OUTPUT_PATH
重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH
重新定义目标链接库文件的存放位置
PROJECT_NAME
返回通过PROJECT指令定义的项目名称
三、判断和循环
cmake也能进行判断和循环操作
if判断
if(expression)
# then section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
#...
elseif(expression2)
# elseif section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
#...
else(expression)
# else section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
#...
endif(expression)
foreach循环(有四种方式)
方式一:
#遍历参数列表
foreach(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endforeach(loop_var)
##############################
foreach(i 0 1 2 3)
message(STATUS "i is ${i}")
endforeach(i)
方式二:
#从0开始直到total结束(包含total)
foreach(loop_var RANGE total)
##############################
foreach(i RANGE 3)
message(STATUS "i is ${i}")
endforeach(i)
方式三:
#从start开始直到stop结束之间的值,可以设置步进值step
foreach(loop_var RANGE start stop [step])
##############################
foreach(i RANGE 0 5 2)
message(STATUS "i is ${i}")
endforeach(i)
方式四:
#按照list进行循环
foreach(loop_var IN [LISTS [list1 [...]]]
[ITEMS [item1 [...]]])
while循环
while(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endwhile(condition)
一个使用循环的常规例子,常用来遍历文件夹。
set(DIR_LIST "common" "config" "main" "include")
foreach(v ${DIR_LIST})
include_directories(${v})
aux_source_directory(${v} SRC_FILES_SUB)
set(SRC_FILES ${SRC_FILES} ${SRC_FILES_SUB})
endforeach()
四、常用的几个命令
#外部调用指令,可移执行任何外部命令,后面加参数
exec_program(pwd OUTPUT_VARIABLE CUR_DIR)
#打印日志指令,可以输出信息
message(STATUS "CUR_DIR = ${CUR_DIR}")
其中message的第一个参数可以是:
无参数:重要消息;
STATUS
:非重要消息;
WARNING``:CMake 警告, 会继续执行;
AUTHOR_WARNING
:CMake 警告 (dev), 会继续执行;
SEND_ERROR
:CMake 错误, 继续执行,但是会跳过生成的步骤;
FATAL_ERROR
:CMake 错误, 终止所有处理过程;
五、其他
关于自定义编译选项,统一定义文件、测试、版本号、安装包等的操作,可以参考下面文章。其他操作