CMake 基本命令

原文: http://blog.csdn.net/yangfeng2014/article/details/50638315


本帖子适用于初学者,StepByStep的入门CMake,CMake也是一门编程语言,只不过是针对编译和链接这种程序构建的过程的语言,学习基本语法就可以初步入门,后面需要什么复杂的功能,进阶掌握需要自己去查找官方文档,后续会给出查阅的一些方式

CMake常用命令

基本语法规则


  • cmake变量使用${}方式取值,但是在IF控制语句中是直接使用变量名
  • 环境变量使用$ENV{}方式取值,使用SET(ENV{VAR} VALUE)赋值
  • 指令(参数1 参数2…)

    参数使用括弧括起,参数之间使用空格或分号分开。

ADD_EXECUTABLE指令为例:
ADD_EXECUTABLE(hello main.c func.c)或者
ADD_EXECUTABLE(hello main.c;func.c)

指令是大小写无关的,参数和变量是大小写相关的。推荐你全部使用大写指令。

基本命令


  • PROJECT

    PROJECT(projectname [CXX] [C] [Java])

    指定工程名称,并可指定工程支持的语言。支持语言列表可忽略,默认支持所有语言;指定项目名称,生成的VC项目的名称;
  • SET

    SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

    定义变量(可以定义多个VALUE,如SET(SRC_LIST main.c util.c reactor.c))
  • MESSAGE

    MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …)

    向终端输出用户定义的信息或变量的值

    SEND_ERROR, 产生错误,生成过程被跳过

    STATUS, 输出前缀为–的信息

    FATAL_ERROR, 立即终止所有cmake过程
  • ADD_EXECUTABLE

    ADD_EXECUTABLE(bin_file_name ${SRC_LIST})

    生成可执行文件,编译可执行程序,指定编译,好像也可以添加.o文件

    • add_executable (helloDemo demo.cxx demo_b.cxx) #将cxx编译成可执行文件
  • ADD_LIBRARY

    ADD_LIBRARY(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] SRC_LIST)

    生成动态库或静态库

    SHARED 动态库

    STATIC 静态库

    MODULE 在使用dyld的系统有效,若不支持dyld,等同于SHARED

    EXCLUDE_FROM_ALL 表示该库不会被默认构建
  • SET_TARGET_PROPERTIES

    设置输出的名称,设置动态库的版本和API版本
  • CMAKE_MINIMUM_REQUIRED

    CMAKE_MINIMUM_REQUIRED(VERSION version_number [FATAL_ERROR])

    声明CMake的版本要求
  • ADD_SUBDIRECTORY

    ADD_SUBDIRECTORY(src_dir [binary_dir] [EXCLUDE_FROM_ALL])

    向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置

    EXCLUDE_FROM_ALL含义:将这个目录从编译过程中排除
  • INCLUDE_DIRECTORIES

    INCLUDE_DIRECTORIES([AFTER | BEFORE] [SYSTEM] dir1 dir2 … )

    向工程添加多个特定的头文件搜索路径,路径之间用空格分隔,如果路径包含空格,可以使用双引号将它括起来,默认的行为为追加到当前头文件搜索路径的后面。指定头文件的搜索路径,相当于指定gcc的-I参数。有如下两种方式可以控制搜索路径添加的位置:

    • CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过SET这个cmake变量为on,可以将添加的头文件搜索路径放在已有路径的前面
    • 通过AFTER或BEFORE参数,也可以控制是追加还是置前
    • INCLUDE_DIRECTORIES (${HELLO_SOURCE_DIR}/Hello) #增加Hello为include目录
  • LINK_DIRECTORIES

    LINK_DIRECTORIES(dir1 dir2 …)

    添加非标准的共享库搜索路径,动态链接库或静态链接库的搜索路径,相当于gcc的-L参数

    • LINK_DIRECTORIES(${HELLO_BINARY_DIR}/Hello) #增加Hello为link目录
  • TARGET_LINK_LIBRARIES

    TARGET_LINK_LIBRARIES(target lib1 lib2 …)

    为target添加需要链接的共享库,添加链接库,相同于指定-l参数

    • target_link_libraries(demo Hello) #将可执行文件与Hello连接成最终文件demo
  • ADD_DEFINITIONS

    在C/C++编译器添加-D定义,添加编译参数

    ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),参数之间用空格分隔

    如果你的代码中定义了#ifdef ENABLE_DEBUG #endif,这个代码块就会生效。

    如果要添加其他的编译器开关,可以通过CMAKE_C_FLAGS变量和CMAKE_CXX_FLAGS变

    量设置。

    • add_definitions(-DDEBUG)将在gcc命令行添加DEBUG宏定义
    • add_definitions( “-Wall -ansi –pedantic –g”)
  • ADD_DEPENDENCIES

    ADD_DEPENDENCIES(target-name depend-target1 depend-target2 …)

    定义target依赖的其他target,确保target在构建之前,其依赖的target已经构建完毕
  • ADD_TEST与ENABLE_TESTING

    ENABLE_TESTING指令用来控制Makefile是否构建test目标,涉及工程所有目录。语

    法很简单,没有任何参数,ENABLE_TESTING(),一般情况这个指令放在工程的主

    CMakeLists.txt中。

    ADD_TEST(testname Exename arg1 arg2 …)

    testname是自定义的test名称,Exename可以是构建的目标文件也可以是外部脚本等

    等。后面连接传递给可执行文件的参数。如果没有在同一个CMakeLists.txt中打开

    ENABLE_TESTING()指令,任何ADD_TEST都是无效的。

    比如我们前面的Helloworld例子,可以在工程主CMakeLists.txt中添加

    ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main)

    ENABLE_TESTING()

    生成Makefile后,就可以运行make test来执行测试了。
  • AUX_SOURCE_DIRECTORY

    AUX_SOURCE_DIRECTORY(dir VAR)

    发现一个目录下所有的源代码文件并将列表存储在一个变量中

    把当前目录下的所有源码文件名赋给变量DIR_HELLO_SRCS

    你也可以通过后面提到的FOREACH指令来处理这个LIST
  • EXEC_PROGRAM

    EXEC_PROGRAM(Executable [dir where to run] [ARGS ][OUTPUT_VARIABLE ] [RETURN_VALUE ])

    用于在指定目录运行某个程序(默认为当前CMakeLists.txt所在目录),通过ARGS添加参数,通过OUTPUT_VARIABLE和RETURN_VALUE获取输出和返回值,如下示例:

