[Linux工具] Makefile

[复制链接]
发表于 2025-11-15 19:43:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×


简介

Linux的make步伐用来自动化编译大型源码,很多时间,我们在Linux下编译安装软件,只必要敲一个make就可以全自动完成,非常方便。
make能自动化完成这些工作,是由于项目提供了一个Makefile文件,它负责告诉make,应该怎样编译和链接步伐。
Makefile相称于Java项目的pom.xml,Node工程的package.json,Rust项目的Cargo.toml,差异之处在于,make固然最初是针对C语言开发,但它实际上并不限定C语言,而是可以应用到恣意项目,乃至不是编程语言。别的,make重要用于Unix/Linux情况的自动化开发,把握Makefile的写法,可以更好地在Linux情况下做开发,也可以为后续开发Linux内核做好预备。
在本教程中,我们将由浅入深,一步一步学习怎样编写Makefile,完全针对零根本小白,只必要提前把握怎样利用Linux下令。
安装make

在Linux(Ubuntu)体系中,我们可以利用包管理工具直接安装make以及GCC工具链。比方在Ubuntu下,利用以下下令:
  1. $ sudo apt update
  2. $ sudo apt install build-essential
复制代码
安装完成后,可以输入以下下令验证安装是否乐成:
  1. $ make -v
  2. GNU Make 4.3
  3. $ gcc --version
  4. gcc (Ubuntu ...) 11.4.0
复制代码
如许,我们就乐成地安装了make,以及GCC工具链。
Makefile根本

在Linux情况下,当我们输入make下令时,它就在当前目次查找一个名为Makefile的文件,然后,根据这个文件界说的规则,自动化地实行恣意下令,包罗编译下令。
Makefile由多少条规则(Rule)构成,每一条规则指出一个目的文件(Target),多少依靠文件(Prerequisites),以及天生目的文件的下令。规则的根本格式如下:
  1. 目标文件: 依赖文件1 依赖文件2 ...
  2.     命令
复制代码
紧接着,以Tab开头的是下令,用来天生目的文件。下令可以是任何Shell下令,如gcc、cp、mv等。以#开头的是表明,会被make下令忽略。
编译C语言步伐

下面是一个典范的Makefile,用于编译C语言步伐:
  1. BIN=code          # 目标文件
  2. CC=gcc            # 编译器
  3. SRC=$(wildcard *.c)
  4. # 所有的.c文件
  5. OBJ=$(SRC:.c=.o)  # 替换为.o文件
  6. LFLAGS=-o
  7. FLAGS=-c
  8. RM=rm -f          # 删除方式
  9. $(BIN): $(OBJ)
  10.     @$(CC) $(LFLAGS) $@ $^
  11. %.o: %.c
  12.     @$(CC) $(FLAGS) $<
  13. .PHONY: clean
  14. clean:
  15.     $(RM) $(OBJ) $(BIN)
复制代码
在这个Makefile中:

  • BIN=code:变量 BIN 的值是 code,体现目的文件名。
  • CC=gcc:变量 CC 的值是 gcc,体现所利用的编译器。
  • SRC=$(wildcard *.c)
    :SRC 体现当前目次下全部的 .c 文件,利用 wildcard 函数动态天生。
  • OBJ=$(SRC:.c=.o):将 SRC 中的 .c 文件名更换为 .o,体现目的文件对应的中心文件(对象文件)。
  • LFLAGS=-o:链接选项,指定输出文件名。
  • FLAGS=-c:编译选项,用于天生中心文件。
  • RM=rm -f:删除下令,用于整理目的文件和中心文件。
  • $(wildcard *.c) 用于匹配当前目次下的全部.c文件。
  • $(SRC:.c=.o) 将全部的.c文件更换为.o文件。
  • $@ 体现目的文件。
  • $< 体现第一个依靠文件。
  • $^ 体现全部依靠文件。
  • .PHONY 声明clean为伪目的,克制与同名文件辩说。
实行make即可编译,实行make clean可整理天生的文件。
**注意:**如果在修改文件内容,但是其他文件没有改变内容(Modify time)没有更新,则未改变的文件不会举行重新编译,大概会造成步伐出现题目。以是当项目出现题目的时间可以对项目举行重新创建,以此办理题目。
利用隐式规则

Makefile支持很多内置的隐式规则,比方编译C语言步伐的规则:
  1. %.o: %.c
  2.     $(CC) $(FLAGS) $<
复制代码
寄义:

  • 将每个 .c 文件编译为对应的 .o 文件(对象文件)。
  • $< 体现第一个依靠文件。
