[TOC]

CMakeLists.txt编写

  • 文件名必须严格写为CMakeLists

基础的三句话:

1
2
3
4
5
6
7
8
cmake_minmum_required (VERSION 2.8) //这句话指的是支持的cmake最低版本

project (test) //这句话是项目名称

add_executable(test_executable_file main.c)
//这句话有两类参数,第一个参数是预计生成的可执行文件,后面的参数是Cpp语言源文件,
如果说有多个源文件,则在第二类参数里面添加,比如:
add_executable(test2 main.cpp test.cpp)

清除命令:

1
2
3
make clean //清除test_executable_file可执行文件

rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile test_executable_file //删干净

将所有文件包含进去的命令:

1
2
3
4
5
6
aux_source_directionary(dir var)
#这句话有两个参数,前面一个dir指的是目标路径,后面的var指的是一个变量
#因此这句话的作用就是,把dir路径下的cpp文件列表存到var变量里

#对应的,add_executable() 的第二个参数变为 ${var}:
add_executable(test ${var})

用set命令来指定我们想包含的文件:

1
2
3
4
5
6
7
set (var
./mian.c
./test1.c
./test2.c
)

#这个命令把上面三个c文件列表存到了var变量,同样的 add_executable()的第二个参数也是变为${var}

指定头文件路径

1
2
include_directories (dir1 dir2)
#把dir1 和dir2 内的头文件包含进去

构建项目结构

1
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
  • source_dir 源代码目录

    指定一个包含CMakeLists.txt和代码文件所在的目录,该目录可以是绝对路径,也可以是相对路径,对于后者相对路径的起点是CMAKE_CURRENT_SOURCE_DIR。此外,如果子目录再次包含的CMakeLists.txt,则将继续处理里层的CMakeLists.txt,而不是继续处理当前源代码

  • binary_dir 二进制代码目录

    这个目录是可选的,如果指定,cmake命令执行后的输出文件将会存放在此处,若没有指定,默认情况等于source_dir没有进行相对路径计算前的路径,也就是CMAKE_BINARY_DIR

  • EXCLUDE_FEOM_ALL

    这个标志是可选的,如果传递了该参数表示新增加的子目录将会排除在ALL目录之外

双CMakeLists法:

  • 在根目录下构建 CMakeLists.txt ,然后再这个lists里面,使用add_subdirectionary命令,使编译过程转到src文件夹内的CMakeLists里面

  • 在src的CMakeLists里面,编写主要工作:

    1
    2
    3
    4
    aux_source_directionary (. src_list)
    include_directories (../include)
    add_executable (main ${src_list})
    set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
    • EXECUTABLE_OUTPUT_PATH :目标二进制可执行文件的存放位置
    • PROJECT_SOURCE_DIR:工程的根目录

    这两个都是cmake的预定义变量,直接拿来用

  • 在build目录下执行cmake过程:

    1
    2
    3
    cd build
    cmake ..
    make

    cd build以后,会把执行编译生成的文件放在build里面,防止把代码结构变成史

    cmake .. 的含义,是从上一级目录中寻找cmakelist

单CMakeLists法

直接在根目录下编写cmakelist,并把参数写好

1
2
3
4
5
6
7
8
9
10
11
cmake_minmun_required (VERSION 2.8)

project(single_cmakelist)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #把可执行文件放到bin里边

aux_source_directory (src SRC_LIST)

include_directories (include)

add_executable (main ${SRC_LIST})

同样的,新建一个bulid文件夹然后在里面cmake .. make即可

二者的区别

最明显的区别就是,双cmakelist利用了add_subdirectoryI()函数进入后优先执行字母里cmakelist的特性

把整个编译过程分层了,分成外层的控制全局和内层的具体实现

动态库和静态库的编译控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cmake_minimum_required (VERSION 3.5)

project (demo)

set (SRC_LIST ${PROJECT_SOURCE_DIR}/testFunc/testFunc.c) #把src路径设置好

add_library (testFunc_shared SHARED ${SRC_LIST}) #第1个参数指定库的名字;第2个参数决定是动态还是静态,如果没有就默认静态;第3个参数指定生成库的源文件
add_library (testFunc_static STATIC ${SRC_LIST})

set_target_properties (testFunc_shared PROPERTIES OUTPUT_NAME "testFunc")
set_target_properties (testFunc_static PROPERTIES OUTPUT_NAME "testFunc")

set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cmake_minimum_required (VERSION 3.5)

project (demo)


set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.c)

# find testFunc.h
include_directories (${PROJECT_SOURCE_DIR}/testFunc/inc)

find_library(TESTFUNC_LIB testFunc HINTS ${PROJECT_SOURCE_DIR}/testFunc/lib)

add_executable (main ${SRC_LIST})

target_link_libraries (main ${TESTFUNC_LIB})

  • find_library: 在指定目录下查找指定库,并把库的绝对路径存放到变量里,其第一个参数是变量名称,第二个参数是库名称,第三个参数是HINTS,第4个参数是路径,其它用法可以参考cmake文档
  • target_link_libraries: 把目标文件与库文件进行链接

条件编译

简单程序

1
2
3
4
5
6
7
8
9
10
cmake_minimum_required (VERSION 2.8)

project (demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

add_compile_options(-std=c++11 -Wall) #这句话

add_executable(main main.cpp)

生成指定的bin

1
2
3
4
5
6
7
8
9
10
cmake_minimum_required(VERSION 3.5)

project(demo)

option(MYDEBUG "enable debug compilation" OFF)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

add_subdirectory(src)

使用option命令,第一个参数是用户自己规定的名字,中间是显示的信息,最后一个是开关,不写默认是关

然后在src的cmakelist里面就可以读取呼呼自己输入的名字的开关状态来决定:

1
2
3
4
5
6
7
8
9
cmake_minimum_required (VERSION 3.5)

add_executable(main1 main1.c)

if (MYDEBUG) #如果为ON
add_executable(main2 main2.c)
else()
message(STATUS "Currently is not in debug mode")
endif()