在src中运行ls命令,在src/CMakeLists.txt添加
EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUE LS_RVALUE) 
IF (not LS_RVALUE) 
MESSAGE(STATUS "ls result: " ${LS_OUTPUT}) # 缩进仅为美观,语法无要求 
ENDIF(not LS_RVALUE) 

在cmake 生成Makefile的过程中,就会执行ls命令,如果返回0,则说明成功执行,那么就输出ls *.c的结果。关于IF语句,后面的控制指令会提到。

  • FILE

    文件操作指令,基本语法为:

    • FILE(WRITE filename “message to write”… )

      WRITE 将一则信息写入文件’filename’中,如果该文件存在,它会覆盖它,如果不存在,它会创建该文件。
    • FILE(APPEND filename “message to write”… )

      APPEND 如同WRITE,区别在于它将信息内容追加到文件末尾。
    • FILE(READ filename variable)

      READ 会读取文件的内容并将其存入到变量中。它会在给定的偏移量处开始读取最多numBytes个字节。如果指定了HEX参数,二进制数据将会被转换成十进制表示形式并存储到变量中。
    • file(STRINGS filename variable [LIMIT_COUNT num]

      [LIMIT_INPUT numBytes] [LIMIT_OUTPUTnumBytes]

      [LENGTH_MINIMUM numBytes] [LENGTH_MAXIMUMnumBytes]

      [NEWLINE_CONSUME] [REGEX regex]

      [NO_HEX_CONVERSION])

      STRINGS 从文件中解析出ASCII字符串列表并存储在变量中。文件中的二进制数据将被忽略。回车符(CR)也会被忽略。也能解析Intel Hex和Motorola S-record文件,这两种文件在读取是会自动转换为二进制格式,可以使用参数NO_HEX_CONVERSION 禁用这种自动转换。LIMIT_COUNT设置可返回的最大数量的字符串。LIMIT_INPUT 设置从输入文件中可读取的最大字节数。LIMIT_OUTPUT设置了存储在输出变量中最大的字节数。 LENGTH_MINIMUM设置了返回的字符串的最小长度。小于这个长度的字符串将被忽略。 LENGTH_MAXIMUM 设置返回的字符串的最大长度。大于这个长度的字符串将被切分为长度不大于于最大长度值的子字符串。NEWLINE_CONSUME 允许换行符包含进字符串中而不是截断它们。REGEX 指定了返回的字符串必须匹配的正则表达式的模式。典型用法:

      file(STRINGS myfile.txt myfile), 将输入文件的每行内容存储在变量”myfile”中。
    • FILE(GLOB variable [RELATIVE path] [globbing expressions]…)

      GLOB 会产生一个由所有匹配globbing表达式的文件组成的列表,并将其保存到变量中。Globbing 表达式与正则表达式类似,但更简单。如果指定了RELATIVE 标记,返回的结果将是与指定的路径相对的路径构成的列表。 (通常不推荐使用GLOB命令来从源码树中收集源文件列表。原因是:如果CMakeLists.txt文件没有改变,即便在该源码树中添加或删除文件,产生的构建系统也不会知道何时该要求CMake重新产生构建文件。globbing 表达式包括:
  • .cxx     - match all files with extension cxx
    .vt?      - match all files with extension vta,…,vtz
    f[3-5].txt - match files f3.txt,f4.txt, f5.txt

    FILE(GLOB_RECURSE variable [RELATIVE path][globbing expressions]…) GLOB_RECURSE 与GLOB类似,区别在于它会遍历匹配目录的所有文件以及子目录下面的文件。对于属于符号链接的子目录,只有FOLLOW_SYMLINKS指定一或者cmake策略CMP0009没有设置为NEW时,才会遍历这些目录。

    Examples of recursive globbing include: 
    /dir/*.py - match all python files in /dir and subdirectories
    file(RENAME  oldname newname)

    RENAME 将文件系统中的文件或目录移动到目标位置,并自动替换目标位置处的文件或目录。

  • FILE(REMOVE [directory]…)

    REMOVE 会删除指定的文件以及子目录下的文件。
  • FILE(REMOVE_RECURSE [directory]…)

    REMOVE_RECURSE 会删除指定的文件及子目录,包括非空目录。
  • FILE(MAKE_DIRECTORY [directory]…)

    MAKE_DIRECTORY在指定目录处创建子目录,如果它们的父目录不存在,也会创建它们的父目录。
  • FILE(RELATIVE_PATH variable directory file)

    RELATIVE_PAT推断出指定文件相对于特定目录的路径。
  • FILE(TO_CMAKE_PATH path result)

    TO_CMAKE_PATH会将路径转换成cmake风格的路径表达形式。
  • FILE(TO_NATIVE_PATH path result)

    TO_NATIVE_PATH与TO_CMAKE_PATH类似,但执行反向操作,将cmake风格的路径转换为操作系统特定风格的路径表式形式。
  • configure_file: 将一份文件拷贝到另一个位置并修改它的内容。将文件input拷贝到output然后替换文件内容中引用到的变量值。如果input是相对路径,它被评估的基础路径是当前源码路径。input必须是一个文件,而不是个路径。如果output是一个相对路径,它被评估的基础路径是当前二进制文件路径。如果output是一个已有的路径,那么输入文件将会以它原来的名字放到那个路径下。

    该命令替换掉在输入文件中,以${VAR}格式或@VAR@格式引用的任意变量,如同它们的值是由CMake确定的一样。 如果一个变量还未定义,它会被替换为空。如果指定了COPYONLY选项,那么变量就不会展开。如果指定了ESCAPE_QUOTES选项,那么所有被替换的变量将会按照C语言的规则被转义。该文件将会以CMake变量的当前值被配置。如果指定了@ONLY选项,只有@VAR@格式的变量会被替换而${VAR}格式的变量则会被忽略。这对于配置使用\${VAR}格式的脚本文件比较有用。任何类似于#cmakedefine VAR的定义语句将会被替换为#define VAR或者/* #undef VAR */,视CMake中对VAR变量的设置而定。任何类似于#cmakedefine01 VAR的定义语句将会被替换为#define VAR 1或#define VAR 0,视VAR被评估为TRUE或FALSE而定。configure_file的作用是让普通文件也能使用CMake中的变量。
  • message(STATUS "current dir: ${CMAKE_CURRENT_SOURCE_DIR}")  
    file(WRITE test1.txt "Some messages to Write\n" )  
    file(APPEND test1.txt "Another message to write\n")  
    file(READ test1.txt CONTENTS LIMIT 4 OFFSET 12)  
    message(STATUS "contents of test1.txt is: \n ${CONTENTS}")  
    file(MD5 ${CMAKE_CURRENT_SOURCE_DIR}/test1.txt HASH_CONTENTS)  
    message(STATUS "hash contents of test1.txt is: \n ${HASH_CONTENTS}")  
    file(STRINGS test1.txt PARSED_STRINGS)  
    message(STATUS "\n strings of test1.txt is: \n ${PARSED_STRINGS}")  
    file(GLOB files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.*")  
    message(STATUS  "files: ${files}")  
    file(MAKE_DIRECTORY dir1 dir2)  
    file(RENAME dir2 dir3)  
    file(REMOVE dir3)  
    file(REMOVE_RECURSE dir3)  
    file(RELATIVE_PATH relative_path $"hljs-tuple">{"hljs-variable">PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/test1.txt)  
    message(STATUS "relative path : ${relative_path}")  
    file(TO_CMAKE_PATH "$ENV{PATH}" cmake_path)  
    message(STATUS "cmake path: ${cmake_path}")  
    file(TO_NATIVE_PATH "/usr/local/sbin;/usr/local/bin" native_path)  
    message(STATUS "native path: ${native_path}")  
    file(DOWNLOAD "http://www.baidu.com" ${CMAKE_CURRENT_SOURCE_DIR}/index.html SHOW_PROGRESS)  
    file(COPY test1.txt DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/dir1)  
    file(INSTALL test1.txt DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/dir1)  
     
     
         
         
         
         
      • INCLUDE

        INCLUDE(module> [OPTIONAL] [RESULT_VARIABLE <VAR>]
                            [NO_POLICY_SCOPE])
        INCLUDE(file [OPTIONAL])  #用来载入CMakeLists.txt文件
        INCLUDE(module [OPTIONAL]) #用来载入预定义的cmake模块
        
        #OPTIONAL参数的左右是文件不存在也不会产生错误
        
           
           
               
               
               
               

          可以载入一个文件,也可以载入预定义模块(模块会在CMAKE_MODULE_PATH指定的路径进行搜索) 载入的内容将在处理到INCLUDE语句时直接执行。

          从给定的文件中读取CMake的清单文件代码。在清单文件中的命令会被立即处理,就像它们是写在这条include命令展开的地方一样。如果指定了OPTIONAL选项,那么如果被包含文件不存在的话,不会报错。如果指定了RESULT_VARIABLE选项,那么var或者会被设置为被包含文件的完整路径,或者是NOTFOUND,表示没有找到该文件。

          如果指定的是一个模块(module)而不是一个文件,查找的对象会变成路径CMAKE_MODULE_PATH下的文件module.cmake。

        • get_filename_component( VAR FileName
          PATH|ABSOLUTE|NAME|EXT|NAME_WE|REALPATH
          [CACHE] )
          将变量VAR设置为路径(PATH),文件名(NAME),文件扩展名(EXT),去掉扩展名的文件名(NAME_WE),完整路径(ABSOLUTE),或者所有符号链接被解析出的完整路径(REALPATH)。注意,路径会被转换为Unix的反斜杠(/),并且没有结尾的反斜杠。该命令已经考虑了最长的文件扩展名。如果指定了CACHE选项,得到的变量会被加到cache中。

        • get_filename_component(VAR FileName
          PROGRAM [PROGRAM_ARGS ARG_VAR]
          [CACHE])
          在FileName中的程序将会在系统搜索路径中被查找,或者是一个完整路径。如果与PRPGRAM一起给定了PROGRAM_ARGS选项,那么任何在Filename字符串中出现的命令行中选项将会从程序名中分割出来并存储在变量中。这可以用来从一个命令行字符串中分离程序名及其选项。
        • OPTION
          为用户提供一个可选项,
          option(option_variable “描述选项的帮助性文字” [initial value])
          该命令为用户提供了一个在ON和OFF中做出选择的选项。如果没有指定初始值,将会使用OFF作为初值。如果有些选项依赖于其他选项的值,参见CMakeDependentOption模块的帮助文件。

        • target_include_directories

        target_include_directories was added in CMake 2.8.11 and is the recommended
        way to set include directories. For lesser versions, we revert to set_property
        if(CMAKE_VERSION VERSION_LESS 2.8.11)
          include_directories(\${HDF5_INCLUDE_DIRS})
        else()
          target_include_directories(${program} PUBLIC ${HDF5_INCLUDE_DIRS})
        endif()

      • target_compile_options
      • # target_compile_options was added in CMake 2.8.12 and is the recommended way to
        # set compile flags. Note that this sets the COMPILE_OPTIONS property (also
        # available only in 2.8.12+) rather than the COMPILE_FLAGS property, which is
        # deprecated. The former can handle lists whereas the latter cannot.
        if(CMAKE_VERSION VERSION_LESS 2.8.12)
          string(REPLACE ";" " " f90flags "${f90flags}")
          set_property(TARGET ${program} PROPERTY COMPILE_FLAGS "${f90flags}")
        else()
          target_compile_options(${program} PUBLIC ${f90flags})
        endif()

      你可能感兴趣的:(cmake,cmake)