cmake指令详解

来源:互联网 发布:slam算法工程师招聘 编辑:程序博客网 时间:2024/05/19 19:55

PROJECT(工程名字)

这条指令会自动创建两个变量:

_BINARY_DIR(二进制文件保存路径) _SOURCE_DIR(源代码路径)
cmake系统也帮助我们预定义了PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR其值与上述对应相等

SET(变量名 变量值)

SET(VAR [VALUE] [CACHE TYPEDOCSTRING [FORCE]])SET(SRC_LIST main.c t1.ct2.c)SET(SRC_LIST main.c)

MESSAGE

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …)
向终端输出用户定义的信息或变量的值
SEND_ERROR, 产生错误,生成过程被跳过
STATUS, 输出前缀为—的信息
FATAL_ERROR, 立即终止所有cmake过程

ADD_EXECUTABLE

ADD_EXECUTABLE(可执行文件名 生成该可执行文件的源文件)
说明源文件需要编译出的可执行文件名
例:
ADD_EXECUTABLE(hello ${SRC_LIST})
说明SRC_LIST变量中的源文件需要编译出名为hello的可执行文件

ADD_SUBDIRECTORY

ADD_SUBDIRECTORY(src_dir [binary_dir] [EXCLUDE_FROM_ALL])
向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置
EXCLUDE_FROM_ALL含义:将这个目录从编译过程中排除

SET(EXECUTABLE_OUTPUT_PATHPROJECTBINARYDIR/bin)SET(LIBRARYOUTPUTPATH{PROJECT_BINARY_DIR}/lib)更改生成的库文件路径

ADD_LIBRARY

ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)
生成动态静态库
例:
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES

设置目标的一些属性来改变它们构建的方式。
set_target_properties(target1 target2 …
PROPERTIES prop1 value1
prop2 value2 …)
  为一个目标设置属性。该命令的语法是列出所有你想要变更的文件,然后提供你想要设置的值。你能够使用任何你想要的属性/值对,并且在随后的代码中调用GET_TARGET_PROPERTY命令取出属性的值。

  影响一个目标输出文件的名字的属性详述如下。

PREFIX和SUFFIX属性覆盖了默认的目标名前缀(比如lib)和后缀(比如.so)。

IMPORT_PREFIX和IMPORT_SUFFIX是与之等价的属性,不过针对的是DLL(共享库目标)的导入库。

