本文内容:
1. 编译过程
2. GCC编译器
3. Makefile
4. 使用GDB调试程序
1. 编译过程
![](https://img.haomeiwen.com/i9257371/464f343bdc600074.png)
2. GCC编译器
- 将源文件编译成可执行文件:
$: gcc hello.c
生成的可执行文件名默认为a.out - 用 -o 参数指定输出文件名:
$: gcc hello.c -o hello
此时将会生成可执行文件hello - 编译生成目标文件
参数 -c 用于生成目标文件
$: gcc -c hello.c
将会生成目标文件 hello.o - 也可以多文件编译:
$: gcc -c hello.c test.c main.c
将会生成目标文件 hello.o,test.o,main.o
3. Makefile
3.1 一个小例子
在sock/sock.h, sock/sock.cpp声明定义了类Sock,用于生成服务器端套接字,接受客户端连接;在process/process.h, process/process.cpp中声明定义了类Process, 用于创建新的进程;在main.c 中包含了以上两个头文件,并调用这两个类。
makefile的内容:
main:main.o sock/sock.o process/process.o
g++ -o main main.o sock/sock.o process/process.o
sock.o:sock/sock.cpp sock/sock.h
g++ -c -o sock/sock.o sock/sock.cpp
process.o:process/process.cpp process/process.h
g++ -c -o process.o process/process.cpp
clean:
rm -f main main.o process/process.o sock/sock.o
执行make:
![](https://img.haomeiwen.com/i9257371/885b6a481ad5ca02.png)
执行结果:
在主目录下生成了main.o 和可执行文件main,在sock目录下生成sock.o,在process目录下生成了process.o。
3.2 Makefile规则
makefile的基本规则:
TARGET...:DEPENDEDS...
COMMAND
...
以小例子中的第一条为例:
main是要生成的目标文件TARGET,
main.o sock/sock.o process/process.o是main的依赖文件DEPENDEDS,
g++ -o main main.o sock/sock.o process/process.o
是要执行的命令COMMAND。
- TARGET:可以是可执行文件或目标文件,也可以是一个命令,如clean;
- DEPENDS:执行命令需要的以来条件,若达不到以来条件则不会执行下面的命令,当依赖文件中有文件的时间戳比目标文件新时,就会执行COMMAND命令;
- COMMAND:命令,例如编译、生成库文件、进入目录等,每个命令占一行,每个命令必须以TAB键开始。
3.3 Makefile中的变量
1. 自动变量
常用的自动变量:
变量 | 含义 |
---|---|
$* | 表示目标文件名,不包含扩展名 |
$+ | 表示所有的依赖文件,以空格分开,按顺序排列,包含重复文件 |
$< | 表示依赖项中第一个依赖文件 |
$? | 表示依赖项中所有比目标文件的时间戳晚的以来文件,以空格分开 |
$@ | 目标文件名称 |
$^ | 依赖项中所有不重复的依赖文件,以空格分开 |
2. 用户自定义变量
用户可以自定义变量,节省输入时间,而且便于修改,第一小节中的例子可以改为:
TARGET=main
OBJS=main.o sock/sock.o process/process.o
RM=rm -f
$(TARGET):$(OBJS)
g++ -o $(TARGET) $(OBJS)
$(OBJS):%.o:%.c #表示将OBJS中所有扩展名为.o的文件替换成扩展名为.c的文件
g++ -c $< -o $@
clean:
-$(RM) $(TARGET) $(OBJS)
执行过程:
![](https://img.haomeiwen.com/i9257371/2314725760816d77.png)
3. 预定义变量
暂时不用,待补充
3.4 搜索路径
输入文件时,手动添加目录不仅麻烦而且容易出错,可以使用VPATH变量避免多次输入目录,则上节中的例子可以改为:
VPATH=sock:process
TARGET=main
OBJS=main.o sock.o process.o
RM=rm -f
$(TARGET):$(OBJS)
g++ -o $(TARGET) $(OBJS)
$(OBJS):%.o:%.c #表示将OBJS中所有扩展名为.o的文件替换成扩展名为.c的文件
g++ -c $< -o $@
clean:
-$(RM) $(TARGET) $(OBJS)
不同的目录之间用冒号:分隔,make会自动找到对应的文件并添加目录。
但以上方法编译出的目标文件都放在了当前主目录,因此可以用以下方法将目标文件放到一个目录:
VPATH=sock:process
OBJSDIR=objs
TARGET=main
OBJS=main.o sock.o process.o
RM=rm -f
$(TARGET):$(OBJSDIR) $(OBJS)
g++ -o $(TARGET) $(OBJSDIR)/*.o
$(OBJS):%.o:%.c #表示将OBJS中所有扩展名为.o的文件替换成扩展名为.c的文件
g++ -c $< -o $(OBJSDIR)/$@
clean:
-$(RM) $(TARGET)
-$(RM) $(OBJSDIR)/*.o
3.5 推导规则
使用make编译扩展名为.c的C语言文件时,将源文件编译成目标文件的命令不用给出,因为make编译时会使用默认的规则,只要在makefile里给出需要重建的目标文件名(.o文件),make就会自动为这个文件寻找对应的.c文件,并将其构建为目标文件。
3.6 递归make
暂时不用,待补充
3.7 Makefile中的函数
暂时不用,待补充
4. 使用GDB调试程序
待补充
参考文献
- 《Linux网络编程(第2版)》,宋敬彬等编著。
网友评论