Makefile的使用

目录

1.为什么要使用Makefile

2.Makefile的基础语法

一、目标、依赖和命令

二、变量

三、通配符和模式规则

四、伪目标

五、注释

3.Makefile函数

foreach

filter/filter-out

Wildcard

patsubst


1.为什么要使用Makefile

在软件开发过程中,通常需要进行一系列的编译、链接等操作来生成可执行程序或库文件。如果手动执行这些命令,不仅繁琐易错,而且效率低下。Makefile 可以自动识别哪些文件发生了变化,并只重新编译和链接那些受影响的部分,大大节省了时间。例如,在一个大型项目中,当你只修改了一个源文件时,Makefile 会自动判断出只需要重新编译这个文件以及依赖它的部分,而不是重新编译整个项目。

使用Makefile有以下好处:

一、简化编译过程

对于大型项目,通常包含多个源文件和复杂的依赖关系。手动编译这些文件会非常耗时且容易出错。Makefile 可以定义一系列规则,指定如何编译、链接这些源文件。例如,你可以在 Makefile 中指定使用特定的编译器、编译选项等。当你执行 “make” 命令时,Makefile 会自动按照规则进行编译,大大简化了编译过程。

二、自动依赖管理

  1. 检测依赖关系:Makefile 能够自动检测源文件之间的依赖关系。如果一个源文件发生了变化,Makefile 会确定哪些文件依赖于它,并只重新编译那些受影响的文件。比如,有一个源文件 A.cpp 被修改了,而文件 B.cpp 和 C.cpp 依赖于 A.cpp,那么 Makefile 会只重新编译 B.cpp 和 C.cpp,而不会重新编译其他未受影响的文件。
  2. 确保一致性:通过管理依赖关系,Makefile 可以确保项目在不同的编译环境下保持一致性。如果某个依赖文件缺失或发生变化,Makefile 会发出错误提示,以便开发者及时处理。

三、提高开发效率

  1. 快速构建:由于 Makefile 只重新编译受影响的文件,所以可以大大缩短构建时间。在开发过程中,频繁的编译是很常见的,Makefile 的高效构建能力可以显著提高开发效率。
  2. 方便调试:在调试过程中,开发者可能需要频繁地修改和编译代码。Makefile 可以快速响应这些变化,使得调试过程更加顺畅。

四、可重复性和可维护性

  1. 可重复性:Makefile 确保了每次构建的结果都是一致的。这对于团队开发非常重要,因为每个开发者都可以使用相同的构建过程来获得相同的结果。
  2. 可维护性:随着项目的发展,源文件的数量和依赖关系可能会发生变化。Makefile 可以方便地进行修改和扩展,以适应这些变化。同时,清晰的规则和依赖关系也使得项目更容易维护。

五、跨平台支持

不同的操作系统和开发环境可能有不同的编译工具和命令。Makefile 可以通过适当的配置,在不同的平台上实现相同的构建过程。这使得项目可以在多个平台上进行开发和部署,提高了项目的可移植性。

2.Makefile的基础语法

Makefile 有以下基础语法:

一、目标、依赖和命令

1.基本结构:

  • Makefile 由一系列规则组成。每个规则的形式为:目标: 依赖文件列表,接着是一个或多个命令行,以制表符(Tab)开头。例如:
   myprogram: main.o utils.o
       gcc -o myprogram main.o utils.o

在这个例子中,myprogram是目标,main.outils.o是依赖文件。当执行 “make myprogram” 时,如果依赖文件比目标文件新,就会执行后面的命令来生成目标文件。

2.目标:

  • 目标可以是一个可执行文件、目标文件、库文件等。它代表了要生成的产物。
  • 可以有多个目标,也可以有一个目标依赖于其他目标。例如:
   all: myprogram
   myprogram: main.o utils.o
       gcc -o myprogram main.o utils.o
   main.o: main.c
       gcc -c main.c
   utils.o: utils.c
       gcc -c utils.c

这里,“all” 是一个伪目标,它依赖于 “myprogram”。当执行 “make all” 时,会先构建 “myprogram”。

3.依赖:

  • 依赖是生成目标所需要的文件。如果依赖文件的时间戳比目标文件新,就会触发命令的执行。
  • 依赖可以是源文件、目标文件、库文件等。可以有多个依赖,用空格分隔。

4.命令:

  • 命令是用于生成目标的具体操作。每个命令行必须以制表符开头,不能用空格。
  • 命令可以是任何 shell 命令,如编译命令、链接命令、复制文件等。

二、变量

