编写CMakeLists.txt文件

一、编写CMakeLists.txt文件

下面通过一个Demo来讲解如何编写CMakeLists.txt文件,Demo的结构如下:

./Demo/
├── 3rd                         # 第三方库目录
│   ├── CMakeLists.txt          # 编译第三方库对应的CMakeLists.txt
│   ├── include                 # 存放第三方库对应的头文件
│   │   └── mathApi.h
│   ├── libmathApi.so           # 第三方库编译完生成的动态库文件
│   └── src                     # 存放第三方库对应的源代码
│       └── mathImpl.c
├── CMakeLists.txt              # Demo对应的CMakeLists.txt
├── Demo                        # 编译完Demo生成的二进制文件
├── include                     # 存放Demo头文件
│   └── example.h
└── src                         # 存放Demo源文件
    └── main.c

第三方库对应的CMakeLists.txt文件如下:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)                                # 指定需要CMake的最低版本号
project(math_project)                                              # 设置工程名称

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)           # 设置头文件搜索路径
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src main_src)     # 设置要编译的源代码

add_library(mathApi SHARED ${main_src})                            # 生成动态库文件

Demo对应的CMakeLists.txt文件如下:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)                                 # 指定需要CMake的最低版本号
project(Demo_project)                                               # 设置工程名称
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rd/include)        # 设置头文件搜索路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rd/)                  # 设置要链接的库路径
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src demo_src)      # 设置要编译的源代码
add_executable(Demo ${demo_src})                                    # 根据源码生成二进制文件
target_link_libraries(Demo mathApi)                                 # 链接动态库

注意:CMake命令是大小写不敏感的,可以用大写,也可以用小写,也可以混写。但是,变量是区分大小写的。

二、常用命令用法

2.1、命令与语法

CMake命令通常使用如下格式:COMMAND( arg1 arg2 …)命令关键字后用括号包含所有参数;各参数之间用空格或换行符分隔;参数通常有以下形式:
1)变量:以${MY_VAIRABLE}形式表示;
2)枚举量:例如ADD_LIBRARY可以设置要生成的链接库为SHARED或者STATIC;
3)值:也就是任意字符串内容。
下面介绍常用的CMake命令用法。
注意:命令中的[]内容为可选项,|分隔的内容表示只能选择这几个中的一个

2.2、include_directories

包含头文件路径,类似于makfilede的-I

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

示例:编译Demo的时间需要包含第三方组件头文件以及Demo自己的头文件

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rd/include)        # 设置头文件搜索路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

2.3、link_directories

指定库链接路径,类似于makfilede的-L

link_directories([AFTER|BEFORE] directory1 [directory2 ...])

示例:Demo编译时需要连接第三方库,此时就要指明第三方库路径

link_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rd/)                  # 设置要链接的库路径

2.4、aux_source_directory

在指定的目录下查找所有的源文件名称,并将列表存储在variable变量中

aux_source_directory(<dir> <variable>)

示例:Demo编译时需要指定要编译的源文件

aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src demo_src)      # 设置要编译的源代码

2.5、target_link_libraries

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

target_link_libraries(<target> [item1] [item2] [...]
                      [[debug|optimized|general] <item>] ...)

示例:生成的Demo二进制文件需要连接第三方库组件

target_link_libraries(Demo mathApi)                                 # 链接动态库

2.6、add_library

将指定的源文件生成链接文件,然后添加到工程中去。其中表示库文件的名字,该库文件会根据命令里列出的源文件来创建。而STATIC、SHARED和MODULE的作用是指定生成的库文件的类型。STATIC库是目标文件的归档文件,在链接其它目标的时候使用。SHARED库会被动态链接(动态链接库),在运行时会被加载。MODULE库是一种不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数。默认状态下,库文件将会在于源文件目录树的构建目录树的位置被创建,该命令也会在这里被调用。

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

示例:第三方组件编译完需要生成一个动态库

add_library(mathApi SHARED ${main_src})                            # 生成动态库文件

2.7、add_executable

使用指定的源文件生成一个二进制文件

add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               [source1] [source2 ...])

示例:Demo源文件编译完后要生成一个二进制文件

add_executable(Demo ${demo_src})                                    # 根据源码生成二进制文件

三、示例

cmake_minimum_required(VERSION 3.14.1)
project(csf_project)

#初始化编译框架
set(CMAKE_BUILD_TYPE Debug)
#热补丁PIE方式
set(FRAME_SUPPORT_HOTPATCH_MODE "PIE")
#开启-Bsymbolic选项
set(FRAME_ENABLE_FALGE_BSYMBOLIC ON)
message("path: $ENV{COMPLIE_FRAME_PATH}")
include("$ENV{COMPLIE_FRAME_PATH}/frame_common.cmake")

set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY TRUE)

#设置全局变量
set(CSP3RDCOMPONENTS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../")
set(ENV{LIBPATH} "${CMAKE_CURRENT_SOURCE_DIR}/build/target/")
set(ENV{ERRFILE} "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake_err.log")

#CSF自定义函数
include("${CMAKE_CURRENT_SOURCE_DIR}/build/cmakefiles/csf_pre_func.cmake")

#添加依赖或外部组件
include("${CMAKE_CURRENT_SOURCE_DIR}/build/cmakefiles/extern_deps.cmake")
if(TEST)
    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/contrib ${CMAKE_CURRENT_SOURCE_DIR}/build/contrib)
endif()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/build/source)

ADD_CUSTOM_TARGET(clean_after_build
  # 编译完成后,将依赖文件挪走,避免代码静态检测等工具统计
  COMMAND bash -c "rm -rf dependence/;mkdir -p dependence ; mv ${CMAKE_CURRENT_SOURCE_DIR}/dependence/files dependence/;" VERBATIM
  # 编译完成后,删除测试代码,避免代码静态检测等工具统计
  COMMAND bash -c "rm $(find \"${CMAKE_CURRENT_SOURCE_DIR}\" -type f -name \"*_test.*\") &>/dev/null; echo \"clean test code\";" VERBATIM
  WORKING_DIRECTORY  ${CMAKE_CURRENT_SOURCE_DIR}/../
  COMMENT "clean after build...................."
  )

set(PROGRAM_PKG_NAME CSF-1.0.0-csp-SNAPSHOT-Linux-x64.tar.gz)
if(DEFINED ENV{IDE_VERSION})
    set(PROGRAM_PKG_NAME CSPHAService-1.0.0-csp-ENV{IDE_VERSION}-Linux-x64.tar.gz)
endif()

set(OUTPUTPATH $ENV{PWD}/build)
if(DEFINED ENV{OUTPUTPATH})
    set(OUTPUTPATH $ENV{OUTPUTPATH})
endif()

ADD_CUSTOM_TARGET(package
  WORKING_DIRECTORY  ${CMAKE_CURRENT_SOURCE_DIR}/build/target/
  COMMAND sh -c "tar -zcvf ${OUTPUTPATH}/${PROGRAM_PKG_NAME}  * ;"
  COMMAND echo "${OUTPUTPATH}/${PROGRAM_PKG_NAME}  create successfully"
  COMMENT "package all................................."
)



你可能感兴趣的:(CMake工具,linux,c++,运维)