在构建目标时,OUTPUT_NAME属性设置目标的真实名字,并且可以用来辅助创建两个具有相同名字的目标,即使CMake需要唯一的逻辑目标名。OUTPUT_NAME可以为不同的配置设置输出的目标名字。当目标在指定的配置名(全部大写,例如DEBUG_POSTFIX)下被构建时,_POSTFIX为目标的真实名字设置一个后缀。该属性的值在目标创建时被初始化为CMAKE_POSTFIX的值(可执行目标除外,因为较早的CMake版本不会为可执行文件使用这个属性。)

  LINK_FLAGS属性可以用来为一个目标的链接阶段添加额外的标志。LINK_FLAGS_将为配置添加链接标志,例如DEBUG,RELEASE,MINSIZEREL,RELWITHDEBINFO。DEFINE_SYMBOL属性设置了编译一个共享库中的源文件时才会被定义的预处理器符号名。如果这个值没有被设置的话,那么它会被设置为默认值target_EXPORTS(如果目标不是一个合法的C标示符的话可以用一些替代标志)。这对于检测头文件是包含在它们的库以内还是以外很有帮助,从而可以合理设置dllexport/dllimport修饰符(注意,只有在编译到的时候,这个符号才会被定义;因此猜测在代码中,判断预处理符号是否被定义可以知道依赖库是导入的还是导出的——译注)。COMPILE_FLAGS属性可以设置附加的编译器标志,它们会在构建目标内的源文件时被用到。它也可以用来传递附加的预处理器定义。

  LINKER_LANGUAGE属性用来改变链接可执行文件或共享库的工具。默认的值是设置与库中的文件相匹配的语言。CXX和C是这个属性的公共值。

  对于共享库,VERSION和SOVERSION属性分别可以用来指定构建的版本号以及API版本号。当构建或者安装时,如果平台支持符号链接并且链接器支持so名字,那么恰当的符号链接会被创建。如果只指定两者中的一个,缺失的另一个假定为具有相同的版本号。对于可执行文件,VERSION可以被用来指定构建版本号。当构建或者安装时,如果该平台支持符号链接,那么合适的符号链接会被创建。对于在Windows系统而言,共享库和可执行文件的VERSION属性被解析成为一个”major.minor”的版本号。这些版本号被用做该二进制文件的镜像版本。

  还有一些属性用来指定RPATH规则。INSTALL_RPATH是一个分号分隔的list,它指定了在安装目标时使用的rpath(针对支持rpath的平台而言)(-rpath在gcc中用于在编译时指定加载动态库的路径;优先级较系统库路径要高。详情参见http://www.cmake.org/Wiki/CMake_RPATH_handling#What_is_RPATH_.3F——译注)。INSTALL_RPATH_USE_LINK_PATH是一个布尔值属性,如果它被设置为真,那么在链接器的搜索路径中以及工程之外的目录会被附加到INSTALL_RPATH之后。SKIP_BUILD_RPATH是一个布尔值属性,它指定了是否跳过一个rpath的自动生成过程,从而可以从构建树开始运行。BUILD_WITH_INSTALL_RPATH是一个布尔值属性,它指定了是否将在构建树上的目标与INSTALL_RPATH链接。该属性要优先于SKIP_BUILD_RPATH,因此避免了安装之前的重新链接。INSTALL_NAME_DIR是一个字符串属性,它用于在Mac OSX系统上,指定了被安装的目标中使用的共享库的”install_name”域的目录部分。如果目标已经被创建,变量CMAKE_INSTALL_RPATH, CMAKE_INSTALL_RPATH_USE_LINK_PATH, CMAKE_SKIP_BUILD_RPATH, CMAKE_BUILD_WITH_INSTALL_RPATH和CMAKE_INSTALL_NAME_DIR的值会被用来初始化这个属性。

  PROJECT_LABEL属性可以用来在IDE环境,比如visual studio,中改变目标的名字。 VS_KEYWORD可以用来改变visual studio的关键字,例如如果该选项被设置为Qt4VSv1.0的话,QT集成将会运行得更好。

  VS_SCC_PROJECTNAME, VS_SCC_LOCALPATH, VS_SCC_PROVIDER可以被设置,从而增加在一个VS工程文件中对源码控制绑定的支持。

  PRE_INSTALL_SCRIPT和POST_INSTALL_SCRIPT属性是在安装一个目标之前及之后指定运行CMake脚本的旧格式。只有当使用旧式的INSTALL_TARGETS来安装目标时,才能使用这两个属性。使用INSTALL命令代替这种用法。

  EXCLUDE_FROM_DEFAULT_BUILD属性被visual studio生成器使用。如果属性值设置为1,那么当你选择”构建解决方案”时,目标将不会成为默认构建的一部分。

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME “hello”)

