Cmake使用

1、多个源文件在同一目录

头文件和多个源文件都在同一目录中,该项目的工程树状图如下:

1
2
3
4
├── CMakeLists.txt
├── main.cpp
├── myMath.cpp
└── myMath.h

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#include "myMath.h"

int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s argv[1] argv[2] \n", argv[0]);
return 1;
}
int a = atof(argv[1]);
int b = atoi(argv[2]);
int result = add(a, b);
printf("%d + %d = %d\n", a, b, result);
return 0;
}

myMath.cpp

1
2
3
4
5
#include "myMath.h"

int add(int a, int b) {
return (a + b);
}

myMath.h

1
int add(int a, int b);

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目信息
project (demo2)

# 查找当前目录下的所有源文件,并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)

#指定可执行文件输出目录
SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/output") #可执行文件输出目录

# 指定生成目标
add_executable(demo ${DIR_SRCS})

新建build文件夹,进入该文件夹下,输入cmake ..,最后输入make,生成可执行文件

1
2
3
4
mkdir ./build
cd ./build
cmake ..
cmake --build .(类似于make)
示例图片

此时,该项目的工程树状图如下:

1
2
3
4
5
6
7
8
├── build
├── build.sh
├── CMakeLists.txt
├── main.cpp
├── myMath.cpp
├── myMath.h
└── output
└── demo

2、多个源文件在不同一目录

将myMath.cpp和myMath.h移到add文件夹下,该项目的工程树状图如下:

1
2
3
4
5
6
7
├── add
│ ├── CMakeLists.txt
│ ├── myMath.cpp
│ └── myMath.h
├── build.sh
├── CMakeLists.txt
└── main.cpp

子目录中的 CMakeLists.txt:

1
2
3
4
5
# 查找当前目录下的所有源文件,并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)

# 生成静态链接库
add_library (MathFunctions ${DIR_LIB_SRCS})

根目录中的 CMakeLists.txt :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目信息
project (demo3)

SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/output") # 可执行文件输出目录

# 查找当前目录下的所有源文件,并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)

# 添加add子目录
add_subdirectory(add)

# 指定生成目标
add_executable(demo main.cpp)

# 添加静态库链接库
target_link_libraries(demo MathFunctions)

编译——链接——生成的过程一致,

示例图片

此时,该项目的工程树状图如下:

1
2
3
4
5
6
7
8
9
10
├── build
├── add
│ ├── CMakeLists.txt
│ ├── myMath.cpp
│ └── myMath.h
├── build.sh
├── CMakeLists.txt
├── main.cpp
└── output
└── demo

3、cmake补充选项

3.1、指定编译器

添加指定目录下的编译器,这里以添加本地指定目录下的交叉编译工具链为例

1
2
3
4
5
6
#指定目录
set(tools /home/power/host/usr)
set(tools /usr/local/arm/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf)
#指定编译工具链
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)
示例图片

3.2、添加语言标准

1
2
3
4
5
6
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # 添加c++11标准支持
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") # 添加c++14标准支持
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") # 添加c++17标准支持

# set the C++ standard to C++ 11
set(CMAKE_CXX_STANDARD 11)

3.3、关闭告警信息打印

1
add_definitions(-w)

3.4、添加头文件

1
2
3
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/INCLUDE") # 头文件包含目录
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/POOL") # 头文件包含目录
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/BASE") # 头文件包含目录

