目录
1、add_definitions()
语法:
add_definitions(-D${宏名字})
代码中应用
这种可以在我们更改别人代码做实验时使用,既不对其源码进行破坏,又可以添加自己的功能。之前都是在程序中进行#define,有了这个后可以直接在编译的时候进行选择。具体的,在工程CMakeLists.txt 中,使用add_definitions()函数控制代码的开启和关闭:
option(TEST_DEBUG "option for debug" OFF)
if (TEST_DEBUG) # 这个TEST_DEBUG 是CMake中的变量
add_definitions(-DTEST_DEBUG) # 这个TEST_DEBUG 是CMake中的变量
endif(TEST_DEBUG)
*.c源码中就可以使用:
#ifdef TEST_DEBUG
...
...
#else
...
#endif
对程序进行控制。
运行时
运行构建项目的时候可以添加参数控制宏的开启和关闭.
cmake -DUSE_MACRO = on .. #打开
cmake -DUSE_MACRO=off .. #关闭
2、find_package()
语法
find_package(catkin REQUIRED COMPONENTS
common
map
roscpp
)
作用
引入外部依赖包,执行之后,会为以下几个变量 赋值(这些变量需要模块预先定义):
<LibaryName>_FOUND
<LibaryName>_INCLUDE_DIR or <LibaryName>_INCLUDES
<LibaryName>_LIBRARY or <LibaryName>_LIBRARIES
使用:
find_package(CURL)
add_executable(curltest curltest.cc)
if(CURL_FOUND)
target_include_directories(clib PRIVATE ${CURL_INCLUDE_DIR})
target_link_libraries(curltest ${CURL_LIBRARY})
else(CURL_FOUND)
message(FATAL_ERROR ”CURL library not found”)
endif(CURL_FOUND)
3、include_directories
语法
include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
作用
将给定目录 dir1 dir2 加给编译器搜索到的包含文件 .默认情况下,加到目录列表的最后. 通过设定 CMAKE_include_directories_BEFORE 为 ON 来改变. 通过使用 BEFORE or AFTER 可以加在前面或者后面. 如果设定 SYSTEM 选项 编译器认定为系统包含目录.
4、target_include_directories
语法
target_include_directories(t x / y)
作用
指定目标文件 t 的搜索目录范围 – 它将x / y添加到目标t的包含路径。
5、link_directories
语法
link_directories( self/define/lib/path )
作用
该指令的作用主要是指定要链接的库文件的路径,该指令有时候不一定需要。因为find_package和find_library指令可以得到库文件的绝对路径。不过你自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。
6、ADD_LIBRARY()
语法
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])
作用:将源码source构建成一个库, 供他人使用
<name>
:库的名字,直接写名字即可,不要写lib,会自动加上前缀的哈。
[STATIC | SHARED | MODULE]
:类型有三种。
SHARED,动态库
STATIC,静态库
MODULE,在使用 dyld 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。
XCLUDE_FROM_ALL
:这个库不会被默认构建,除非有其他的组件依赖或者手工构建。
使用
SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
注意,一般我们使用的静态库/动态库只是后缀名不同而已,上面构建的libhello.so与libhello_static.a,显然名字不同哦。这时你会有一个想法,那我把hello_static改成hello,结果是不可行的,静态库无法构建。重名会忽略第二条指令。
解决方法:改libhello_static.a的属性–输出名字
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
样就可以生成libhello.so与libhello.a了
关于动态库的版本号
#VERSION 指代动态库版本,SOVERSION 指代 API 版本。
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
从中我们可以看出:不管你的动态库版本是什么,对外调用总是libxxx.so。
7、add_executable
方式1
add_executable(< name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL] source1 source2 … sourceN)
add_executable:使用给定的源文件,为工程引入一个可执行文件。引入一个名为< name>的可执行目标,该目标会由调用该命令时在源文件列表中指定的源文件来构建。< name>对应于逻辑目标名字,并且在工程范围内必须是全局唯一的。被构建的可执行目标的实际文件名将根据具体的本地平台创建出来(比如< name>.exe或者仅仅是< name>)。
默认情况下,可执行文件将会在构建树的路径下被创建,对应于该命令被调用的源文件树的路径。如果要改变这个位置,查看RUNTIME_OUTPUT_DIRECTORY目标属性的相关文档。如果要改变最终文件名的< name >部分,查看OUTPUT_NAME目标属性的相关文档。
如果指定了MACOSX_BUNDLE选项,对应的属性会附加在创建的目标上。查看MACOSX_BUNDLE目标属性的文档可以找到更多的细节。
如果指定了EXCLUDE_FROM_ALL选项,对应的属性将会设置在被创建的目标上。查看EXCLUDE_FROM_ALL目标属性的文档可以找到更多的细节。
方式2
add_executable(< name> IMPORTED)
一个导入的可执行目标引用了一个位于工程之外的可执行文件。该格式不会生成构建这个目标的规则。该目标名字的作用域在它被创建的路径以及底层路径有效。它可以像在该工程内的其他任意目标一样被引用。导入可执行文件为类似于add_custom_command之类的命令引用它提供了便利。
关于导入的可执行文件的细节可以通过设置以IMPORTED_开头的属性来指定。这类属性中最重要的是IMPORTED_LOCATION(以及它对应于具体配置的版本IMPORTED_LOCATION_< CONFIG>);该属性指定了执行文件主文件在磁盘上的位置。查看IMPORTED_*属性的文档来获得更多信息。
8、target_link_libraries
语法:
target_link_libraries(<target> [item1] [item2] [...]
[[debug|optimized|general] <item>] ...)
作用
该指令的作用为将目标文件与库文件进行链接。
上述指令中的<target>是指通过add_executable()和add_library()指令生成已经创建的目标文件。而[item]表示库文件没有后缀的名字。默认情况下,库依赖项是传递的。当这个目标链接到另一个目标时,链接到这个目标的库也会出现在另一个目标的连接线上。这个传递的接口存储在interface_link_libraries的目标属性中,可以通过设置该属性直接重写传递接口。
target_link_libraries里库文件的顺序符合gcc链接顺序的规则,即被依赖的库放在依赖它的库的后面,例如:
target_link_libraries(hello A B.a C.so)
在上面的命令中,libA.so可能依赖于libB.a和libC.so,如果顺序有错,链接时会报错。还有一点,B.a会告诉CMake优先使用静态链接库libB.a,C.so会告诉CMake优先使用动态链接库libC.so,也可直接使用库文件的相对路径或绝对路径。使用绝对路径的好处在 于,当依赖的库被更新时,make的时候也会重新链接。
9、aux_source_directory
语法
aux_source_directory(<dir> <variable>)
作用
在目录中查找所有源文件。
收集指定目录中所有源文件的名称,并将列表存储在提供的变量中。 该命令旨在供使用显式模板实例化的项目使用。 模板实例化文件可以存储在Templates子目录中,并使用此命令自动收集,以避免手动列出所有实例化。
试图使用此命令来避免编写库或可执行目标的源文件列表。 尽管这似乎可行,但是CMake无法生成知道何时添加新源文件的生成系统。 通常,生成的构建系统知道何时需要重新运行CMake,因为修改了CMakeLists.txt文件以添加新的源。 当仅将源代码添加到目录而不修改该文件时,将不得不手动重新运行CMake来生成包含新文件的构建系统。
10、set_target_properties
语法
set_target_properties(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
作用1
set_target_properties(
Thirdlib
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/libThirdlib.so
)
导入外部库,设置外部库的头文件路径。
导入外部库,设置外部库文件所在的路径。
作用2
设置动态库版本号
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
VERSION:动态库版本
SOVERSION:API版本
最后生成的结果是:
libhello.so.1.2
libhello.so.1->libhello.so.1.2
libhello.so->libhello.so.1
11、add_subdirectory
语法
add_subdirectory (source_dir [binary_dir] [EXCLUDE_FROM_ALL])
作用
添加一个子目录并构建该子目录。
source_dir
必选参数。该参数指定一个子目录,子目录下应该包含CMakeLists.txt
文件和代码文件。子目录可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前目录的一个相对路径。-
binary_dir
可选参数。该参数指定一个目录,用于存放输出文件。可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前输出目录的一个相对路径。如果该参数没有指定,则默认的输出目录使用source_dir
。 -
EXCLUDE_FROM_ALL
可选参数。当指定了该参数,则子目录下的目标不会被父目录下的目标文件包含进去,父目录的
CMakeLists.txt
不会构建子目录的目标文件,必须在子目录下显式去构建。例外情况:当父目录的目标依赖于子目录的目标,则子目录的目标仍然会被构建出来以满足依赖关系(例如使用了target_link_libraries)
。