Makefile的基本使用

1、为什么要使用makefile

  • 在编译项目时,gcc相关参数非常多,如gcc *.c -I include -Wall -g -03 -D DEBUG -…..
  • 这是一个代码管理工具,外部编译时只需要执行makefile即可
  • 屏蔽编译的复杂过程,源代码以最简单的方式生成可执行程序

2、makefile的规则

  • 三要素:目标、依赖、命令
  • 第一条规则是用来生成终极目标的规则
    • 如果规则中的依赖不存在,向下寻找其他的规则;
    • 更新机制:比较的是目标文件和依赖文件的时间;
  • 两个函数:
    • 查找指定目录下,指定类型的文件:
    • src=$(wildcard ./*.c)
    • 匹配替换函数
    • obj=$(patsubst %.c, %.o, $(src)) // 将.c文件重命名为.o文件
  • 三个自动变量
    • $<:规则中的第一个依赖
    • $^:规则中的所有依赖
    • $@:规则中的目标
  • 模式规则
    • %.o:%.c
    • gcc -c %< -o $@

3、几个示例版本

  • 版本一、最简单的makefile
    #冒号前为目标,后面为依赖
    app:main.c add.c sub.c
    
    #加tab缩进后面写的内容为命令
    gcc *.c -g -o main.out
    
  • 使用make命令执行makefile中的内容

  • 版本二、最简单的makefile等价于:

    app:main.o add.o sub.o
    gcc main.o add.o sub.o -g -o main.out
    
    main.o:main.c
    gcc -c main.c
    
    add.o:add.c
    gcc -c add.c
    
    sub.o:sub.c
    gcc -c sub.c
    
  • 分依赖的好处在没有修改过的地方不会重复编译

  • 第一条为终级目标,向下寻找依赖,向上执行命令

  • 版本三、使用变量继续优化,使用变量

    obj=main.o add.o sub.o
    target=app
    $(target):$(obj)
    gcc $(obj) -o $(target)
    
    %.o:%.c
     gcc -c $< -o $@
    
    #makefile中的自动变量,只能在命令中使用
    #$<:第一个依赖
    #$@:规则中的目标
    #$^:规则中的所有依赖
    #gcc $(obj) -o $(target)还可以写成gcc $^ -o $@
    
  • 版本四、使用函数来动态编译
    #目标变量
    target = app
    
    #依赖变量
    #obj = main.o add.o sub.o
    #依赖变量可通过函数wildcard实现获取,函数名后面直接跟参数
    #1、获取所有.c文件
    src = $(wildcard ./*.c)
    #2、将所有的.c替换成.o,使用函数patsubst
    obj = $(patsubst %.c, %.o, $(src))
    
    #终极目标,生成app
    $(target):$(obj)
    gcc $(obj) -o $(target)
    
    #中间目标通用公式
    %.o:$.c
    #$< 表示第一个依赖
    #$@ 表示规则中的目标
    gcc -c $< -o $@
    
    #添加一个伪目标(不比较生成文件的新旧),清理旧文件
    .PHONY:clean
    clean:
    #命令前面加个“-”表示如果执行失败直接忽略,否则将在当前停止
    -rm -f $(target) $(obj)
    

Leave a Reply