3.5、区分操作系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MESSAGE("Identifying the OS...")
if(WIN32)
MESSAGE("This is Windows.")
exec_program("cmd" ${PROJECT_SOURCE_DIR} ARGS "/c chcp" OUTPUT_VARIABLE CHCP_OUT)
string(REGEX MATCH "[0-9]+" CODE_PAGE ${CHCP_OUT})
message("Active code page: ${CODE_PAGE}")
if(CODE_PAGE EQUAL 936 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
MESSAGE("This is Windows Chinese. Change the charset to GBK.")
add_compile_options("-fexec-charset=GBK")
endif()
elseif(APPLE)
MESSAGE("This is MacOS.")
elseif(UNIX)
MESSAGE("This is Linux.")
endif()

3.6、添加动态库

1
2
target_link_libraries(prot_IEC104_myown_ubantu -ldl -lpthread)  #线程
target_link_libraries(prot_IEC104_myown_ubantu -ldl -lrt) #共享库(dlopen)

3.7、debug模式编译

1
set(CMAKE_BUILD_TYPE Debug)

4、工程用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
CMAKE_MINIMUM_REQUIRED(VERSION 3.20) # cmake最低版本要求

#指定编译器
#set(tools /home/power/host/usr)
#set(tools /usr/local/arm/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf)
#set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
#set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)

PROJECT(prot_IEC104) # 工程名 CppTemplate

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") # 添加c++11标准支持

SET(CMAKE_BUILD_TYPE "Debug") # Debug模式 选项: Release Debug MinSizeRel RelWithDebInfo
SET(CMAKE_CXX_FLAG "$CMAKE_CXX_FLAG -Wall")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb") # debug模式下 gdb相关选项
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") # release模式下 gdb相关选项
# set(CMAKE_VERBOSE_MAKEFILE ON) # 开启调试 出现问题时开启

# enable_testing() # 打开测试

add_definitions(-w) #关闭打印警告信息

add_definitions(-DDEBUG) # 相当于代码中 #define DEBUG

# add_subdirectory(test) # 添加test子目录

SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/output") # 可执行文件输出目录

INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/INCLUDE") # 头文件包含目录
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/POOL") # 头文件包含目录
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/BASE") # 头文件包含目录
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/fixed") # 头文件包含目录
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/fixed/north") # 头文件包含目录

# 这段代码可以区分操作系统
MESSAGE("Identifying the OS...")
if(WIN32)
MESSAGE("This is Windows.")
exec_program("cmd" ${PROJECT_SOURCE_DIR} ARGS "/c chcp" OUTPUT_VARIABLE CHCP_OUT)
string(REGEX MATCH "[0-9]+" CODE_PAGE ${CHCP_OUT})
message("Active code page: ${CODE_PAGE}")
if(CODE_PAGE EQUAL 936 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
MESSAGE("This is Windows Chinese. Change the charset to GBK.")
add_compile_options("-fexec-charset=GBK")
endif()
elseif(APPLE)
MESSAGE("This is MacOS.")
elseif(UNIX)
MESSAGE("This is Linux.")
endif()
# 这段代码可以区分操作系统

AUX_SOURCE_DIRECTORY(BASE DIR_SRCS) # 添加源代码文件夹, 自动扫描所有文件
AUX_SOURCE_DIRECTORY(POOL DIR_SRCS) # 添加源代码文件夹, 自动扫描所有文件
AUX_SOURCE_DIRECTORY(RDB DIR_SRCS) # 添加源代码文件夹, 自动扫描所有文件
AUX_SOURCE_DIRECTORY(TOOL DIR_SRCS) # 添加源代码文件夹, 自动扫描所有文件
AUX_SOURCE_DIRECTORY(UTIL DIR_SRCS) # 添加源代码文件夹, 自动扫描所有文件
AUX_SOURCE_DIRECTORY(fixed DIR_SRCS) # 添加源代码文件夹, 自动扫描所有文件
AUX_SOURCE_DIRECTORY(fixed/north DIR_SRCS) # 添加源代码文件夹, 自动扫描所有文件
AUX_SOURCE_DIRECTORY(./ DIR_SRCS) # 添加源代码文件夹, 自动扫描所有文件

add_executable(prot_IEC104_myown_ubantu # 输出名为sudoku的可执行文件
${DIR_SRCS}
)

#链接动态库
target_link_libraries(prot_IEC104_myown_ubantu -ldl -lpthread)
target_link_libraries(prot_IEC104_myown_ubantu -ldl -lrt)