大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
vscode
Cmake简介
简介
-
CMake是一个跨平台的安装编译工具,可以用简单的语句来描述所有平台的安装(编译过程)。
-
CMake可以说已经成为大部分C++开源项目标配
传统的C++文件不通系统对应不通的编译
比如 当添加一个文件的时候需要对不通操作系统中的工程进行修改
有了Cmake以后,只需要编写一个CmakeLists文件就可以对应将一个C++工程不通操作系统
当新添加一个文件的时候只需要更改对应的CmakeLists即可
Cmake语法
基本语法格式:指令(参数 1 参数 2…)
- 参数使用括弧括起
- 参数之间使用空格或分号分开
指令是大小写无关的,参数和变量是大小写相关的
set(HELLO hello.cpp)
add_executable(hello main.cpp hello.cpp)
ADD_EXECUTABLE(hello main.cpp ${HELLO})
变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名
重要指令和CMake常用变量
重要指令
cmake_minimum_required – 指定CMake的最小版本要求
# CMake最小版本要求为2.8.3
cmake_minimum_required(VERSION 2.8.3)
- 语法:cmake_minimum_required(VERSION versionNumber [FATAL_ERROR])
project – 定义工程名称,并可指定工程支持的语言
# 指定工程名为HELLOWORLD
project(HELLOWORLD)
- 语法:project(projectname [CXX] [C] [Java])
set – 显式的定义变量
# 定义SRC变量,其值为main.cpp hello.cpp
set(SRC sayhello.cpp hello.cpp)
- 语法:set(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
include_directories – 向工程添加多个特定的头文件搜索路径 —>相当于指定g++编译器的-I参数
# 将/usr/include/myincludefolder 和 ./include 添加到头文件搜索路径
include_directories(/usr/include/myincludefolder ./include)
- 语法:include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)
link_directories – 向工程添加多个特定的库文件搜索路径 —>相当于指定g++编译器的-L参数
# 将/usr/lib/mylibfolder 和 ./lib 添加到库文件搜索路径
link_directories(/usr/lib/mylibfolder ./lib)
- 语法:link_directories(dir1 dir2 …)
add_library – 生成库文件
# 通过变量 SRC 生成 libhello.so 共享库
add_library(hello SHARED ${SRC})
- 语法:add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)
add_compile_options – 添加编译参数
1# 添加编译参数 -Wall -std=c++11
2add_compile_options(-Wall -std=c++11 -O2)
- 语法:add_compile_options(
add_executable – 生成可执行文件
# 编译main.cpp生成可执行文件main
add_executable(main main.cpp)
- 语法:add_executable(exename source1 source2 … sourceN)
target_link_libraries – 为 target 添加需要链接的共享库 —>相同于指定g++编译器-l参数,用在add_executable之后(link_library用在add_excutable之前)
# 将hello动态库文件链接到可执行文件main
target_link_libraries(main hello)
- 语法:target_link_libraries(target library1library2…)
add_subdirectory – 向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置
# 添加src子目录,src中需有一个CMakeLists.txt
add_subdirectory(src)
- 语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
aux_source_directory – 发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表
# 定义SRC变量,其值为当前目录下所有的源代码文件
aux_source_directory(. SRC)
# 编译SRC变量所代表的源代码文件,生成main可执行文件
add_executable(main ${SRC})
- 语法:aux_source_directory(dir VARIABLE)
CMake常用变量
CMAKE_C_FLAGS gcc编译选项
CMAKE_CXX_FLAGS g++编译选项
# 在CMAKE_CXX_FLAGS编译选项后追加-std=c++11
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
CMAKE_BUILD_TYPE 编译类型(Debug, Release)
# 设定编译类型为debug,调试时需要选择debug
set(CMAKE_BUILD_TYPE Debug)
# 设定编译类型为release,发布时需要选择release
set(CMAKE_BUILD_TYPE Release)
CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
__BINARY_DIR
这三个变量指代的内容是一致的。
如果是 in source build,指的就是工程顶层目录。
如果是 out-of-source 编译,指的是工程编译发生的目录。
PROJECT_BINARY_DIR 跟其他指令稍有区别,不过现在,你可以理解为他们是一致的。
CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
__SOURCE_DIR
这三个变量指代的内容是一致的,不论采用何种编译方式,都是工程顶层目录。
也就是在 in source build时,他跟 CMAKE_BINARY_DIR 等变量一致。
PROJECT_SOURCE_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的。
CMAKE_C_COMPILER:指定C编译器
CMAKE_CXX_COMPILER:指定C++编译器
EXECUTABLE_OUTPUT_PATH:可执行文件输出的存放路径
LIBRARY_OUTPUT_PATH:库文件输出的存放路径
CMake编译工程
CMake目录结构:项目主目录存在一个CMakeLists.txt文件
两种方式设置编译规则:
- 包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeLists.txt通过add_subdirectory添加子目录即可;
- 包含源文件的子文件夹未包含CMakeLists.txt文件,子目录编译规则体现在主目录的CMakeLists.txt中;
编译流程
在 linux 平台下使用 CMake 构建C/C++工程的流程如下:
手动编写 CmakeLists.txt。
执行命令 cmake PATH生成 Makefile ( PATH 是顶层CMakeLists.txt 所在的目录 )。
执行命令make 进行编译。
# important tips
. # 表示当前目录
./ # 表示当前目录
.. # 表示上级目录
../ # 表示上级目录
两种构建方式
内部构建(in-source build):不推荐使用
内部构建会在同级目录下产生一大堆中间文件,这些中间文件并不是我们最终所需要的,和工程源文件放在一起会显得杂乱无章。
## 内部构建
# 在当前目录下,编译本目录的CMakeLists.txt,生成Makefile和其他文件
cmake .
# 执行make命令,生成target
make
外部构建(out-of-source build):推荐使用
将编译输出文件与源文件放到不同目录中
## 外部构建
# 1. 在当前目录下,创建build文件夹
mkdir build
# 2. 进入到build文件夹
cd build
# 3. 编译上级目录的CMakeLists.txt,生成Makefile和其他文件
cmake ..
# 4. 执行make命令,生成target
make
CMake代码实践
针对第五章写的两个小项目来写对应的CMakeLists.txt
最小CMake工程
# Set the minimum version of CMake that can be used
cmake_minimum_required(VERSION 3.0)
# Set the project name
project (HELLO)
# Add an executable
add_executable(hello_cmake main.cpp)
多目录工程 – 直接编译
cmake_minimum_required(VERSION 3.0)
project(HELLOWORLD)
#对应 -Iinclude
include_directories(include)
#main_cmake 是输出文件名
add_executable(main_cmake main.cpp src/swap.cpp)
多目录工程 – 生成库编译
# Set the minimum version of CMake that can be used
cmake_minimum_required(VERSION 3.0)
#project name
project(SWAP_LIBRARY)
#add compile options
add_compile_options("-Wall -std=c++11")
#set CMAKE_BUILD_TYPE
set( CMAKE_BUILD_TYPE Debug )
# set output binary path
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
############################################################
# Create a library
############################################################
#Generate the static library from the library sources
add_library( swap_library STATIC src/Swap.cpp )
target_include_directories( swap_lib PUBLIC ${PROJECT_SOURCE_DIR}/include )
############################################################
# Create an executable
############################################################
# Add an executable with the above sources
add_executable( swap_01 main.cpp )
# link the new swap_01 target with the swap_lib target
target_link_libraries( swap_01 swap_liby )
CMake完整项目
.
│ CMakeLists.txt
│ main.cpp
│ myexe.exe
│
├─build
├─include
│ Gun.h
│ Solider.h
│
└─src
Gun.cpp
Solider.cpp
main.cpp
#include "Gun.h"
#include "Solider.h"
void test(){
Solider solider("xusanduo");
solider.addGun(new Gun("AK47"));
solider.addBulletToGun(20);
solider.fire();
}
int main(){
test();
return 0;
}
Gun.h
#pragma once
#include<string>
class Gun{
public:
Gun(std::string type){
this->_bullet_count = 0;
this->_type = type;
}
void addBullet(int bullet_num);
bool shoot();
private:
int _bullet_count;
std::string _type;
};
Solider.h
#pragma once
#include<string>
#include "Gun.h"
class Solider{
public:
Solider(std::string name);
void addBulletToGun(int num);
bool fire();
void addGun(Gun *ptr_gun);
~Solider();
private:
std::string _name;
Gun * _ptr_gun;
};
Gun.cpp
#include "Gun.h"
#include<iostream>
using namespace std;
void Gun::addBullet(int bullet_num){
this->_bullet_count += bullet_num;
}
bool Gun::shoot(){
if (this->_bullet_count <= 0)
{
cout << "there is no bullet !" << endl;
return false;
}
this->_bullet_count -= 1;
cout << "shoot successfully" << endl;
return true;
}
Solider.cpp
#include "Solider.h"
Solider::Solider(std::string name){
this->_name = name;
this->_ptr_gun = nullptr;
}
void Solider::addGun(Gun *ptr_gun){
this->_ptr_gun = ptr_gun;
}
void Solider::addBulletToGun(int num){
this->_ptr_gun->addBullet(num);
}
bool Solider::fire(){
this->_ptr_gun->shoot();
return true;
}
Solider::~Solider(){
if(this->_ptr_gun == nullptr){
return;
}
delete this->_ptr_gun;
this->_ptr_gun = nullptr;
}
- 命令行编译
g++ .\main.cpp .\src\Gun.cpp .\src\Solider.cpp -Iinclude -o myexe
- cmake编译
CMakeLists.txt文件
cmake_minimum_required(VERSION 3.0)
project(SOLIDER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_BUILD_TYPE Debug)
include_directories(include)
#或者include_directories(${CMAKE_SOURCE_DIR}/include)
add_executable(myexe main.cpp src/Gun.cpp src/Solider.cpp)
编译
cd build
cmake ..
make
当更改文件后 直接用make命令构建即可 make会只编译修改的文件
调试步骤launch.json和tasks.json
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "输入程序名称,例如 ${workspaceFolder}/a.exe", //可执行文件
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}", //进入当前工作目录
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/path/to/gdb", //gdb路径
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build" //调试之前执行的任务 一般是生成exe文件
}
]
}
tasks.json
{
"version": "2.0.0",
"options": {
"cwd": "${workspaceFolder}/build" #进入build目录
},
"tasks": [
{
"type": "shell", #第一个task
"label": "cmake",
"command": "cmake",
"args": [
".."
]
},
{
"label": "make", #第二个task
"group": {
"kind": "build",
"isDefault": true
},
"command": "mingw32-make.exe", #win10下是mingw32.make linux下是make
"args": [
]
},
{
"label": "Build", #task任务名 和launch.json中的preLaunchTask对应
"dependsOrder": "sequence", #顺序执行task任务
"dependsOn":[
"cmake",
"make"
]
}
]
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/168517.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...