🗒️Makefile 规则与语法学习
2023-6-20
| 2023-6-20
0  |  Read Time 0 min
type
status
date
slug
summary
tags
category
icon
password

🗓️学习日期规划

2023/6/20

😦Makefile是啥

一种用于自动化构建和管理软件项目的文件。和make命令搭配使用

📝写一个简单的Makefile

编辑 Makefile,写入一个最简单的
然后运行 make hello,可以发现输出了
➜ make hello echo "hello world" hello world
当然,我们可以在其中插入更多的过程(但是这个过程是不严谨的,因为hello此时应该是要被构建的目标,只有echo是不足以构建的,也就是make必须要产生点东西,在这里就是要产生hello,最差的做法都必须要 echo “hello world” > hello
尝试将makefile修改成这样,然后写入一些简单的东西
很神奇

📓配合C语言进行编译与使用

首先写一个简单的 main.c
然后仿照我们日常使用的make命令,写一个简单的makefile
尝试 make build, make install 后直接在控制台执行 hello 试试
再试试 make uninstall, make clean 等操作
工作很正常

插入变量

自定义变量

Makefile中也可以使用变量,我们可以这样尝试,在makefile的开头插入 target_name = hello,并重新尝试 make build, make install等操作

预定义变量

除此之外,makefile还会有一些预定义变量,我们可以这么编写一个来查看

环境变量

还可以查看一些环境变量,比如 PATH 之类的
在参考文章内,还可以发现有一些其他的环境变量
Makefile 常用的环境变量有下面这些:
  • $*:不包含扩展名的目标文件名称
  • $<:第一个依赖文件名称
  • $?:所有时间戳比目标文件晚的依赖文件
  • $@:目标文件完整名称
  • $^:所有不重复的依赖文件

Makefile 切换工作目录

需要注意的是,makefile每一的命令是独立的,不会说上一条cd了以后工作目录就变了。如果需要跨目录执行,则需要在同一行使用 && 拼接,以下是拼接后的结果

Makefile 伪目标

伪目标(Phony Target)是一种特殊类型的目标,其名称与实际文件名或目标不相关。伪目标通常用于定义一些不生成对应输出文件的操作或命令。它们用于表示一些常见的动作或规则,并提供一种方便的方式来执行这些操作。
伪目标在Makefile中以特殊的方式声明,使用伪目标可以避免与实际文件名冲突,并且即使存在同名的文件,也能确保这些规则被执行。伪目标在Makefile中没有依赖关系,即使依赖项的文件存在,伪目标的规则也会被执行。
罗里吧嗦的讲了一大堆,结果我自己都没看懂,那就实际写个东西看看吧

对于单个构建

尝试写一个这样的makefile
然后再创建一个test1,尝试make test1
可以发现,test1所在的构建没法正常执行了,这是因为make判断当前目录下已经有test1这个文件了,那你已经构建完成了,我就没必要给你重复执行这个过程了,而.PHONY: test1就是告诉make,你这个构建过程不产生一个叫test1的文件,如果没有.PHONY,那么我一看到你有test1这个文件我就不会执行了。而如果有.PHONY,我不管你有没有test1,我都去执行test1这个过程。
加上 .PHONY: test1 ,我们再来试试
加上了,可以发现,这时候make test1已经不管你目录下是否有test1了,我都照样执行。

对于依赖关系

尝试写一个这样的makefile,注意这里 test1: test2 test3 是放在同一行的,目的是为了让它执行test2和test3的构建,而不是将test2和test3当成命令。
在文件目录没有 test* 的时候,它执行的结果是这样的
我们尝试创建一个test2,再重新执行一遍
发现了吗,少了一个test2。
我们再尝试创建一个test3
又少了一个。
然后我们尝试加入这个传说中的伪目标
发现了吗,明明test2这个文件是存在的,但它还是执行了test2,我们再把test3加上。
test3也回来了,删掉test2和test3也是同样的结果。
至此,就可以发现,.PHONY的加入,可以让 Makefile 不再去看对应构建是否存在该文件再去判断是否执行。

Makefile 包含

如果在不同目录下有不同的 Makefile,可以用下面的方法来嵌套
注意,这里include了build文件夹的Makefile以后,使用的是哪个目录下的makefile,那么工作目录就在那个目录,不会说工作目录变成了build
尝试在工作目录 make build2,成功执行,且文件生成到了 ./build/hello。
 

Makefile 条件判断

makefile也可以进行条件判断,但是只能进行一些简单的判断,如 ifeq, ifneq, ifdef, ifndef
需要注意的是,条件判断语句不能直接放在规则的命令部分,因为这些语句需要在 Makefile 的解析阶段进行处理,而不是在命令执行阶段。
即以下的写法是错误的
它会抛出以下异常

Makefile 管理命令

makefile还有许多管理命令,用--help就能看到,这里就不赘述了

⁉️自问自答

  • 像make xxx这样的指令,xxx就是在makefile中定义好过程的吗?
    • 确实是。我们可以尝试新建一个Makefile,输入 hello: echo “Hello World”
      然后输入 make hello
      ➜ make hello echo "hello world" hello world
  • 只有C/C++能用makefile吗
    • 从上面就能看得出来,并不是这样的,只不过比较常用的是这个而已?它就是描述一个过程,使用make xxx会执行一系列的命令,所以,当然我们可以在其中放一些恶意代码。makefile会像执行shell一样执行下来。
  • 什么是 Makefile 伪目标(?)
    • 伪目标(Phony Target)是一种特殊类型的目标,其名称与实际文件名或目标不相关。伪目标通常用于定义一些不生成对应输出文件的操作或命令。它们用于表示一些常见的动作或规则,并提供一种方便的方式来执行这些操作。
      伪目标在Makefile中以特殊的方式声明,使用伪目标可以避免与实际文件名冲突,并且即使存在同名的文件,也能确保这些规则被执行。伪目标在Makefile中没有依赖关系,即使依赖项的文件存在,伪目标的规则也会被执行。
      解决方案看上面
  • Makefile 怎么切换目录执行
    • 不能直接在一行cd后在下一行执行,而是需要在需要切换目录命令同一行前面加上cd &&
      例如:cd build && pwd,否则下一行目录就会变回去了
  • make 的多线程编译?

🤗鸣谢

  • 健雄 徐 的 Arch-Playground
  • U2F sdGVkX1 的 技术支持与规划

🔖参考文章

本文以学习为目的,大部分内容都参考了以下文章,十分感谢以下的文章。
 
技术分享
  • 学习
  • LFS 构建与学习从CTF.Show签到题入手尝试逆向题
    • GitTalk
    Catalog