makefile 基本写法

makefile 基本写法

需要注意的是, 每一行commands在一个单独的shell进程中,这些shell之间没有任何继承关系

<target> : <prerequisites> 
[tab]  <commands>

比如下面的例子的运行结果为:MY_PATH=[]

mytarget:
    export MY_PATH=aaabbbccc
    echo "MY_PATH=[$$MY_PATH]"

下面的例子的运行结果为:MY_PATH=[aaabbbccc]

mytarget:
    export MY_PATH=aaabbbccc; \
    echo "MY_PATH=[$$MY_PATH]"

思考一下, 为什么要写成$$MY_PATH, ( M Y P A T H ) 能 打 印 出 来 吗 ? 这 里 可 以 参 考 如 下 文 章 的 解 释 , 实 质 上 m a k e f i l e 会 先 去 解 释 第 一 个 (MY_PATH) 能打印出来吗?这里可以参考如下文章的解释,实质上makefile会先去解释第一个 (MYPATH)makefile,而shell会去解释第二个 , 如 果 只 有 一 个 ,如果只有一个 ,, make 会因为找不到变量MY_PATH而终止,因为MY_PATH是定义在shell中的。

https://blog.csdn.net/darennet/article/details/8185881

基本语法

直接式变量赋值与递归式变量赋值

# 递归式变量赋值,make会将整个makefile展开后,再决定变量的值
algo = gzip.o lzma.o

# 直接式变量赋值,变量的值决定于它在makefile中的位置
algo := gzip.o lzma.o

举个例子就能说明区别

_algo = gzip
algo := $(_algo)
_algo = lzma

test:
        @echo "algo=$(algo)"

输出应该为gzip,也就是说在定义的时候就展开了

_algo = gzip
algo = $(_algo)
_algo = lzma

test:
        @echo "algo=$(algo)"

输出应该为lzma,将整个makefile展开后才确定了_algo的值,进而确定了algo的值

打印回显

# 正常情况下make 会打印每一条命令然后再执行,使用@可以阻止回显
    echo "hello world!"
    @echo "hello world!"

其他赋值

只有在变量未被赋值时才赋值

# 条件赋值
algo ?= lzma

# 增量式赋值
algo += gzip

使用函数

return = $(functionname arg1, arg2, arg3...)

扩展通配符wildcard

# * 表示任意一个或多个字符
# ? 表示任意一个字符
# [...]  [abc] 表示abc中任意一个字符匹配, [^abc]表示除abc意外的字符
# [0-9] 表示0~9任意一个数字
algo = $(wildcard *.c)

test:
        @echo "algo=$(algo)"

假如在Makefile所在的目录下有lzma.c, gzip.c, bzip2.c, xz.c, lzo.c 那么algo会打印出所有的这些.c文件名称

匹配替代通配符patsubst

# % 为模式字符
algo = $(patsubst %.c,%.o,$(wildcard *.c))
test:
        @echo "algo = $(algo)"

去除路径notdir

OBJS = /usr/opt/bin/algo.c
algo = $(notdir $(OBJS))

test:
        @echo "algo = $(algo)"

运行结果

root@chlxy:# make
algo = algo.c

字符串替换subst

string_old = AAAAABBBBBCCCCC
string_new = $(subst A,a,$(string_old))

test:
        @echo "new string is $(string_new)"

运行结果,其中需要注意,如果在上述A,a,后面加空格再加$(string_new)会导致输出中带有空格

root@chlxy:# make
new string is aaaaaBBBBBCCCCC

过滤函数filter

string_old = AAAAA.c BBBBB.o CCCCC.s
string_new = $(filter %.o, $(string_old))

test:
        @echo "new string is $(string_new)"

运行结果

root@chlxy:# make
new string is BBBBB.o

循环函数 foreach

algos = lzma gzip lzo lz4 xz
algofiles = $(foreach algo, $(algos), $(algo).c)

test:
        @echo "$(algofiles)"

运行结果

root@chlxy:# make
 lzma.c  gzip.c  lzo.c  lz4.c  xz.c

显式运行shell

algos = $(shell ls)

test:
        @echo "$(algos)"

运行结果

root@chlxy:# make
bzip2.c gzip.c lz4.c lzma.c lzo.c Makefile xz.c

运行控制 error 与 warning

ifndef ARCH
$(error should define ARCH...)
endif

ifndef PLAT
$(warning forget define PLAT ?)
endif

test:
        @echo "this is a test"

运行结果

root@chlxy:# make
Makefile:3: *** should define ARCH...。 停止。
root@chlxy:# make ARCH=arm
Makefile:7: forget define PLAT ?
this is a test
root@chlxy:# make ARCH=arm PLAT=yes
this is a test

其他函数

# 函数太多,具体使用方法就不再一一举例了

# 将字符串升序排列,并去掉重复单词
sort

# 取单词函数
word

# 取字符串函数
wordlist

# 统计字符串中单词数目
words

# 取字符串的第一个单词,lastword同理取最后一个单词
firstword

# 取目录,包含指定文件的路径目录
dir

# 取前缀函数
basename

# 实现用户自定义函数的引用,$(call function arg1,arg2,...)
call

条件判断

# ifeq ifneq ifdef ifndef

ifeq ($(ARCH), arm)
        MY_ARCH = ARCH_ARM
else ifeq ($(ARCH), arm64)
        MY_ARCH = ARCH_ARM_64
else
        MY_ARCH = unknown
endif

ifdef PLAT
        MY_PLAT = nxp
else
        MY_PLAT = unknown
endif

test:
        @echo "MY_ARCH = $(MY_ARCH) MY_PLAT=$(MY_PLAT)"

运行结果

root@chlxy:# make ARCH=arm
MY_ARCH = ARCH_ARM MY_PLAT=unknown
root@chlxy:# make ARCH=arm PLAT=yes
MY_ARCH = ARCH_ARM MY_PLAT=nxp
root@chlxy:# make ARCH=arm64
MY_ARCH = ARCH_ARM_64 MY_PLAT=unknown
makefile是一种用于自动化构建和编译程序的脚本文件。makefile基本写法包括目标、依赖、规则和命令这三个要素。 1. 目标:目标是指需要生成的文件或执行的任务。在makefile中,目标通常是一个可执行文件或一个文件的对象文件。可以有多个目标,每个目标占据一行,并以冒号(:)结尾。 2. 依赖:依赖是指目标生成所依赖的文件或任务。在makefile中,依赖通常是源文件或其他目标。依赖也可以有多个,每个依赖之间用空格分隔,放在目标的后面。 3. 规则:规则是指定义了目标和依赖之间关系的部分。在makefile中,规则以目标为开头,后面是一个冒号(:),然后是依赖。规则可以有多行,每行以一个Tab键开头,表示规则所对应的命令。 例如,下面是一个简单的makefile示例: ``` target: dependency command ``` 其中,`target`是目标,`dependency`是依赖,`command`是需要执行的命令。 通过这样的规则,当依赖发生变化时,可以使用make命令来自动更新目标。make工具会自动识别目标和依赖之间的关系,并执行相应的命令来生成目标。 需要注意的是,makefile中的命令必须以Tab键开头,否则make工具无法正确解析。 这只是makefile的一种简单写法,实际上,makefile可以包含更复杂的规则和命令,以满足具体项目的需求。可以通过学习更多的makefile语法和使用方法来进一步掌握makefile写法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [手把手教你写makefile](https://blog.csdn.net/weixin_43574962/article/details/104108641)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值