【一生一芯02】‘RTFSC’-Makefile构建总结

本文深入讲解Makefile的基础规则、变量使用、条件判断等核心概念,并详细介绍NEMU和AM项目的构建流程,适合希望深入了解Makefile机制及其在实际项目中应用的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.makefile总结

1.1makefile基本规则

1.1.1makefile变量

1.1.2make自动推导

1.1.3清空目标文件

1.2makefile综述

1.2.1引用其他makefile

1.2.2makefile工作方式

1.3makefile规则书写

1.3.1通配符的使用

1.3.2文件搜寻 

1.3.3伪目标

 1.3.4多目标静态模式

1.4命令书写

1.4.1显示命令

1.4.2 命令执行

1.4.3命令出错 

1.4.4定义命令包

1.5使用变量 

1.5.1变量基础

 1.5.2变量中的变量

1.5.3变量值的替换

1.5.4追加变量值

1.6条件判断

1.7使用函数

1.7.1函数调用语法

 1.7.2字符串处理函数

1.7.3文件名操作函数

 1.7.4foreach函数

 1.7.5if函数

1.7.6call函数 

1.7.7shell函数

1.8make的运行

1.8.1检查规则

1.8.2make参数

1.9隐含规则

1.9.1使用隐含规则

1.9.2隐含规则使用变量 

1.9.3模式规则

1.9.4★自动化变量★

2.NEMU项目构建

3.AM项目构建

3.1AM-Makefile

3.1.1基础设置和检查

3.1.2一般编译目标

3.1.3常规编译标志

3.1.4特定架构配置

3.1.5编译选项

3.2riscv64-nemu.mk(ARCH)

3.3riscv64.mk(ISA)

3.4nemu.mk(PLATFORM)


1.makefile总结

以下内容参考《跟我一起写makefile》,仅作个人学习总结。

make 命令执行时,需要一个 Makefile 文件,以告诉 make 命令需要怎么样的去编译和链接程序。

1.1makefile基本规则

target...:prerequisites...
    command

target: 目标文件,Objectfile,执行文件,或者标签

prerequisites:生成target所需文件或目标

command:make执行的命令(任意shell命令)

1.1.1makefile变量

Makefile 中的变量其实就是 C/C++中的宏。

objects = main.0 kbd.o display.o insert.o #all .o file
edit: $(objects)
    cc -o edit $(objects) 

1.1.2make自动推导

GNU 的 make 很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必 要去在每一个[.o]文件后都写上类似的命令,因为,我们的 make 会自动识别,并自己推导 命令。 只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make 找到whatever.o,那么 whatever.c,就会是 whatever.o 的依赖文件,并且 cc -c whatever.c 也会被推导出来。

1.1.3清空目标文件

所有生成的文件,都应当可以被清空,这有利于重编译和保持文件清洁。

.PHONY:clean
clean:
    rm edit $(objects)

1.2makefile综述

makefile主要包含五个东西:显式规则,隐式规则,变量定义,文件指示和注释

1.2.1引用其他makefile

makefile使用include关键字可以把别的makefile包含进来

include <filename>

 filename 可以是当前操作系统 Shell 的文件模式(可以保含路径和通配符) 在 include 前面可以有一些空字符,但是绝不能是[Tab]键开始。make 命令开始时,会把找寻 include 所指出的其它 Makefile,并把其内容安置在当前的位置。

如果文件都没有指定绝对路径或是相对路径的话, make 会在当前目录下首先寻找,如果当前目录下没有找到,那么,make 还会在下面的几个目录下找:

1."-I"或"--include-dir"所指定目录

2.<prefix>/include中

1.2.2makefile工作方式

GNU 的 make 工作时的执行步骤入下:

1、读入所有的 Makefile。

2、读入被 include 的其它 Makefile。

3、初始化文件中的变量。

4、推导隐晦规则,并分析所有规则。

5、为所有的目标文件创建依赖关系链。

6、根据依赖关系,决定哪些目标要重新生成。

7、执行生成命令。

1.3makefile规则书写

targets : prerequisites 
    command 

或是这样: 
targets : prerequisites ; command 
    command 

1.3.1通配符的使用

~/:当前用户$HOME目录

*.c:表示所有后缀为c的文件

clean: 
    rm -f *.o

1.3.2文件搜寻 

在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在不同的目录中。所以,当 make 需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是定义一个路径,让 make 在自动去找。

VPATH

VPATH = src:../headers

make 会优先在当前的目录中去找寻依赖文件和目标文件,找不到时会去VPATH中寻找,如上所示会按照"src"和"../headers"顺序去搜索。目录由“冒号”分隔。 

关键字vpath

1、vpath 为符合模式的文件指定搜索目录。

vpath <pattern> <directories>

