cmake配置C++工程
# 使用前提——安装CMake
sudo apt-get install cmake
# 检测安装是否成功:
cmake --version
如果你用的是vscode写代码的话,最好还是装一个CMake插件。
# vscode调试cmake
添加如下的launch.json文件
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
// Resolved by CMake Tools:
"program": "${command:cmake.launchTargetPath}",
"args": ["9"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
若没有使用vscode的插件,详细配置见附录。
# CMake生成Makefile流程
# 基本语法
一个最基本的CmakeLists.txt文件最少需要包含以下3行代码:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (section1)
# 指定生成目标
add_executable(section1 main.c)
# 编译
- 执行cmake PATH命令生成 Makefile。其中, PATH 是 CMakeLists.txt 所在的目录。
- 使用 make 命令进行编译。
# 代码详解
- cmake_minimum_required:设置一个工程所需要的最低 CMake版本,如果 CMake的当前版本低于指定的版本,它会停止处理工程文件,并报告错误。
- project:为整个工程设置一个工程名。
- add_executable:使用给定的源文件,为工程引入一个可执行文件。
add_executable(
[WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...]) 引入一个名字为 的可执行目标,这个可执行目标会由调用该命令时在源文件列表中指定的源文件来构建,比如main.c就是一个源码文件。 在工程范围内必须是全局唯一的,它实际上就是make编译后生成的可执行文件。
# 指定C++标准
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# 新建配置文件添加版本信息
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# configure a header file to pass the version number to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add that directory to the list of paths to search for include files
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
create TutorialConfig.h.in
in the source directory with the following contents:
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
# 添加库
For this tutorial we will put the library into a subdirectory called MathFunctions.
├── CMakeLists.txt
├── MathFunctions
│ ├── CMakeLists.txt
│ ├── MathFunctions.h
│ └── mysqrt.cxx
├── TutorialConfig.h.in
└── tutorial.cxx
MathFunctions--CMakeLists.txt
add_library(MathFunctions mysqrt.cxx)
top-level CMakeLists.txt
# add the MathFunctions library
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC MathFunctions)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/MathFunctions"
)
# 添加可选项
# should we use our own math functions
# 我们应该使用自己的数学函数吗
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_INCLUDES}
)
请注意,这里使用变量
EXTRA_LIBS
来收集所有可选库,以供以后链接到可执行文件中。变量EXTRA_INCLUDES
类似地用于可选的头文件。
首先,在 中tutorial.cxx
,MathFunctions.h
如果需要,请包含标题:
// should we include the MathFunctions header?
#ifdef USE_MYMATH
#include "MathFunctions.h"
#else
#include <cmath>
#endif
然后,在同一个文件中,USE_MYMATH
控制使用哪个平方根函数:
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
由于源代码现在需要USE_MYMATH
我们可以TutorialConfig.h.in
使用以下行添加它 :
#cmakedefine USE_MYMATH
# 添加第三方库
# 链接指定的log4cplus库文件和头文件。
set(INC_DIR /usr/local/include)
set(LINK_DIR /usr/local/lib)
target_include_directories( Tutorial
PRIVATE ${INC_DIR}
)
link_directories( Tutorial
PRIVATE ${LINK_DIR}
)
target_link_libraries(Tutorial log4cplus)
# 单文件目录
├── CMakeLists.txt
├── main.c
├── myadd.c
├── myadd.h
cmake_minimum_required(VERSION 3.0)
project(test1)
# 列出当前目录下所有的源文件--main.c,add.c,add.h
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
add_executable(Demo ${DIR_SRCS})
编译成静态库
cmake_minimum_required(VERSION 3.0)
project(test1)
set(LIBSRC myadd.c myadd.h)
add_library(myadd ${LIBSRC})
add_executable(Demo main.c)
target_link_libraries(Demo myadd)
# 多文件目录
test2
├── CMakeLists.txt
├── main.c
├── math
│ ├── CMakeLists.txt
│ ├── myadd.c
│ └── myadd.h
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo3)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 添加 math 子目录
add_subdirectory(math)
# 指定生成目标
add_executable(Demo main.cc)
# 添加链接库
target_link_libraries(Demo MathFunctions)
math下的CMakeLists.txt是:
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)
# 生成链接库
add_library (MathFunctions ${DIR_LIB_SRCS})
add_library是编译成一个静态库
# 附录
# 未使用CMake编译工程时的配置
c_cpp_propertites.json
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/local/gcc-9.3.0/lib/gcc/x86_64-pc-linux-gnu/9.3.0/../../../../include/c++/9.3.0/**",
"/usr/local/gcc-9.3.0/lib/gcc/x86_64-pc-linux-gnu/9.3.0/../../../../include/c++/9.3.0/x86_64-pc-linux-gnu/**",
"/usr/local/gcc-9.3.0/lib/gcc/x86_64-pc-linux-gnu/9.3.0/../../../../include/c++/9.3.0/backward/**",
"/usr/local/gcc-9.3.0/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include/**",
"/usr/local/include/**",
"/usr/local/gcc-9.3.0/include/**",
"/usr/local/gcc-9.3.0/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include-fixed/**",
"/usr/include/x86_64-linux-gnu/**",
"/usr/include/**",
"${workspaceFolder}/cal/**"
],
"defines": [],
"compilerPath": "/usr/local/gcc/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
launch.json
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch", // 配置名称,将会在启动配置的下拉菜单中显示
"type": "cppdbg", // 配置类型,这里只能为cppdbg
"request": "launch", // 请求配置类型,可以为launch(启动)或attach(附加)
"program": "${fileDirname}/${fileBasenameNoExtension}.out", // 将要进行调试的程序的路径
"args": [], // 程序调试时传递给程序的命令行参数,一般设为空即可
"stopAtEntry": false, // 设为true时程序将暂停在程序入口处,我一般设置为true
"cwd": "${workspaceFolder}", // 调试程序时的工作目录
"environment": [], // (环境变量?)
"externalConsole": false, // 调试时是否显示控制台窗口,一般设置为true显示控制台,
// 但是最新版cpptools有BUG,具体请看文末的注意
"internalConsoleOptions": "neverOpen", // 如果不设为neverOpen,调试时会跳到“调试控制台”选项卡,你应该不需要对gdb手动输命令吧?
"MIMode": "gdb", // 指定连接的调试器,可以为gdb或lldb。但目前lldb在windows下没有预编译好的版本。
"miDebuggerPath": "gdb", // 调试器路径,Windows下后缀不能省略,Linux下则去掉
"setupCommands": [ // 用处未知,模板如此
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": false
}
],
"preLaunchTask": "Compile" // 调试会话开始前执行的任务,一般为编译程序。与tasks.json的label相对应
}
]
}
task.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Compile", // 任务名称,与launch.json的preLaunchTask相对应
"command": "g++", // 要使用的编译器, C++就写g++
"args": [
"${file}",
"-I",
"${workspaceFolder}/cal",
"-o", // 指定输出文件名,不加该参数则默认输出a.exe,Linux下默认a.out
"${fileDirname}/${fileBasenameNoExtension}.out",
"${workspaceFolder}/cal/test02.cpp",
"-g", // 生成和调试有关的信息
//"-Wall", // 开启额外警告
"-static-libgcc", // 静态链接
"-std=c++11" // C语言最新标准为c11,或根据自己的需要进行修改比如C++17
], // 编译命令参数
"type": "shell", // 可以为shell或process,前者相当于先打开shell再输入命令,后者是直接运行命令
"group": {
"kind": "build",
"isDefault": true // 设为false可做到一个tasks.json配置多个编译指令,需要自己修改本文件,我这里不多提
},
"presentation": {
"echo": true,
"reveal": "always", // 在“终端”中显示编译信息的策略,可以为always,silent,never。具体参见VSC的文档
"focus": true, // 设为true后可以使执行task时焦点聚集在终端
"panel": "shared" // 不同的文件的编译信息共享一个终端面板
},
//"problemMatcher": "$gcc"
}
]
}