cmake命令速查手册

目录

  1. 基本知识点
  2. ADD_LIBRARY
  3. INCLUDE_DIRECTORIES
  4. FIND_LIBRARY
  5. ADD_EXECUTABLE
  6. add_subdirectory
  7. aux_source_directory
  8. break
  9. INSTALL
  10. Filesystem
  11. Ref

基本知识点

在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:

  1. 编写 CmakeLists.txt。
  2. 执行命令“cmake PATH”或者“ccmake PATH”生成 Makefile ( PATH 是 CMakeLists.txt 所在的目录)。
  3. 使用 make 命令进行编译。

CMakeLists.txt由命令、注释和空格组成:

  • 命令不区分大小写
  • 注释使用“#”符号
  • 命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。

CMakeLists.txt 编写完成后需要使用 cmake 或 ccmake 命令生成Makefile 。 ccmake 与命令 cmake 的不同之处在于 ccmake 提供了一个图形化的操作界面。cmake 命令的执行方式如下:

cmake [options] 

通常推荐的使用方式是在工程目录下创建一个文件夹,如:build,然后cd到build执行cmake .. ,这样的好处是编译的产出易于清除:

mkdir build
cd build
cmake ..
make

 

ADD_LIBRARY

将指定的源文件生成链接文件,然后添加到工程中去。