同时生成动态静态库
ADD_LIBRARY(hello SHARED LIBHELLOSRC)ADDLIBRARY(hellostaticSTATIC{LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME “hello”)
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
控制版本
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
VERSION指代动态库版本,SOVERSION指代API版本。

INSTALL

INSTALL(TARGETS hellohello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
INSTALL(FILES hello.h DESTINATIONinclude/hello)
注意,静态库要使用ARCHIVE关键字
cmake -DCMAKE_INSTALL_PREFIX=/usr ..[路径]

INCLUDE_DIRECTORIES(追加标志 头文件路径)

INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)
向工程添加多个特定的头文件搜索路径,路径之间用空格分隔,如果路径包含空格,可以使用双引号将它括起来。默认的行为是追加到当前头文件搜索路径的后面。有如下两种方式可以控制搜索路径添加的位置:
CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过SET这个cmake变量为on,可以将添加的头文件搜索路径放在已有路径的前面
通过AFTER或BEFORE参数,也可以控制是追加还是置前

LINK_DIRECTORIES(库文件路径)

LINK_DIRECTORIES(directory1 directory2 …)

TARGET_LINK_LIBRARIES

设置目标要连接库文件的名称
TARGET_LINK_LIBRARIES(target library1

作一些Windows相关的操作

ELSE(WIN32)
MESSAGE(STATUS “This is not windows”)

作一些非Windows相关的操作

ENDIF(WIN32)
通过设置SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
上述代码可写为
IF(WIN32)
ELSE()
ENDIF()
还可以
IF(WIN32)

do something related to WIN32

ELSEIF(UNIX)

do something related to UNIX

ELSEIF(APPLE)

do something related to APPLE

ENDIF(WIN32)

WHILE指令的语法是:
WHILE(condition)
COMMAND1(ARGS …)
COMMAND2(ARGS …)

ENDWHILE(condition)

FOREACH指令的使用方法有三种形式:
列表
FOREACH(loop_var arg1 arg2…)
COMMAND1(ARGS …)
COMMAND2(ARGS …)

ENDFOREACH(loop_var)
像我们前面使用的AUX_SOURCE_DIRECTORY的例子
AUX_SOURCE_DIRECTORY(. SRC_LIST)
FOREACH(F SRCLIST)MESSAGE({F})
ENDFOREACH(F)

范围
FOREACH(loop_var RANGE total)
ENDFOREACH(loop_var)
从0到total以1为步进举例如下:
FOREACH(VAR RANGE 10)
MESSAGE(VAR)ENDFOREACH(VAR)010FOREACH(loopvarRANGEstartstop[step])ENDFOREACH(loopvar)startstopstepFOREACH(ARANGE5153)MESSAGE({A})
ENDFOREACH(A)
最终得到的结果是:
5
8
11
14
这个指令需要注意的是,直到遇到ENDFOREACH指令,整个语句块才会得到真正的执行。

FIND_PACKAGE(CURL)
IF(CURL_FOUND)
INCLUDE_DIRECTORIES(CURLINCLUDEDIR)TARGETLINKLIBRARIES(curltest{CURL_LIBRARY})
ELSE(CURL_FOUND)
MESSAGE(FATAL_ERROR ”CURL library not found”)
ENDIF(CURL_FOUND)

可以自己定义一些FIND_PACKAGE包,比如
定义cmake/FindHELLO.cmake模块

FIND_PATH(HELLO_INCLUDE_DIR hello.h /usr/include/hello /usr/local/include/hello)
FIND_LIBRARY(HELLO_LIBRARY NAMES hello PATH /usr/lib /usr/local/lib)
IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
SET(HELLO_FOUND TRUE)
ENDIF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
IF (HELLO_FOUND)
IF (NOT HELLO_FIND_QUIETLY)
MESSAGE(STATUS “FoundHello: ${HELLO_LIBRARY}”)
ENDIF (NOT HELLO_FIND_QUIETLY)
ELSE (HELLO_FOUND)
IF (HELLO_FIND_REQUIRED)
MESSAGE(FATAL_ERROR”Could not find hello library”)
ENDIF (HELLO_FIND_REQUIRED)
ENDIF (HELLO_FOUND)

那么可以使用
FIND_PACKAGE(HELLO)
IF(HELLO_FOUND)
ADD_EXECUTABLE(hello main.c)
INCLUDE_DIRECTORIES(HELLOINCLUDEDIR)TARGETLINKLIBRARIES(hello{HELLO_LIBRARY})
ENDIF(HELLO_FOUND)
来操作,不过操作之前需要设置cmake搜索路径
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

原创粉丝点击