1.定义变量:

  • 可以使用 “=”、“:=”、“?=” 等符号来定义变量。例如:
   CC = gcc
   OBJS = main.o utils.o

这里定义了两个变量 “CC” 和 “OBJS”。

1.使用变量:

  • 在规则中可以使用变量来代替具体的值。例如:
   myprogram: $(OBJS)
       $(CC) -o myprogram $(OBJS)

这里使用了变量 “OBJS” 和 “CC” 来指定依赖文件和编译器。

三、通配符和模式规则

1.通配符:

  • Makefile 支持通配符,如 “*”、“?” 等。可以用通配符来匹配一组文件。例如:
   SRC_FILES = *.c

这里定义了一个变量 “SRC_FILES”,它包含了当前目录下所有的 C 源文件。

2.模式规则:

  • 模式规则可以用于对一类目标进行统一的构建。例如:
   %.o: %.c
       $(CC) -c $< -o $@

这个规则表示,对于任何以 “.c” 结尾的文件,都可以生成一个对应的以 “.o” 结尾的目标文件。其中," < "表示第一个依赖文件," @ "表示目标文件。

四、伪目标

1.定义伪目标:

  • 伪目标不是真正的文件,而是一个标签,用于执行一系列命令。定义伪目标的方式是在目标名前加上 “.PHONY” 关键字。例如:
  .PHONY: clean
   clean:
       rm -f *.o myprogram

这里定义了一个伪目标 “clean”,用于删除生成的目标文件和中间文件。

2.使用伪目标:

  • 可以像使用普通目标一样使用伪目标,执行 “make clean” 就会执行 “clean” 规则中的命令。

五、注释

1.注释方式:

  • Makefile 中使用 “#” 进行注释。例如:
   # 这是一个注释
   myprogram: main.o utils.o
       gcc -o myprogram main.o utils.o

3.Makefile函数

makefile里面可以包含很多函数,这些函数都是make本身实现的,下面我们来几个常用的函数。引用一个函数用“$”。

  • foreach

函数foreach语法如下:

$(foreach var,list,text) 

前两个参数,‘var’和‘list’,将首先扩展,注意最后一个参数 ‘text’ 此时不扩展;接着,对每一个 ‘list’ 扩展产生的字,将用来为 ‘var’ 扩展后命名的变量赋值;然后 ‘text’ 引用该变量扩展;因此它每次扩展都不相同。结果是由空格隔开的 ‘text’。在 ‘list’ 中多次扩展的字组成的新的 ‘list’。‘text’ 多次扩展的字串联起来,字与字之间由空格隔开,如此就产生了函数 foreach 的返回值。

实例:

A = a b c
B = $(foreach f, &(A), $(f).o)
​
all:
    @echo B = $(B)

结果:

B = a.o b.o c.o
  • filter/filter-out

函数filter/filter-out语法如下:

$(filter pattern...,text)     # 在text中取出符合patten格式的值
$(filter-out pattern...,text) # 在text中取出不符合patten格式的值

实例:

C = a b c d/
​
D = $(filter %/, $(C))
E = $(filter-out %/, $(C))
​
all:
        @echo D = $(D)
        @echo E = $(E)

结果:

D = d/
E = a b c
  • Wildcard

函数Wildcard语法如下:

$(wildcard pattern) # pattern定义了文件名的格式, wildcard取出其中存在的文件。

这个函数 wildcard 会以 pattern 这个格式,去寻找存在的文件,返回存在文件的名字。

实例:

在该目录下创建三个文件:a.c b.c c.c

files = $(wildcard *.c)
​
all:
        @echo files = $(files)

结果:

files = a.c b.c c.c

我们也可以用wildcard函数来判断,真实存在的文件

实例:

files2 = a.c b.c c.c d.c e.c  abc
files3 = $(wildcard $(files2))
​
all:
        @echo files3 = $(files3)

结果:

files3 = a.c b.c c.c
  • patsubst

函数 patsubst 语法如下:

$(patsubst pattern,replacement,\$(var))

patsubst 函数是从 var 变量里面取出每一个值,如果这个符合 pattern 格式,把它替换成 replacement 格式,

实例:

files2  = a.c b.c c.c d.c e.c abc
​
dep_files = $(patsubst %.c,%.d,$(files2))
​
all:
        @echo dep_files = $(dep_files)
​

结果:

dep_files = a.d b.d c.d d.d e.d abc

实际上windows工具管理程序的内部机制,也是Makefile,我们在linux下来开发裸板程序的时候,使用Makefile组织管理这些程序  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值