add_library( [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [source1] [source2] [...]
)

表示库文件的名字,STATIC、SHARED和MODULE的作用是指定生成的库文件的类型,source1 source2表示各个源文件。

add_library(${PROJECT_NAME} SHARED 
            src/hello.cpp inc/world.cpp 
)

 

INCLUDE_DIRECTORIES

添加头文件路径

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

它相当于g++选项中的-I参数的作用,也相当于环境变量中增加路径到CPLUS_INCLUDE_PATH变量的作用。

# eg: 
include_directories(../../../thirdparty/comm/include)

 

添加需要链接的库文件路径,该指令有时候不一定需要。因为find_package和find_library指令可以得到库文件的绝对路径。不过你自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。

link_directories(directory1 directory2 ...)

它相当于g++命令的-L选项的作用,也相当于环境变量中增加LD_LIBRARY_PATH的路径的作用。

# eg: 
link_directories("/home/server/third/lib")

 

FIND_LIBRARY

查找库所在路径

A short-hand signature is: 

find_library ( name1 [path1 path2 ...]) 

The general signature is: 

find_library ( 
         
        name | NAMES name1 [name2 ...] [NAMES_PER_DIR] 
        [HINTS path1 [path2 ... ENV var]] 
        [PATHS path1 [path2 ... ENV var]] 
        [PATH_SUFFIXES suffix1 [suffix2 ...]] 
        [DOC "cache documentation string"] 
        [NO_DEFAULT_PATH] 
        [NO_CMAKE_ENVIRONMENT_PATH] 
        [NO_CMAKE_PATH] 
        [NO_SYSTEM_ENVIRONMENT_PATH] 
        [NO_CMAKE_SYSTEM_PATH] 
        [CMAKE_FIND_ROOT_PATH_BOTH | 
         ONLY_CMAKE_FIND_ROOT_PATH | 
         NO_CMAKE_FIND_ROOT_PATH] 
)

例子如下:

# eg: 
FIND_LIBRARY(RUNTIME_LIB rt /usr/lib /usr/local/lib NO_DEFAULT_PATH)

cmake会在目录中查找,如果所有目录中都没有,值RUNTIME_LIB就会被赋为NO_DEFAULT_PATH

 

添加需要链接的库文件路径

link_libraries(library1  library2 ...)
# eg: 
# 直接是全路径 
link_libraries(“/home/server/third/lib/libcommon.a”)

 # 下面的例子,只有库名,cmake会自动去所包含的目录搜索 
link_libraries(iconv) 

# 传入变量 
link_libraries(${RUNTIME_LIB}) 

# 也可以链接多个
link_libraries("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" "/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")

可以链接一个,也可以多个,中间使用空格分隔。

 

将目标文件与库文件进行链接

target_link_libraries( [item1] [item2] [...] 
                      [debug|optimized|general] [] ...
)

其中是指通过add_executable()和add_library()指令生成已经创建的目标文件。而[item]表示库文件没有后缀的名字。默认情况下,库依赖项是传递的。当这个目标链接到另一个目标时,链接到这个目标的库也会出现在另一个目标的连接线上。这个传递的接口存储在interface_link_libraries的目标属性中,可以通过设置该属性直接重写传递接口。

# eg: 
# 以下写法都可以: 
target_link_libraries(myProject comm)         # 连接libhello.so库,默认优先链接动态库 
target_link_libraries(myProject libcomm.a)    # 显示指定链接静态库 
target_link_libraries(myProject libcomm.so)   # 显示指定链接动态库 # 再如: 
target_link_libraries(myProject libcomm.so)  #这些库名写法都可以。 
target_link_libraries(myProject comm) 
target_link_libraries(myProject -lcomm)

 

ADD_EXECUTABLE

为工程生成目标文件

add_executable( [WIN32] [MACOSX_BUNDLE] 
               [EXCLUDE_FROM_ALL] 
               source1 [source2 ...]
)

# eg: 
add_executable(demo main.cpp )

 

add_subdirectory

为构建添加一个子路径

add_subdirectory(source_dir [binary_dir] 
                 [EXCLUDE_FROM_ALL])

这条命令的作用是为构建添加一个子路径。source_dir选项指定了CMakeLists.txt源文件和代码文件的位置。如果source_dir是一个相对路径,那么source_dir选项会被解释为相对于当前的目录,但是它也可以是一个绝对路径。binary_dir选项指定了输出文件的路径。如果binary_dir是相对路径,它将会被解释为相对于当前输出路径,但是它也可以是一个绝对路径。如果没有指定binary_dir,binary_dir的值将会是没有做任何相对路径展开的source_dir,这也是通常的用法。在source_dir指定路径下的也应该有一个CMakeLists.txt,而且当执行命令add_subdirectory时会进入source_dir,并执行此路径下的CMakeLists.txt。

如果指定了EXCLUDE_FROM_ALL选项,在子路径下的目标默认不会被包含到父路径的ALL目标里,并且也会被排除在IDE工程文件之外。用户必须显式构建在子路径下的目标,比如一些示范性的例子工程就是这样。典型地,子路径应该包含它自己的project()命令调用,这样会在子路径下产生一份完整的构建系统(比如VS IDE的solution文件)。注意,目标间的依赖性的优先级要高于这种排除行为。如果一个被父工程构建的目标依赖于在这个子路径下的目标,被依赖的目标会被包含到父工程的构建系统中,以优先满足依赖性的要求。

 

aux_source_directory

查找在某个路径下的所有源文件

aux_source_directory( )

搜集所有在指定路径下的源文件的文件名,将输出结果列表储存在指定的变量中。该命令主要用在那些使用显式模板实例化的工程上。模板实例化文件可以存储在Templates子目录下,然后可以使用这条命令自动收集起来;这样可以避免手工罗列所有的实例。

 

break

从一个包围该命令的foreach或while循环中跳出

break()

 

INSTALL

INSTALL指令用于定义安装规则,安装的内容可以包括目标二进制、动态库、静态库以及文件、目录、脚本等。

目标文件的安装:

INSTALL(TARGETS targets... 
        [[ARCHIVE|LIBRARY|RUNTIME] 
                [DESTINATION ] 
                [PERMISSIONS permissions...] 
                [CONFIGURATIONS [Debug|Release|...]] 
                [COMPONENT ] 
                [OPTIONAL] ] 
        [...]
)

TARGETS后面跟的就是通过ADD_EXECUTABLE或者ADD_LIBRARY定义的目标文件,可能是可执行二进制、动态库、静态库。

目标类型也就相对应的有三种,ARCHIVE特指静态库,LIBRARY特指动态库,RUNTIME特指可执行目标二进制。

DESTINATION定义了安装的路径,如果路径以/开头,那么指的是绝对路径,这时候CMAKE_INSTALL_PREFIX其实就无效了。如果你希望使用CMAKE_INSTALL_PREFIX来定义安装路径,就要写成相对路径,即不要以/开头,那么安装后的路径就是${CMAKE_INSTALL_PREFIX}/

# eg: 
INSTALL(TARGETS myrun mylib mystaticlib 
        RUNTIME DESTINATION bin 
        LIBRARY DESTINATION lib 
        ARCHIVE DESTINATION libstatic 
)

即:可执行二进制myrun安装到${CMAKE_INSTALL_PREFIX}/bin目录 

动态库libmylib安装到${CMAKE_INSTALL_PREFIX}/lib目录 

静态库libmystaticlib安装到${CMAKE_INSTALL_PREFIX}/libstatic目录 

特别注意的是你不需要关心TARGETS具体生成的路径,只需要写上TARGETS名称就可以 

了。

 

普通文件的安装:

INSTALL(FILES files... DESTINATION  
        [PERMISSIONS permissions...] 
        [CONFIGURATIONS [Debug|Release|...]] 
        [COMPONENT ] 
        [RENAME ] 
        [OPTIONAL]
) 
# 可用于安装一般文件,并可以指定访问权限,文件名是此指令所在路径下的相对路径。
# 如果默认不定义权限PERMISSIONS,安装后的权限为,OWNER_WRITE,OWNER_READ, 
# GROUP_READ,和WORLD_READ,即644权限。

 

非目标文件的可执行程序安装(比如脚本之类):

INSTALL(PROGRAMS files... DESTINATION  
        [PERMISSIONS permissions...] 
        [CONFIGURATIONS [Debug|Release|...]] 
        [COMPONENT ] 
        [RENAME ] 
        [OPTIONAL]
)

跟上面的FILES指令使用方法一样,唯一的不同是安装后权限为: 

OWNER_EXECUTE, GROUP_EXECUTE, 和WORLD_EXECUTE,即755权限

 

目录的安装:

INSTALL(DIRECTORY dirs... DESTINATION  
        [FILE_PERMISSIONS permissions...] 
        [DIRECTORY_PERMISSIONS permissions...] 
        [USE_SOURCE_PERMISSIONS] 
        [CONFIGURATIONS [Debug|Release|...]] 
        [COMPONENT ] 
        [[PATTERN  | REGEX ] 
                [EXCLUDE] [PERMISSIONS permissions...]] 
        [...]
)

这里主要介绍其中的DIRECTORY、PATTERN以及PERMISSIONS参数。 

DIRECTORY后面连接的是所在Source目录的相对路径,但务必注意: 

abc和abc/有很大的区别。 abc意味着abc这个目录会安装在目标路径下; abc/意味着abc这个目录的内容会被安装在目标路径下; 

如果目录名不以/结尾,那么这个目录将被安装为目标路径下的abc,如果目录名以/结尾,代表将这个目录中的内容安装到目标路径,但不包括这个目录本身。 

PATTERN用于使用正则表达式进行过滤,PERMISSIONS用于指定PATTERN过滤后的文件权限。

看一个例子:

INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj 
        PATTERN "CVS" EXCLUDE 
        PATTERN "scripts/*" 
        PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ 
        GROUP_EXECUTE GROUP_READ
)

