学习视频链接
目录
5.2 编写 CMakeLists.txt 构建项目编译规则、使用外部构建,手动编译 CMake 项目
一、安装相应的软件
1.1 安装cmake
sudo apt update 更新软件包来源
sudo apt install cmake 安装cmake
cmake --version 查看是否安装成功
1.2 安装vscode
二、g++编译相关参数
2.1 -g
1、作用
编译带调试信息的可执行文件
2、案例
g++ -g test.cpp -o test
2.2 -O[n]
1、作用
优化源码
2、案例
-O 同时减小代码的长度和执行时间,其效果等价于 -O1
-O0 表示不做优化
-O1 为默认优化
-O2 除了完成 -O1 的优化之外,还进行一些额外的调整工作,如指令调整等
-O3 则包括循环展开和其他一些与处理特性相关的优化工作
选项将使编译的速度比使用 -O 时慢,但通常产生的代码执行速度会更快
g++ -O2 test.cpp -o test
3、测试
2.3 -l 和 -L
1、作用
指定库文件 | 指定库文件路径
2、案例
(1) -l 参数(小写)就是用来指定程序要链接的库,-l 参数紧接着就是库名
在 /lib 和 /usr/lib 和 /usr/local/lib 里的库直接用 -l 参数就能链接
链接 glog 库
g++ -lglog test.cpp -o test
(2) 如果库文件没放在上面三个目录里,需要使用 -L 参数(大写)指定库文件所在目录
-L 参数跟着的是库文件所在的目录名
链接 mytest 库,libmytest.so 在 /home/bing/mytestlibfolder 目录下
g++ -L/home/bing/mytestlibfolder -lmytest test.cpp -o test
2.4 -I
1、作用
指定头文件搜索目录
2、案例
/usr/include 目录一般是不用指定的,gcc 知道去那里找,但是如果头文件不在 /usr/icnclude 里我们就要用 -I 参数指定了,比如头文件放在 /myinclude 目录里,那编译命令行就要加上 -I/myinclude 参数了,如果不加你会得到一个 "xxxx.h: No such file or directory" 的错误。-I 参数可以用相对路径,比如头文件在当前目录,可以用 -I . 来指定
g++ -I/myinclude test.cpp -o test
2.5 警告信息
2.6 设置编译标准和输出文件名
2.7 查看手册
man gcc
三、编译C++项目
3.1 打开vscode
3.2 编写项目
3.3 编译项目
四、CMake
4.1 简介
cmake 是一个跨平台的安装编译工具,可以用简单的语句来描述所有平台的安装(编译过程)
CMake 是大部分 C++ 开源项目标配
4.2 语法特性介绍
1、基本语法格式
(1) 指令(参数1 参数2 ...)
参数使用括弧括起
参数之间使用空格或分号分开
(2) 指令是大小写无关的,参数和变量是大小写相关的
set(HELLO hello.cpp)
add_executab1e(hello main.cpp hello.cpp)
ADD_EXECUTABLE(he11o main.cpp ${HELLO})
(3) 变量使用 ${} 方式取值,但是在 IF 控制语句中是直接使用变量名
4.3 重要指令和 CMake 常用变量
1、重要指令
(1)cmake_minimum_required 指定 CMake 的最小版本要求
语法:cmake_minimum_required(VERSION versionNumber [FATAL_ERROR])
# CMake 最小版本要求为 2.8.3
2 cmake_minimum_required(VERSION 2.8.3)
(2)project 定义工程名称,并可指定工程支持的语言
语法:project(projectname [CXX] [C] [Java])
# 指定工程名为 HELLOWORLD
project(HELLOWORLD)
(3)set 显式的定义变量
语法:set(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
# 定义 SRC 变量,其值为 sayhe11o. cpp he11o. cpp
set(SRC sayhel1o.cpp he11o.cpp)
(4)include_directories 向工程添加多个特定的头文件搜索路径 --> 相当于指定 g++ 编译器的 -I 参数
语法:include_directories([AFTER | BEFORE] [SYSTEM] dir1 dir2 ...)
# 将/usr/include/myincludefolder 和./include 添加到头文件搜索路径
include_directories(/usr/include/myincludefo1der ./include)
(5)link_directories 向工程添加多个特定的库文件搜索路径 --> 相当于指定 g++ 编译器的 -L 参数
语法:link_directories(dir1 dir2 ....)
# 将/usr/1ib/my1ibfo1der 和./1ib 添加到库文件搜索路径
1ink_directories(/usr/1ib/mylibfolder ./1ib)
(6)add_ library 生成库文件
语法: add_ library(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
# 通过变量 SRC 生成 libhe11o.so 共享库
add_library(he11o SHARED ${SRC})
(7)add_compile_options 添加编译参数
语法:add_compile_options(<option> ...)
# 添加编译参数 -Wa11 -std=c++11
add_compile_options(-Wa11 -std=c++11 -02)
(8)add_executable 生成可执行文件
语法:add_library(exename source1 source2 ... sourceN)
# 编译 main.cpp 生成可执行文件 main
add_executable(main main.cpp)
(9)target_link libraries 为 target 添加需要链接的共享库 ---> 相同于指定 g++ 编译器 -I 参数
语法:target link_libraries(target library1<debug | optimized> library2...)
# 将 he11o 动态库文件链接到可执行文件 main
target_link_libraries(main he11o)
(10)add_subdirectory 向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置
语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
# 将 he11o 动态库文件链接到可执行文件 main
target_link_libraries(main he11o)
(11)aux_source_directory 发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表
语法:aux_source_directory(dir VARIABLE)
# 定义 SRC 变量,其值为当前目录下所有的源代码文件
aux_source_directory(. SRC)
# 编译 SRC 变量所代表的源代码文件,生成 main 可执行文件
add_executable(main ${SRC})
2、CMake 常用变量
(1)CMAKE_C_FLAGS gcc 编译选项
(2)CMAKE_CXX_FLAGS g++ 编译选项
# 在 CMAKE_CXX_FLAGS 编译选项后追加 -std=c++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
(3)CMAKE_ BUILD TYPE编译类型(Debug, Release)
# 设定编译类型为 debug,调试时需要选择 debug
set(CMAKE_BUILD_TYPE Debug)
# 设定编译类型为 release,发布时需要选择 release
set(CMAKE_BUILD_TYPE Release)
(4)CMAKE_BINARY DIR
PROJECT_BINARY_DIR
<projectname>_BINARY DIR
a. 这三个变量指代的内容是一致的
b. 如果是 in source build,指的就是工程顶层目录
c. 如果是 out-of-source 编译指的是工程编译发生的目录
d. PROJECT_BINARY_DIR 跟其他指令稍有区别,不过现在,你可以理解为他们是一致的
(5)CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
<projectname>_SOURCE_DIR
a. 这三个变量指代的内容是一 致的,不论采用何种编译方式,都是工程顶层目录
b. 也就是在 in source build 时,他跟 CMAKE_BINARY_DIR 等变量一致
c. PROJECT_SOURCE_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的
(6)CMAKE_C_COMPILER:指定 C 编译器
(7)CMAKE_CXX_COMPILER:指定 C++ 编译器
(8)EXECUTABLE_OUTPUT_PATH:可执行文件输出的存放路径
(9)LIBRARY_OUTPUT_PATH:库文件输出的存放路径
4.4 CMake 编译工程
CMake 目录结构:项目主目录存在一个 CMakeLists.txt 文件
两种方式设置编译规则:
a. 包含源文件的子文件夹包含 CMakeLists.txt 文件,主目录的 CMakeLists.txt 通过 add_subdirectory 添加子目录即可;
b. 包含源文件的子文件夹未包含 CMakeLists.txt 文件,子目录编译规则体现在主目录 CMakeLists.txt 中;
1、编译流程
在 linux 平台下使用 CMake 构建 C/C++ 工程的流程如下:
a. 手动编写 CmakeLists.txt
b. 执行命令 cmake PATH 生成 Makefile( PATH 是顶层 CMakeLists.txt 所在的目录)
c. 执行命令 make 进行编译
2、两种构建方式
(1)内部构建 (in-source build):不推荐使用
内部构建会在同级目录下产生一大堆中间文件, 这些中间文件并不是我们最终所需要的,和工程源文件放在一起会显得杂乱无章
# 内部构建
# 在当前目录下,编译本目录的 CMakeLists.txt,生成 Makefile 和其他文件
cmake .
# 执行 make 命令,生成 target
make
(2)外部构建 (out-of-source build):推荐使用将编译输出文件与源文件放到不同目录中
# 外部构建
# 1. 在当前目录下,创建 build 文件夹
mkdir build
# 2. 进入到 bui1d 文件夹
cd build
# 3. 编译上级月录的 CMakeLists.txt,生成 Makefile 和其他文件
cmake
# 4. 执行 make 命令,生成 target
make
4.5 实战
1、编写项目
2、编译
运行可执行文件
3、外部构建
4、项目编译
五、使用vscode进行完整项目开发
案例:土兵突击
需求:
1. 兵许三多有一把枪,叫做 AK47
2. 士兵可以开火
3. 士兵可以给枪装填子弹
4. 枪能够发射子弹
5. 枪能够装填子弹--增加子弹数量
开发:
开发枪类
开发士兵类
5.1 合理设置项目目录、编写编译项目源文件
1、设置项目目录
2、编写项目
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;
};
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 << "Thers is no bullet!" << endl;
return false;
}
this->_bullet_count -= 1;
cout << "shoot successfully!" << endl;
return true;
}
Solider.h
#pragma once
#include <string>
#include "Gun.h"
class Solider
{
public:
Solider(std::string name);
~Solider();
void addGun(Gun *ptr_gun);
void addBulletToGun(int num);
bool fire();
private:
std::string _name;
Gun *_ptr_gun;
};
Solider.cpp
#include "Solider.h"
using namespace std;
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()
{
return(this->_ptr_gun->shoot());
}
Solider::~Solider()
{
if(this->_ptr_gun==nullptr)
{
return;
}
delete this->_ptr_gun;
this->_ptr_gun = nullptr;
}
main.cpp
#include "Gun.h"
#include "Solider.h"
void test()
{
Solider sanduo("xusanduo");
sanduo.addGun(new Gun("AK47"));
sanduo.addBulletToGun(20);
sanduo.fire();
}
int main(void)
{
test();
return 0;
}
3、编译项目
5.2 编写 CMakeLists.txt 构建项目编译规则、使用外部构建,手动编译 CMake 项目
给编译添加参数