Linux-3


Makefile

1. 简介

  1. Makefile文件定义了一系列规则来指定文件的编译规则,比如先编译哪些文件后编译哪些文件/哪些文件需要重新编译等。实际工程中,单个项目中会含有多个源文件,如果手动进行编译过于麻烦,而Makefile则实现了编译自动化,通过编写/修改Makefile文件,从而只需要一个指令即可实现文件的自动编译。

  2. 命名规则:makefile/Makefile.

  3. 书写规则

    • 单个makefile文件可以有若干个规则

      目标 ...: 依赖 ...
          命令 (shell命令)
          ...
      • 目标:最终要生成的文件
      • 依赖:生成目标所需要的文件或目标
      • 命令:通过执行命令对依赖操作生成目标(命令前必须要有Tab缩进.)
  4. 实例

    app: main.o minus.o plus.o multi.o divi.o
            gcc main.o minus.o plus.o multi.o divi.o -o app
    
    minus.o: minus.c
            gcc -c minus.c -o minus.o
    
    plus.o: plus.c
            gcc -c plus.c -o plus.o
    
    multi.o: multi.c
            gcc -c multi.c -o multi.o
    
    divi.o: divi.c
            gcc -c divi.c -o divi.o
    
    main.o: main.c
            gcc -c main.c -o main.o

2. 工作原理

  1. 执行命令前,先检查规则中的依赖是否存在:

    • 若存在,则执行命令
    • 若不存在则向下查找是否有命令用于生成该依赖,若存在则运行该命令
    • 其他规则一般是为第一条规则服务,即默认执行第一条规则,如果其下的命令与第一条规则无关,则不会执行该命令。
  2. 检测更新:减少对其他未修改的文件的编译,提高编译效率

    • 如果规则的依赖比目标生成时间更晚,则需要重新生成目标。
    • 如果规则的依赖比目标生成时间更早,则无需运行该规则。

3. 变量

  1. 自定义变量

    变量名=变量值:var=hello

  2. 预定义变量

  • AR: 归档维护程序的名称,默认值为ar
  • CC:c编译器的名称,默认为cc
  • CXX: C++编译器的名称,默认为g++
  • $@:目标的完整名称
  • $<:第一个依赖文件的名称
  • $^:所有依赖文件

如:

app: main.c a.c b.c c.c
      gcc -c main.c a.c b.c c.c

等价于
app: main.c a.c b.c c.c
      $(CC) -c $^ -o $@

  1. 获取变量值:$(变量名)

  2. 实例

    # 定义变量
    src=main.o minus.o plus.o multi.o divi.o
    target=app
    $(target): $(src)
            $(CC) $(src) -o $(target)
    
    %.o:%.c
            $(CC) -c $< -o $@

4. 函数

  1. $(wildcard PATTERN ...)

    • 功能:获取指定目录下指定类型的文件列表
    • 参数:PATTERN为某个或多个目录下的对应某种类型的文件,如果有多个文件则用空格间隔
    • 返回:得到若干个文件的文件列表,其中文件名之间用空格间隔
  2. $(patsubst <pattern>, <replacement>,<text>)

    • 功能:查找<text>中的单词(以空格、Tab、回车、换行为间隔)是否符合<pattern>,如果匹配,则以<replacement>替换。
    • <pattern>可以包括%通配符,表示任意长度的字符串
    • 返回:函数返回替代后的字符串
  3. clean:无需任何依赖

  4. 实例

    # 定义变量
    src=$(wildcard./*.c)
    objs=$(patsubst %.c, %.o,$(src))
    target=app
    $(target): $(objs)
            $(CC) $(objs) -o $(target)
    
    # 编译生成依赖
    %.o:%.c
            $(CC) -c $< -o $@
    
    # 清除依赖文件
    .PHONY:clean    # 伪目标
    clean:
            rm $(objs) -f

文章作者: Vyron Su
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Vyron Su !