这条指令的执行结果是: 

将icons目录安装到 /share/myproj,将scripts/中的内容安装到/share/myproj包含目录名为CVS的目录,对于scripts/*文件指定权限为 OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ.

 

安装时cmake脚本的执行:

INSTALL([[SCRIPT ] [CODE ]] [...]) 
# SCRIPT参数用于在安装时调用cmake脚本文件(也就是.cmake文件)
# CODE参数用于执行CMAKE指令,必须以双引号括起来。比如: 
INSTALL(CODE "MESSAGE(\"Sample install message.\")")

 

Filesystem

file(GLOB  
     [LIST_DIRECTORIES true|false]
     [RELATIVE ]
     [CONFIGURE_DEPENDS] 
     [...]
) 

file(GLOB_RECURSE  
     [FOLLOW_SYMLINKS] 
     [LIST_DIRECTORIES true|false]
     [RELATIVE ] 
     [CONFIGURE_DEPENDS] 
     [...]
)

 

产生一个匹配 的文件列表并将它存储到变量 中。文件名替代表达式和正则表达式相似,但更简单。如果 RELATIVE 标志位被设定,将返回指定路径的相对路径。结果将按字典顺序排序。

如果 CONFIGURE_DEPENDS 标志位被指定,CMake 将在编译时给主构建系统添加逻辑来检查目标,以重新运行 GLOB 标志的命令。如果任何输出被改变,CMake都将重新生成这个构建系统。

注意:我们不推荐使用 GLOB 来从源文件树收集源文件列表。如果当源文件添加或删除时没有 CMakeLists.txt 文件被修改,那么在 CMake 重新生成时并不会识别出它们。CONFIGURE_DEPENDS 标志位可能不会再所有生成器上可靠的工作,如果一个新的生成器在以后被添加,并不会被支持。如果项目使用它将会被卡主。即使 CONFIGURE_DEPENDS 可靠的工作,在每个重新构建的过程中做检查也十分浪费性能。

GLOB_RECURSE 将会递归所有匹配文件夹的子文件夹和匹配的文件。子文件夹为符号链接时只有当 FOLLOW_SYMLINKS 被指定或规则 CMP0009 没有设置为 NEW 时才会被递归。

默认 GLOB_RECURSE 省略结果列表中的目录,设置 LIST_DIRECTORIES 为 true 来添加目录到结果列表中。如果 FOLLOW_SYMLINKS 被指定或规则 CMP0009 没有设置为 OLD 。LIST_DIRECTORIES 将符号链接作为路径。

 

递归文件名包括的例子:

/dir/*.py - match all python files in /dir and subdirectories

 

Ref:

https://www.jianshu.com/p/ed151fdcf473

https://cmake.org/cmake/help/latest/command/file.html

https://www.cnblogs.com/binbinjx/p/5626916.html

https://blog.csdn.net/bigdog_1027/article/details/79113342

https://blog.csdn.net/guoyajie1990/article/details/78138636

 

 

你可能感兴趣的:(Linux)