cmake教程-提高篇

之前写过一篇文章,以实例简单介绍了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 错误, 终止所有处理过程;

五、其他
关于自定义编译选项,统一定义文件、测试、版本号、安装包等的操作,可以参考下面文章。
其他操作:https://blog.csdn.net/lwljava/article/details/38517193

你可能感兴趣的:(工欲善其事,必先利其器,cmake,linux,嵌入式,经验分享)