程序的编译过程
4个步骤:预处理,编译,汇编,链接.
预处理: 检测语法错误,把头文件包含进来,宏展开.
编译:把. c文件转换成汇编文件.s
汇编:把. s文件转换成二进制文件.o
链接:. .o文件+库文件 =可执行程序
gcc -v -o hello hello.c 就可观看到编译的细节.
gcc -c -o a.o a.c //-c 把预处理,编译,汇编 做完 链接不做.
1.Makefile的作用:高效地编译程序,在修改源文件或者头文件,只需要重新编译牵涉到的文件,就可以重新生成APP
(1) 一起编译、链接:
修改过的,没有被修改过的,都一起编译, 文件很多的时候,编译会花销很大时间
gcc main.c sub.c -o
(2)分开编译,统一链接:
修改过的文件,只会重新生成它的 .o 文件
gcc -c main.c -o main.o
gcc -c sub.c -o sub.o
gcc main.o sub.o -o test
Makefile 自动的帮助我们查看哪个文件被修改过,然后编译它链接它
2.Makefile的简单样式:一个简单的Makefile文件包含一系列的“规则”,其样式如:
目标:依赖
命令
如果“依赖文件”比“目标文件”更加薪,那么执行“命令”来重新生成“目标文件”。命令被执行的2个条件:依赖文件比目标文件新,或者是目标文件还没生成。
由简入难的demo
main.c
#include <stdio.h>
extern void s_fun();
int main()
{
printf("Main s_fun\n");
s_fun();
return 0;
}
sub.c
#include<stdio.h>
#include"sub.h"
void s_fun()
{
printf("s_fun, A = %d\n",A);
}
sub.h
#define A 1
void s_fun();
第一个Makefile
test : main.c sub.c sub.h
gcc main.c sub.c -o test
第二个Makefile
make 没有指定目标会去查找第一个目标 test,要想执行第二个目标,需要指定,make clean
test : main.o sub.o
gcc main.o sub.o -o test
main.o : main.c
gcc -c main.c -o main.o
sub.o : sub.c
gcc -c sub.c -o sub.o
clean :
rm *.o test -f
第三个Makefile
如修改了sub.h A 为2 ,重新make 无效,A 仍然为1
test : main.o sub.o
gcc main.o sub.o -o test
%.o : %.c
gcc -c $< -o $@
clean :
rm *.o test -f
第四个Makefile
使修改后的头文件,能够输出 A =2,两个同目标的规则,一个有命令另一个没有命令,它们将合并在一起
test : main.o sub.o
gcc main.o sub.o -o test
%.o : %.c
gcc -c $< -o $@
sub.o : sub.h
clean :
rm *.o test -f
3.先介绍两个Makefile函数
(1)$(foreach var,list,text) 对list 中的每一个元素取出来赋给var,然后把var改为text所描述的形式
objs := a.o b.o
dep_files := $(foureach f, $(objs), .$(f).d) //最终 dep_files := .a.o.d .b.o.d
(2)$(wildcard pattern) pattern 所列出的文件是否存在,把存在的文件都列出来
dep_file := $(wildcard *.c) //最终src_files中列出了当前目录下的所以 .c文件
第五个Makefile
此Makefile不支持子目录下的文件
objs := main.o sub.o
test : $(objs)
gcc main.o sub.o -o test
#需要判断是否存在依赖文件
dep_files := $(foreach f, $(objs), .$(f).d)
#把依赖文件包含进来
dep_files := $(wildcard $(dep_files))
#判断
ifneq ($(dep_files), )
include $(dep_files)
endif
%.o : %.c
gcc -Wp,-MD,.$@.d -c $< -o $@
sub.o : sub.h
#clean :
# rm *.o test -f
distclean :
rm $(dep_files) *.o test -f