GCC


gcc -E test.c -o test.i | 预处理(-o指定文件名) |
gcc -S test.i -o test.s | 编译 |
gcc -c test.s -o test.o | 汇编 |
gcc test.o -o test | 链接(生成一个可执行程序的软连接) |
gcc test.c -o test | 一条指令可以完成以上所有内容 |
gcc *.c -I(大写的i) include | 由于在main.c中找不到当前文件夹中的头文件,所以用-I指定在include文件夹中找对应的头文件。 |
head.h包含所有运算的函数声明。
以下代码由于程序中没有DEBUG宏,所以不会输出"我被执行"。
#include<stdio.h>int main(){#ifdef DEBUGprintf("我被执行\n");#endifprintf("hello world");return 0;
}
gcc test.c -D DEBUG | 由于局外定义了宏所以会输出"我被执行"。 |
制作静态库:
gcc -c add.c sub.c div.c mult.c -I(大写的i) ./include | 生成add.o sub.o div.o mult.o |
ar rcs libcal.a *.o | 将所有.o文件打包(如果静态库要发布出去要有libcal.a 和 head.h两个文件)。 |
使用静态库:
head.h和libcal.a和main.c在同一个目录。
gcc main.c -o cal -L ./ -l(小写的L) cal | -L指定库路径 -l指定库名称,掐头(lib)去尾(.a) |
./cal | 执行 |
制作动态库:
gcc -c -fpic add.c sub.c mult.c div.c -I(大写的i) ./include | 生成.o文件 |
gcc -shared *.o -o libcal.so | 生成动态库 |
使用动态库:
head.h和libcal.so和main.c要在同一个目录。
gcc main.c -L ./ -l(小写L) cal -o app | 生成app可执行文件 |
./app | 执行 |
当app文件和libcal.so不在同一目录,执行app文件会报错。
解决方案:
一、
sudo vim /etc/ld.so.conf |
添加新路径:动态库所在的路径 |
sudo ldconfig |
二、
sudo ln -s /xxx/xxx/libxxx.so /user/lib/libxxx.so |
makefile
当目录下有makefile文件和一系列.c文件。
gcc *.c -o app | 生成一个app可执行文件。 |
make | 由于上述过程过于繁琐,用make可以自动化编译。(生成.o文件和一个可执行程序) |
make clean | 删除.o文件和那个可执行文件。 |
makefile的编写:
cal:add.c div.c main.c mult.c sub.cgcc add.c div.c main.c mult.c sub.c -o cal
make | 此时会生成cal可执行文件。 |
./cal | 执行cal程序 |
但是以上规则效率太低。
修改:
cal:add.o div.o main.o mult.o sub.ogcc add.o div.o main.o mult.o sub.o -o caladd.o:add.cgcc add.c -cdiv.o:div.cgcc div.c -cmult.o:mult.cgcc mult.c -cmain.o:main.cgcc main.c -csub.o:sub.cgcc sub.c -c
自动变量:
$< | 表示依赖项中第一个依赖文件的名称。 |
$@ | 表示目标文件的名称,包含文件扩展名。 |
$^ | 依赖项中,所有不重复的依赖文件,这些文件之间以空格分开。 |
# 这是一个规则的普通写法
cal:add.o div.o main.o mult.o sub.ogcc add.o div.o main.o mult.o sub.o -o cal# 这是一个规则,用了自动变量
cal:add.o div.o main.o mult.o sub.ogcc $^ -o $@
模式匹配:
# %是一个通配符,匹配的是文件名
%.o:%.cgcc $< -c
以下代码太冗余:
cal:add.o div.o main.o mult.o sub.ogcc add.o div.o main.o mult.o sub.o -o caladd.o:add.cgcc add.c -cdiv.o:div.cgcc div.c -cmult.o:mult.cgcc mult.c -cmain.o:main.cgcc main.c -csub.o:sub.cgcc sub.c -c
修改后:
target=cal
obj=add.o div.o main.o mult.o sub.o$(target):$(obj)gcc $(obj) -o $(target)%.o:%.cgcc -c $^
函数:
一、wildcard
$(wildcard *.c ./sub/*.c) | 返回值格式:a.c b.c c.c d.c e.c f.c ./sub/aa.c ./sub/bb.c |
二、patsubst
src = a.cpp b.cpp c.cpp e.cpp | 接下来要把变量src中的所有文件名的后缀从.cpp替换为.o |
obj = $(patsubst %.cpp, %.o, $(src)) | obj 的值为: a.o b.o c.o e.o |
以下代码还可以优化:
target=cal
obj=add.o div.o main.o mult.o sub.o$(target):$(obj)gcc $(obj) -o $(target)%.o:%.cgcc -c $^
优化后:
target=cal# 搜索磁盘源文件
src=$(wildcard *.c)# 后缀的替换
obj=$(patsubst %.c, %.o, $(src))$(target):$(obj)gcc $(obj) -o $(target)%.o:%.cgcc -c $^
只有当在make后面写clean时才会执行clean
target=cal# 搜索磁盘源文件
src=$(wildcard *.c)# 后缀的替换
obj=$(patsubst %.c, %.o, $(src))$(target):$(obj)gcc $(obj) -o $(target)%.o:%.cgcc -c $^clean:rm $(obj) $(target)
由于当目录中有了clean文件后,再执行make clean会出错,所以要把clean声明为伪目标。
修改后:
target=cal# 搜索磁盘源文件
src=$(wildcard *.c)# 后缀的替换
obj=$(patsubst %.c, %.o, $(src))$(target):$(obj)gcc $(obj) -o $(target)%.o:%.cgcc -c $^.PHONY:clean
clean:rm $(obj) $(target)
现在即使当前目录有clean文件也不影响。
由于mkdir没有管理员权限无法执行,默认往后的所有语句都无法执行
target=cal# 搜索磁盘源文件
src=$(wildcard *.c)# 后缀的替换
obj=$(patsubst %.c, %.o, $(src))$(target):$(obj)gcc $(obj) -o $(target)%.o:%.cgcc -c $^.PHONY:clean
clean:mkdir arm $(obj) $(target)
想要rm执行要在mkdir前面加个-
target=cal# 搜索磁盘源文件
src=$(wildcard *.c)# 后缀的替换
obj=$(patsubst %.c, %.o, $(src))$(target):$(obj)gcc $(obj) -o $(target)%.o:%.cgcc -c $^.PHONY:clean
clean:-mkdir arm $(obj) $(target)
GDB
gcc main.c -g -Wall -o0 -o app | 生成一个调试的可执行文件app |
gdb app | 进入调试的命令 |
l(小写的L) | 查看代码(回车继续往下查看) |
q | 退出 |
set args 1 2 3 | 传入参数1 2 3(如果有函数参数) |
show args | 查看参数 |
run | 运行程序 |
g++ -g *.cpp -o app | 生成调试的可执行文件 |
gdb app | 进入调试的命令 |
l(小写的L) insert.cpp:19 | 查看insert.cpp第19行和上下相关内容 |
l(小写的L) insertSort | 在insert.cpp文件中找到insertSort函数 |
set list 20 | 设置显示行数为20行 |
show list | 查看显示行数 |
l(小写的L) test.cpp:main | 查看到test.cpp里面的main函数 |
b 16 | 在第16行设置断点 |
b if i==5 | 用于例如在for循环里面当i==5时停止 |
b insert.cpp:16 | 在insert.cpp中的第16行设置断点 |
i b | 查看已设置的断点 |
d 1 | 删除第1个断点 |
d 1-2 | 删除第1-2断点 |
d 3 5 | 删除3 和 5断点 |
dis 4 | 设置第4个断点无效 |
dis 6-7 | 设置6-7断点无效 |
ena 4 | 使第4断点生效 |
ena 6-7 | 使6-7断点生效 |
p i | 查看变量i |
p/d i | 以十进制查看变量i |
p/c | 以字符型查看变量i |
p/f | 以浮点数查看变量i |
ptype i | 查看变量i的类型 |
ptype array[i] | 查看array[i]的类型 |
ptype array | 查看array的类型 |
display i | 自动跟踪变量i |
display array[i] | 自动跟踪变量array[i] |
i display | 查看所有的自动跟踪 |
next | 单步调试 |
undisplay 1 | 取消跟踪编号为1的变量 |
disable display 3 | 设置编号为3的变量自动跟踪为无效 |
ena display 3 | 设置编号为3的变量自动跟踪为有效 |
单步调试:
run开始执行程序,一个函数执行的地方打了断点
step | 执行函数体内容 |
finish | 跳出函数体(里面不能有断点,不然跳不出来) |
next | 不执行这个函数体 |
until | 跳出循环体(里面不能有断点,要使它失效或删除) |
set var i=5 | 将变量i的值设为5,可用于for循环中,在for循环打断点,将i值改变 |