2、vpath 清除符合模式的文件的搜索目录。

vpath <pattern> 

3、vpath 清除所有已被设置好了的文件搜索目录。

vpath

vapth 使用方法中的需要包含“%”字符。“%”的意思是匹配零或若干字符, 例如,“%.h”表示所有以“.h”结尾的文件。

vpath %.h ../headers

该语句表示,要求 make 在“../headers”目录下搜索所有以“.h”结尾的文件。(如果 某文件在当前目录没有找到的话)

1.3.3伪目标

“伪目标”并不是一个文件,只是一个标签, 由于“伪目标”不是文件,所以 make 无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。

伪目标最好不要和文件名重名,但可以用特殊标记".PHONY"显式指明伪目标,不管是否有该文件,该目标都是伪目标。

.PHONY: clean 
clean: 
    rm *.o temp 

伪目标可以指定依赖,如下所示可以实现“一键三连” 

all : prog1 prog2 prog3 
.PHONY : all 
 
prog1 : prog1.o utils.o 
    cc -o prog1 prog1.o utils.o 
 
prog2 : prog2.o 
    cc -o prog2 prog2.o 
 
prog3 : prog3.o sort.o utils.o 
    cc -o prog3 prog3.o sort.o utils.o 

 伪目标也可以成为依赖,如下所示可以实现“一键清空”

PHONY: cleanall cleanobj cleandiff 
 
cleanall : cleanobj cleandiff 
    rm program 
 
cleanobj : 
    rm *.o 
 
cleandiff : 
    rm *.diff 

 1.3.4多目标静态模式

<targets ...>: <target-pattern>: <prereq-patterns ...> 
    <commands>

targets 定义了一系列的目标文件,可以有通配符。是目标的一个集合。

target-parrtern 是指明了 targets 的模式,也就是的目标集模式。

prereq-parrterns 是目标的依赖模式,它对 target-parrtern 形成的模式再进行一次依赖目标的定义。

objects = foo.o bar.o 
 
all: $(objects) 
 
$(objects): %.o: %.c 
    $(CC) -c $(CFLAGS) $< -o $@

命令中的“$<”和“$@”是自动化变量,“$<”表示所有的依赖目标集(也就是“foo.c bar.c”),“$@”表示目标集(也就是“foo.o bar.o”)

当文件众多时,利用简单的“静态模式规则”可以高效的完成规则编写。

files = foo.elc bar.o lose.o 
 
$(filter %.o,$(files)): %.o: %.c 
$(CC) -c $(CFLAGS) $< -o $@ 
$(filter %.elc,$(files)): %.elc: %.el 
emacs -f batch-byte-compile $<

 $(filter %.o,$(files))表示调用 Makefile 的 filter 函数,过滤“$filter”集,只要其 中模式为“%.o”的内容。

1.4命令书写

每条命令的开头必须以[Tab]键开头,在命令行之间中的空格或是空行会被忽略。

make 的 命 令 默 认 是 被 “/bin/sh”——UNIX 的标准 Shell 解释执行的。

“#”是注释符,其后的本行字符都被注释。

1.4.1显示命令

通常,make 会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在 命令行前,那么,这个命令将不被 make 显示出来。

echo  git checkout ysyx-tracer
@echo git checkout ysyx-tracer

make执行时,加入参数"-n"或"--just-print",那么将只显示命令,不执行命令,可以利用这个功能调试Makefile。

而 make 参数“-s”或“--slient”则是全面禁止命令的显示。 

1.4.2 命令执行

当依赖目标新于目标时,也就是当规则的目标需要被更新时,make 会一条一条的执行 其后的命令。需要注意的是,如果你要让上一条命令的结果应用在下一条命令时,你应该使 用分号分隔这两条命令。

exec: cd /home/hchen; pwd

1.4.3命令出错 

忽略命令的出错,我们可以在 Makefile 的命令行前加一个减号“-” (在 Tab 键之后),标记为不管命令出不出错都认为是成功的。

clean: 
    -rm -f *.o

给make 加上“-i”或是“--ignore-errors”参数,那么,Makefile 中所有命令都会忽略错误。

如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误。

参数“-k”或是“--keep-going”的作用是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。

1.4.4定义命令包

如果 Makefile 中出现一些相同命令序列,那么我们可以为这些相同的命令序列定义一 个变量。定义这种命令序列的语法以“define”开始,以“endef”结束。

define run-yacc 
    yacc $(firstword $^) 
    mv y.tab.c $@ 
endef 

foo.c : foo.y 
    $(run-yacc) 

1.5使用变量 

在 Makefile 中的定义的变量,就像是 C/C++语言中的宏一样,他代表了一个文本字串,在 Makefile 中执行的时候其会自动原模原样地展开在所使用的地方。其与 C/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值