Makefile基础知识

Makefile基础知识



Makefile 的引入

a.c

#include <stdio.h>

extern void func_b();

int main(int argc, const char *argv[])
{
    func_b();

    return 0;
}

b.c

#include <stdio.h

void func_b()
{
    printf("This is B\n");
}

Makefile:

test : a.o b.o
gcc -o test a.o b.o

a.o : a.c
gcc -c -o a.o a.c

b.o : b.c
gcc -c -o b.o b.c

a.c ==> APP 的过程:

1. 预处理
2. 编译
3. 汇编
4. 链接
a.c ===> xxx.S ===> xxx.o
=====> test
b.c ===> yyy.S ===> yyy.o

缺点: 对所有的文件都再处理一次

应该分别编译,最后链接

gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -o test a.o b.o

问题: 如何判断哪个文件被更新了
: 比较目标文件和依赖文件的时间戳

Makefile的规则:

目标: 依赖1 依赖2 依赖n
`TAB` 命令Makfile的执行原理:

执行条件

  1. 目标不存在
  2. 依赖已更新

: 当依赖比目标新时,执行命令

test : a.o b.o
gcc -o test a.o b.o
a.o : a.c
gcc -o a.o -c a.c
b.o : b.c
gcc -o b.o -c b.c

Makefile的语法

通配符:

  1. $@ 表示目标
  2. $< 表示第一个依赖文件
  3. $^ 表示所有的依赖文件
    在这里插入图片描述
    在这里插入图片描述

假想目标: .PHONY: target

使用Makefile时:

make [目标]

若无目标,则默认第一个目标

在这里插入图片描述

变量

即时变量(简单变量)
A := XXX # A的值即刻确定,在定义是即确定
B = XXX # B的值使用到时才确定

:= # 即时变量
= # 延时变量
?= # 延时变量, 如果是第1次定义才起效, 如果在前面该变量已定义则忽略这句
+= # 附加, 它是即时变量还是延时变量取决于前面的定义

Makefile的函数

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

c. $(wildcard pattern) # pattern定义了文件名的格式,
# wildcard取出其中存在的文件
d. $(patsubst pattern,replacement,$(var)) # 从列表中取出每一个值
# 如果符合pattern
# 则替换为replacement

在这里插入图片描述
在这里插入图片描述
Makefile实例

a. 改进: 支持头文件依赖

Linux Makefile 生成 *.d 依赖文件以及 gcc -M -MF -MP 等相关选项说明

gcc -M c.c // 打印出依赖
gcc -M -MF c.d c.c // 把依赖写入文件c.d
gcc -c -o c.o c.c -MD -MF c.d // 编译c.o, 把依赖写入文件c.d

在这里插入图片描述


温顾知新:

在这里插入图片描述
在这里插入图片描述

Makefile中foreach使用

foreach 函数和别的函数非常的不一样。因为这个函数是用来做循环用的,Makefile中的foreach函数几乎是仿照于Unix标准Shell (/bin/sh)中的for语句,或是C-Shell(/bin/csh)中的foreach语句而构建的。它的语法是:

$(foreach <var>,<list>,<text>)

这个函数的意思是,把参数;中的单词逐一取出放到参数;所指定的变量中,然后再执行<
text>;所包含的表达式。每一次;会返回一个字符串,循环过程中,;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。
所以,;最好是一个变量名,;可以是一个表达式,而;中一般会使用;这个参数来依次枚举;中的单词。举个例子:

names := a b c d

files := $(foreach n,$(names),$(n).o)

上面的例子中, ( n a m e ) 中的单词会被挨个取出,并存到变量“ n ”中,“ (name)中的单词会被挨个取出,并存到变量“n”中,“ (name)中的单词会被挨个取出,并存到变量n中,(n).o”每次根据“ ( n ) ”计算出一个值,这些值以空格分隔,最后作为 f o r e a c h 函数的返回,所以, (n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以, (n)计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,(files)的值是“a.o
b.o c.o d.o”。
注意,foreach中的;参数是一个临时的局部变量,foreach函数执行完后,参数;的变量将不在作用,其作用域只在foreach函数当中。

Makefile中filter使用

$(filter PATTERN…,TEXT)

函数名称:过滤函数—filter。
函数功能:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字符“%”。存在多个模式时,模式表达式之间使用空格分割。
返回值:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。
函数说明:“filter”函数可以用来去除一个变量中的某些字符串,我们下边的例子中就是用到了此函数。

示例:

sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
cc $(filter %.c %.s,$(sources)) -o foo

使用“ ( f i l t e r (filter %.c %.s, (filter(sources))”的返回值给 cc 来编译生成目标“foo”,函数返回值为“foo.c
bar.c baz.s”

Makefile中filter-out使用

$(filter-out PATTERN…,TEXT)

函数名称:反过滤函数—filter-out。
函数功能:和“filter”函数实现的功能相反。过滤掉字串“TEXT”中所有符合模式“PATTERN”的单词,保留所有不符合此模式的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。。
返回值:空格分割的“TEXT”字串中所有不符合模式“PATTERN”的字串。 函数说明:
“filter-out”函数也可以用来去除一个变量中的某些字符串, (实现和“filter”函数相反)。

示例:

objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o

$(filter-out ( m a i n s ) , (mains), (mains),(objects))

实现了去除变量“objects”中“mains”定义的字串(文件名)功能。它的返回值为“foo.o bar.o”

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值