以是该规则会使*.c从第一个开始,逐个编译为对应的.o文件。
小结:隐式规则让Makefile更轻巧,很多情况下不必要显式界说规则。
利用变量

赋值情势 =

这种赋值在剖析时是耽误睁开的。也就是说,右侧的值在被利用时才会被盘算,左值变为变量来利用。这种赋值方式是 GNU Make 的尺度情势。
比方:
  1. SRC=$(wildcard *.c)
复制代码
变量可以进步Makefile的可读性和可维护性。比方:
  1. CC=gcc
  2. CFLAGS=-Wall -g
  3. SRC=main.c utils.c
  4. OBJ=$(SRC:.c=.o)
  5. program: $(OBJ)
  6.     $(CC) $(CFLAGS) -o $@ $^
  7. %.o: %.c
  8.     $(CC) $(CFLAGS) -c $< -o $@
  9. .PHONY: clean
  10. clean:
  11.     rm -f $(OBJ) program
复制代码
符号分析:


  • $(变量名):体现引用变量,比方$(CC)引用了变量CC,其值为gcc。
示例:


  • $@ 示例
  1. objects = foo.o bar.o
  2. $(objects): %.o: %.c
  3.     gcc -c $< -o $@
复制代码
在这个例子中,$@ 将被更换为每个 .o 文件的目的名称,如 foo.o 或 bar.o。

  • $@ 代表当前规则的目的文件名(即左侧的文件)。
  • 它用于在下令中引用规则左侧的目的。

  • $^ 示例
  1. target: dependency1 dependency2
  2.     gcc -o $@ $^
复制代码
在这个例子中,$^ 将被更换为 dependency1 dependency2。

  • $^ 代表当前规则中全部依靠文件的列表。
  • 它用于在下令中引用规则右侧的全部依靠文件。

  • $< 示例
  1. %.o: %.c
  2.     gcc -c $< -o $@
复制代码
在这个例子中,$< 将被更换为规则中的第一个依靠文件,如 main.c。

  • $< 专门用来引用规则中列出的第一个依靠文件。
通过这些示例,可以清楚地明确这些符号的用途及功能。
利用模式规则

模式规则支持利用通配符界说一组目的文件的规则,比方:
  1. %.o: %.c
  2.     $(CC) -c $< -o $@
复制代码
符号分析:


  • %:通配符,体现恣意文件名。比方,%.o匹配全部.o文件,%.c匹配全部.c文件。
  • $<:体现当前规则中的第一个依靠文件。比方,main.c。
  • $@:体现目的文件。比方,main.o。
通过模式规则,可以克制重复界说规则,实用于大规模项目中的批量操纵。
自动天生依靠

对于大型项目,手动维护依靠关系轻易堕落。我们可以利用gcc的-M选项自动天生依靠关系:
  1. gcc -MM main.c > deps.d
复制代码
然后在Makefile中包罗天生的依靠文件:
  1. include deps.d
复制代码
自动天生依靠的意义:


  • 动态更新依靠关系:当源码文件发生变动时,重新运行依靠天生下令即可更新deps.d。
  • 淘汰人工维护的错误:克制手动誊写依靠关系带来的遗漏题目。
注意:


  • 包罗依靠文件时,如果依靠文件不存在,Makefile大概会报错。为此,可以利用如下方式:
  1. -include deps.d
复制代码
这体现如果deps.d不存在,Makefile将不会报错。
示例:


  • 自动天生依靠文件
  1. %.d: %.c
  2.     @set -e; rm -f $@; \
  3.     $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
  4.     mv $@.$$$$ $@
复制代码
在这个规则中,依靠文件 .d 将自动根据对应的 .c 文件天生。

  • 包罗全部依靠
  1. include $(SRC:.c=.d)
复制代码
通过这条规则,可以动态包罗全部的依靠文件。
美满Makefile

通过上述方法,我们可以渐渐美满一个Makefile。以下是一个完备的示例:
  1. BIN=programCC=gccCFLAGS=-Wall -gSRC=$(wildcard *.c)
  2. OBJ=$(SRC:.c=.o)$(BIN): $(OBJ)    $(CC) $(CFLAGS) -o $@ $^%.o: %.c    $(CC) $(CFLAGS) -c $< -o [email protected]: cleanclean:    rm -f $(OBJ) $(BIN).PHONY: allall: clean $(BIN)-include deps.d
  3. %.d: %.c
  4.     @set -e; rm -f $@; \
  5.     $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
  6.     mv $@.$$$$ $@
复制代码
通过以上内容的学习,已经富足编写寄出的Makefile~
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表