Linux详解:makefile

引言

在软件开发过程中,一个项目通常由许多源代码文件和头文件组成。这些文件可能依赖于其他文件,并且在编译和构建过程中需要执行一系列命令和步骤。手动管理这些文件和命令是非常困难的,尤其是当项目越来越复杂时

为了自动化构建、编译和部署过程,我们可以使用构建工具。其中 Make 工具是最流行的构建工具之一。Make 工具提供了一个 Makefile 文件格式,以定义相互依赖的文件和规则,并自动执行构建过程。

Makefile是一种自动化构建工具,用于管理和编译源代码。它能够自动搜索文件依赖关系,并根据需要重新编译程序。本文将详细介绍Makefile的基本使用方法,包括目标、依赖和命令,以及一些常用的技巧和注意事项。

一、Makefile的基本使用

Makefile中包含了一组规则,用于描述如何将源代码转换为可执行文件。每条规则都包括一个或多个目标、依赖和命令。

1.1 目标

目标是Makefile规则所要生成的文件。可以是源代码、目标文件或可执行文件等文件类型。在Makefile中,可以定义多个目标。

例如,在以下示例中,定义了两个目标hello.oworld.o

hello.o: hello.c
        gcc -c hello.c

world.o: world.c
        gcc -c world.c

1.2 依赖

依赖是指待生成目标所依赖的其他目标或文件,其主要作用是指明目标所依赖的文件,确保他们在生成目标之前被更新。依赖通常是源文件或库文件。

例如,在以下示例中,定义的目标hello.oworld.o都有各自的依赖hello.cworld.c

hello.o: hello.c
        gcc -c hello.c

world.o: world.c
        gcc -c world.c

1.3 命令

命令是Makefile规则中指定的转换或操作。每个命令都会在Shell中被执行。

在上述示例中,命令是gcc -c hello.cgcc -c world.c。它们将源代码转化成目标文件。

二、PHONY

.PHONY声明被列为伪目标(phony target)的目标。伪目标是没有对应物理文件的目标,只是用来给其他目标提供前置条件,因此当该目录下出现跟目标名同名文件时,不能被忽略警告。

2.1 为什么需要.PHONY

.PHONY通常用于声明一些不生成实际文件的模拟性目标。如果不加.PHONY声明,那么Make在查找所有文件的依赖关系时,就会把这个目标名称误认为是一个实际的文件,并且去查找相关依赖、更新并尝试生成该目标。这会导致无效的时间浪费,甚至无法正常执行。

例如,有如下的一个Makefile:

build:
    @echo "Build project"
    
clean:
    @echo "Clean project"

.PHONY: build clean

在上面的示例中,使用了.PHONY声明buildclean是伪目标。这两个目标并不代表实际的文件,只是模拟性目标,用于执行编译和清理操作。如果忘记加上.PHONY声明,会导致Make出现错误,无法正常执行。

2.2 .PHONY使用方法

要声明一个伪目标,只需在目标名前面添加一个特殊符号“.PHONY:”。

例如,以下示例定义了伪目标clean和bulid:clean用于删除文件test和文件mytest;build用于创建可执行文件mytest

test:test.c
	gcc $^ -o $@

.PHONY:build clean
build:
      	gcc test.c -o mytest

clean:
      	rm -f mytest test

运行结果与解释如下:

三、特殊符号的用法

这三个符号都是Makefile规则中可以使用的自动变量或预定义变量。

  • $@:表示规则中的目标文件名称
  • $^:表示规则中运行条件中所有的依赖文件列表,以空格分隔
  • $<:表示规则中的第一个依赖文件名称

以下规则为例:

libmylib.a: main.o func1.o func2.o
        ar -rc $@ $^

main.o: main.c
	gcc -c $< -o $@

func1.o: func1.c
        gcc -c $< -o $@

func2.o: func2.c
        gcc -c $< -o $@


.PHONY: clean
clean:
      	rm -f *.o

3.1 $@

在上述示例中,$@用于表示libmylib.a,即当前规则的目标文件名。

在命令中,通过ar -rc $@ $^指定将所有运行条件中的依赖文件进行打包,最终生成目标文件libmylib.a

3.2 $^

可以用于表示规则中运行条件中所有的依赖文件列表,以空格分隔。例如,在上述示例中,可以用于表示规则中运行条件中所有的依赖文件列表,以空格分隔。例如,在上述示例中,$^表示main.o func1.o func2.o

3.3 $<

$<表示规则的第一个依赖文件名称。例如,在以下规则中,<表示规则的第一个依赖文件名称。例如,在以下规则中,<表示main.c

main.o: main.c 
    gcc -c $<

在命令中,通过gcc -c $< -o $@指定只对目标文件所依赖的第一个源文件main.c进行编译。

3.4 %

通配符 % 可以用在 makefile 中,表示匹配任意的字符串。在 makefile 中,% 表示一系列文件名中的字符通配符,也就是说可以处理一些带有类似模式的文件。

如果我们想要对多个源文件进行编译,但这些文件名都只有一个前缀,后缀不同,我们可以使用 % 通配符来定义相关规则。

比如,我们有三个源文件 foo.c、bar.c 和 baz.c,需要编译成对应的目标文件 foo.o、bar.o 和 baz.o。那么,通常情况下的 makefile 会写成:

foo.o: foo.c 
    gcc -c foo.c 
bar.o: bar.c 
    gcc -c bar.c 
baz.o: baz.c 
    gcc -c baz.c

但这样每个源文件都需要单独编写规则,特别是文件较多时显得十分繁琐。此时,我们可以使用 % 通配符来简化代码。

%.o:%.c 
    gcc -c $< -o $@

这里的 %.c 表示匹配任何以 .c 结尾的文件名,而 %.o 表示生成与源文件同名,但以 .o 结尾的目标文件。$< 表示自动变量,在这里是第一个依赖,即对应的源文件名,而 $@ 表示当前目标文件名。

这样,就可以使用一个规则来匹配多个源文件进行生成目标文件,避免了重复的代码和出错的概率。

总之,% 通配符是 makefile 中十分方便的语法,可用于匹配任何字符串,非常适合一些文件名类似且规律性较强的情况下使用。

  1. 总结

本文介绍了Makefile的基本使用方法,包括目标、依赖和命令。同时还介绍了.PHONY声明伪目标以及自动变量的使用方法。

Makefile作为一种自动化构建工具,能够大大提高程序员的工作效率。但是在实际开发中,有很多细节和注意事项需要注意,比如正确编写规则、优化文件依赖关系、处理路径名等等。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一 杯 清 酒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值