环境:Ubuntu16.04
编译
对于C语言,gcc
1.-o
- 作用:指定输出文件的名称。
- 示例:
gcc -o my_program source.c
会将编译结果输出为my_program
(而不是默认的a.out
)。
2.-c
- 作用:只进行编译,不进行链接。生成目标文件(
.o
),用于后续的链接。 - 示例:
gcc -c source.c
会将源代码文件source.c
编译成目标文件source.o
。
3.-D
- 作用:定义宏。相当于在代码中使用
#define
。可以在编译时为预处理器定义宏。 - 示例:
gcc -DDEBUG source.c
会在编译过程中定义DEBUG
宏,可以在代码中使用#ifdef DEBUG
来控制调试代码。
4.-O
- 作用:启用优化选项。后面可以加上优化级别(如
-O1
,-O2
,-O3
等),影响代码优化的程度。 - 示例:
gcc -O2 source.c
会启用中等程度的优化。
5.-e
- 作用:指定程序的入口点。通常用于指定链接时的起始函数名,默认情况下,程序从
main()
开始执行。 - 示例:
gcc -e start source.c
会将start
作为程序的入口点,而不是默认的main
。
6.-E
- 作用:只运行预处理阶段,不进行编译或链接。输出预处理后的代码。
- 示例:
gcc -E source.c
会输出经过预处理后的代码(去掉宏定义等预处理内容)。
7.-Wall
- 作用:启用所有常见的警告信息。帮助开发者发现潜在的错误或不推荐的代码用法。
- 示例:
gcc -Wall source.c
会显示所有常见的编译警告。
8.-g
- 作用:生成调试信息。用于调试时,包含源代码的行号和其他调试信息。
- 示例:
gcc -g source.c
会生成包含调试信息的可执行文件,便于使用调试器(如gdb
)调试。
9.-L
- 作用:指定库文件搜索路径。当链接时,编译器会在指定的路径中查找库文件。
- 示例:
gcc -L/usr/local/lib -o my_program source.c
会让链接器在/usr/local/lib
目录中查找库文件。
10.-l
- 作用:指定要链接的库文件。
-l
后面跟库的名称(不需要加前缀lib
和后缀.a
或.so
)。 - 示例:
gcc -o my_program source.c -lm
会链接数学库libm
(libm.so
或libm.a
)。
11.-v
- 作用:显示详细的编译过程,包括编译器的版本信息、命令行参数、编译器如何调用预处理器、编译器、链接器等信息。
- 示例:
gcc -v source.c
这会打印出gcc
的详细信息以及它执行的每一步。
12.-I
- 作用:指定一个目录作为头文件的搜索路径。当编译器遇到
#include
指令时,会在该目录中查找头文件。 - 示例:
gcc -I/usr/local/include source.c
这会让编译器在/usr/local/include
目录中查找头文件。
13.-M
- -M 生成.c文件与头文件依赖关系以用于Makefile,包括系统库的头文件
14.-MM
- -MM 生成.c文件与头文件依赖关系以用于Makefile,不包括系统库的头文件
对于C++,编译命令:
g++ main.c -std=c++11 -o app
调试
gcc 1.c -g -o app
gdb app
注:如果想进行调试,必须加-g,否则会出现以下情况:
- 进入调试:gdb 可执行文件名字
- 退出调试:quit(q)
- 查看代码:list(l) 行号(注:list显示10行代码,从当前行开始,上下一共10行)
- 开始调试:start(停在main函数的第一行)
- 逐过程:next(n) (逐过程,把函数当成一条语句,不进入函数,继续执行下一条语句)
- 逐语句:step(s) (逐语句,有函数跳到函数里面去执行)
- 继续执行上一条命令:回车 (例如我们上一次执行s命令,按下回车,继续执行s命令)
- 查看变量值:p 变量名
- 持续监控变量:display 变量名
- 结束持续监控变量:undisplay 变量编号
- 开始调试:run(运行到第一个断点处,如果没有断点则直接运行到函数结尾)
- 下断点:break(b) 行号/函数名
- 查看断点信息:info breakpoints
- 继续运行到下一个断点处:continue(c)
- 临时禁用断点:disable 断点编号
- 取消禁用断点:enable 断点编号
在 Linux 中使用 gdb
调试时,可以通过生成 core dump 文件来帮助诊断程序崩溃时的状态。core dump 文件就是程序产生异常退出时,保留异常信息的文件。
makefile
makefile文件(项目管理工具),是GNU工具链的一部分。
一、优点:
- 重用性极强(一次编写终身受益),可以反复使用管理不同的项目
- 便捷的编译管理代码,不用每次书写复杂的编译命令
- 节省编译时间
- 编译时间分为:编译期(预编译、编译、汇编)+链接期(把所有的.o文件链接生成可执行文件)
- 编译期:源文件.c编译生成.o文件
- 第一次编译的时候不会节省编译时间,会保存所有生成的中间文件.o文件,下一次编译的时候只编译修改的源文件,重新生成.o文件,没有修改的源文件直接使用保存的.o文件,一起链接生成可执行文件。
- 怎么判断源文件是否被修改?比较源文件的修改时间和.o文件的生成时间,如果源文件的修改时间比.o文件的生成时间更新,说明生成.o文件以后源文件又被修改过,需要重新编译。
二、命名:必须以makefile或Makefile命名
三、注释:#
四、执行makefile文件:make
五、makefile三要素:
- 目标:完成编译,生成可执行文件,可执行文件的名字就是目标
- 依赖:源文件或者资源文件根据依赖生成目标要执行的命令
- 命令:根据依赖生成目标要执行的命令
目标:依赖
命令(命令前用Tab键)
makefile使用示例:
示例一:
执行make命令即可。
示例二:
makefile执行原理和注意事项:
- 自顶向下建立依赖关系
- 默认只有一个最终目标,可以有多个中间目标
makefile变量定义和使用
1、自定义变量
- 没有数据类型,默认都是字符串类型
- 变量名可以由字母、数字、下划线构成,不能以数字开头,为了与高级语言区分,一般都使用全大写
- 使用:$(变量名)
2、内置
- $@:表示目标名,随着目标名字的变化而变化
- $^:表示所有依赖项
- $<:表示第一个依赖项
示例三:
如上,当我们只修改了makefile文件,其余的没有进行修改时,会提示当前已是最新,这是我们只需要删除所有.o文件,重新执行make命令即可。
内置函数和内建语法:
- wildcard文件名处理函数:获取某个路径下的所有文件名
- SOURCEFILE=$(wildcard *.c)
#获取当前路径下所有.c文件的名字,存到变量SOURCEFILE中
#SOURCEFILE=main.c add.c sub.c des.c mul.c- patsubst字符串处理函数
DFILE=$(patsubst %.c,%.o,$(SOURCEFILE))
#使用patsubst把SOURCEFILE里面的所有.c文件名字变成.o文件
#DFILE=main.o add.o sub.o des.o mul.o
示例四:
示例三中代码可改写成以下形式:
常用变量
- TARGET=myapp#存储目标名字
- cc=gcc#用于存储编译器版本
- INCLUDE_PATH=../include#储头文件路径
- LIBRARY_PATH=../lib#存储库文件路径
- INSTALL_PATH=/usr/bin#存储安装路径
- CFLAGS=-I$(INCLUDE_PATH) -c -Wall#存储编译选项(或加-g...)
- CPPFLAGS=-D#预处理选项
示例五:
示例四中代码可改写成以下形式,提高makefile的复用性,后续只需要对宏进行修改即可。
功能目标:没有依赖,只有命令
- 删除
clean:
rm -rf $(DFILE) $(TARGET)
- 安装
install:
sudo cp $(TARGET) $(INSTALL_PATH)
- 卸载
uninstall:
sudo rm -rf $(INSTALL_PATH)/$(TARGET)
- 输出
output :
echo $(INSTALL PATH)/$(TARGET)
示例六:
执行clean功能:make clean
如有错误,欢迎交流指正!