1 Linux下的C++
环境搭建
gcc编译C程序,g++编译C++程序
gdb调试工具,cmake构建工具
下载
sudo yum install gcc
sudo yum install gcc-c++
sudo yum install gdb
sudo yum install cmake
查看版本
gcc -v
g++ -v
gdb -v
cmake --version
卸载
sudo yum remove gcc
sudo yum remove gcc-c++
sudo yum remove gdb
sudo yum remove cmake
编译
一步到位
g++ -o build hello.cpp //生成名为build的可执行文件
g++ hello.cpp //默认生成名为a.out的可执行文件
分步编译
ESc-->iso
- 预处理
g++ -E -o a.i hello.cpp - 编译
g++ -S -o a.s a.i - 汇编
g++ -c -o a.o a.s - 链接
g++ -o hello a.o
联合编译
g++ -o build main.cpp solve.cpp:将main.cpp和solve.cpp源文件联合编译
GDB
警告不影响可执行文件产生,警告可以忽略,错误不会产生可执行文件
常用指令
g++ -g -o build hello.cpp:编译产生调试信息(必要)gdb build:进入gdb调试q/quit:退出gdb调试run:运行可执行程序,直到遇到断点l/list:展示程序相关信息,默认前十行,继续使用list会展示剩下的部分l 6,10:展示从6到10行l funct:展示funct函数周围
break 3/b 3:在第3行设置断点break funct:在funct函数内第一条语句设置断点info break:查看断点信息delete breakpoint 1:删除编号为1的断点
next/n:执行下一条语句,若下一条语句是函数执行函数内所有语句continue/c:从当前语句执行到下一个断点或程序结束step/s:单步进入当前函数print i:打印变量i的内容print &i:打印变量i的地址信息
set variable i=10:设置变量i的值为10
使用技巧
shell 终端指令:在gdb中执行shell指令set logging on:将日志内容保存到当前目录的gdb.txt文件watch i:为变量i添加监视,当i的值改变时显示旧值和新值watch 0x7fffffffe3bc:为0x7fffffffe3bc地址添加监视
调试出错程序
gdb core_build_1793_1767752286:查看程序build出错原因
不生成core文件
demesg:显示开机信息,查看是否转储core- core文件大小限制
ulimit -a:查看所有Linux限制内容ulimit -c unlimited设置core文件大小为无限制- 添加
ulimit -c unlimited到/etc/profile永久设置
- 保存位置
echo "./core-%e-%p-%t" > /proc/sys/kernel/core_pattern:临时设置保存路径为当前路径,%e可执行文件名,%p进程id,%t时间戳- 添加
kernel.core_pattern=./core-%e-%p-%t到/etc/sysctl.conf并sysctl -p使配置生效,永久设置
调试运行中的进程
./build &:后面加&使程序在后台运行,然后显示作业号和进程号gdb -p 1754:调试进程号为1754的进程pidof build:查看程序进程号kill -9 1754:强制杀死1754进程
库
Linux下静态库为
.a文件,动态库为.so文件
Windows下静态库为.lib文件,动态库为.dll文件
库是二进制文件
静态库
编译时库和源文件一起生成可执行程序,每个可执行程序单独拥有一个静态库,体积大,效率高
- 编译:
g++ -c -o add.o add.cpp:编译源文件add.cpp为二进制文件add.o - 生成:
ar -crs libadd.a add.o:将add.o编译生成静态库文件libadd.a,ar生成静态库,-c创建静态库,-r插入到库中或替换同名文件,-s重置静态库索引 - 使用:
g++ main.cpp -L 库的路径 -l库名 -I 头文件路径 -o build01:编译源文件时使用静态库- 比如:
g++ main.cpp -L . -ladd -I . -o build01,库和头文件都在同目录下 - 使用多个静态库:
g++ main.cpp -L . -ladd -I . -L . -lsub -I . -o build02,使用了libadd.a和libsub.a - 多路径编译:
g++ main.cpp -L ../lib -ladd -I ../haead -o ../build03
- 比如:
动态库
编译时库中相关函数的索引表和源文件一起生成可执行程序,每个可执行程序只有函数的索引表,体积小,效率低
- 编译:
g++ -fPIC -c add.cpp -o add.o:编译源文件add.cpp为二进制文件add.o - 生成:
g++ -shared add.o -o libadd.so:生成动态库文件
编译和生成合并:g++ -fPIC -shared -o libadd.so add.cpp - 使用:
g++ main.cpp -L 库的路径 -l库名 -I 头文件的路径 -o build
动态库加载失败
error while loading shared libraries: libadd.so: cannot open shared object file: No such file or directory
法一:把自己的库放到系统的库文件目录中/lib64或/usr/lib64
法二:设置全局变量
export LD_LIBRARY_PATH=库的路径,比如设置路径为./mylib,要永久设置需要添加到/etc/profile(全局)或~/.bashrc(用户)
第三方库
C/C++默认链接标准输入输出库,其他库需要手动链接
-l库名
g++ main.cpp -lc -lm -lpthread -o build01:-lc标准c库,-lm数学库,-lpthread线程库
头文件
- 将多个头文件包含在一个头文件
myHead.h中 - 将
myHead.h移动到/usr/include目录下 - 源文件直接包含头文件
#include <myHead.h>
Makefile和CMake
Makefile
名为
Makefile的管理项目的文本文件,M一般大写,如果是小写系统默认执行小写的
相当于脚本
面向依赖:
.exe依赖于.o,.o依赖于.s,.s依赖于.i,.i依赖于.cpp
编写Makefile
build01:hello.o
g++ hello.o -o hello
hello.o:hello.s
g++ -c hello.s -o hello.o
hello.s:hello.i
g++ -S hello.i -o hello.s
hello.i:hello.cpp
g++ -E hello.cpp -o hello.i
clear:
rm build01 hello.[^cpp]
简化:
build01:hello.o
g++ -o build01 hello.o
hello.o:hello.cpp
g++ -c -o hello.o hello.cpp
clear:
rm build01 hello.[^cpp]
执行Makefile
make:默认从第一个目标开始执行,直到解决所有依赖make 目标:从指定的目标开始执行,直到解决所有依赖
规则
构成依赖关系
目标:依赖
命令
- 一个规则必须要有一个目标
- 可以没有依赖,只实现某种操作
- 可以没有命令,只描述依赖关系
比如:all:build01
目标
- 默认目标是第一个目标
- 一个规则可以有多个目标
- 一个目标可以间接拥有多个规则,比如:
all:test01 all:test02 test01: @echo "hello" test02: @echo "world" - 伪目标:相当于标签,没有依赖,无条件执行,不会生成文件,比如:
.PHONY:clear #设置伪目标 rm build01 hello.[^cpp]
依赖
- 文件时间戳:
- 根据时间戳来判断依赖是否要进行更新
- 所有文件都更改过,则对所有文件进行编译,生成可执行程序
- 在上次make之后修改过的cpp文件,会被重新编译
- 在上次make只写修改过的头文件,依赖该头文件的目标依赖也会重新编译
- 一个目标可以有多个依赖
命令
- 以制表符开头的shell指令
- 每条命令开一个进程,命令执行完make会检查该命令的返回码,返回成功继续执行后面的命令,返回失败终止当前规则并退出
- 并发执行:
make -j4:开4个线程执行time make:执行make时显示执行时间
模式匹配
%:Makfile规则通配符$@:目标$^:依赖$<:第一个依赖*:普通通配符
all:build01
build01:main.o add.o
g++ -o $@ $^
%.o:%.cpp
g++ -c -o $@ $^
clean:
rm *.o build01
变量
相当于宏
- 变量定义:
变量名=值 +=:追加赋值?=:条件赋值,没有值就赋值,有值就不赋值- 使用变量:
$(变量名)或${变量名} :=:立即展开变量=:延迟展开变量,用最后的赋值展开- 一般命令用延迟展开,目标和依赖用立即展开
- 命令行赋值:
make test AA="hello"
var1?=main.o add.o
CC = g++
all:build01
build01:$(var1)
$(CC) -o $@ $^
%.o:%.cpp
$(CC) -c -o $@ $^
clean:
rm *.o build01
test:
@echo "----$(AA)----"
条件控制
var1?=main.o add.o
ifeq ($(COMPILE),g++)
CC=g++
else
CC=gcc
endif
all:build01
build01:$(var1)
$(CC) -o $@ $^
%.o:%.cpp
$(CC) -c -o $@ $^
clean:
rm *.o build01
外部给COMPILE赋值:make all COMPILE=g++
CMake
CMake是跨平台构建工具,自动添加源文件到对应平台的构建工具
基本语法
指令(参数1 参数2...):参数之间用逗号或空格隔开,指令不分大小写- 在if控制语句中变量取值不需要用
$() - 语句末尾没有分号
基本指令
cmake_minimum_required(VERSION 4.0):指定CMake最小版本支持为4.0版本project(TEST CXX):定义项目名称为TEST并指定项目支持的语言为C++set(SRC main.cpp add.cpp):设置变量SRC,值为main.cpp add.cpp,引用变量用${SRC}add_executable(build ${SRC}):依赖${SRC}生成build可执行文件aux_source_directory(./src SRC):将源文件目录下的所有源文件添加到指定变量includ_directories(./head):添加头文件路径,相当于g++中的-I选项link_directories(./lib):添加库文件路径,相当于g++中的-L选项add_library(add SHARED add.cpp):依赖add.cpp生成动态库add_library(add STATIC add.cpp):依赖add.cpp生成静态库
add_compile_options(-Wall -std=c++11):添加-Wall(显示所有警告)和-std=c++11(设置C++版本为11)编译选项target_link_libraries(build add):添加add库到build程序中
基本变量
CMAKE_C_FLAGS:gcc编译选项的值CMAKE_CXX_FLAGS:g++编译选项的值set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11"):在编译选项中追加-std=c++11选项
CMAKE_BUILD_TYPE:编译类型set(CMAKE_BUILD_TYPE Debug):设置编译类型为调试模式set(CMAKE_BUILD_TYPE Release):设置编译类型为发布模式
CMAKE_CXX_STANDARD:C++标准set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON):设置C++11标准
PROJECT_NAME:项目名PROJECT_SOURCE_DIR:项目资源目录EXECUTABLE_OUTPUT_PATH:可执行文件的产生路径
构建项目
内部构建
中间文件产生在项目主目录,杂乱
在项目主目录:
cmake ./:编译CMakeLists.txt,中间文件生成在项目主目录make:编译项目主目录中的Makefile
外部构建
在项目主目录:
mkdir temp:创建./temp目录用来存放临时文件cd ./temp:进入./temp目录cmake ../:编译项目主目录中的CMakeLists.txt,中间文件生成在temp目录make:编译temp目录中的Makefile

浙公网安备 33010602011771号