Lishengxie logo Lishengxie

Always on the way

  • 文章
  • 关于我
  • 归档
  • 联系
  1. 首页
  2. 文章
  3. Makefile使用学习

Makefile使用学习

2023-04-30 C++ , linux Lishengxie

参考教程

原文:https://makefiletutorial.com/ 中文翻译:https://makefiletutorial.vercel.app

Makefile常用内容

本文主要基于以上教程记录一些平时阅读Makefile可能会用到的信息。

Makefile基础使用

首先,Makefile用于帮助决定一个大型程序的哪些部分需要重新编译,如果有任何文件的依赖项发生改变,那么该文件将会重新编译。Makefile通常由一组规则组成,规则通常如下所示:

target: prerequisites
	command
	command
	command
  • target是文件名,以空格分隔,通常每个规则只有一个。
  • command通常是用于制作目标的一系列步骤,需要以制表符Tab而不是空格开头。
  • prerequisites也是文件名,称为依赖项,以空格分隔,在运行针对目标的命令之前,这些文件需要存在。

下面是一个Makefile的实例:

blah: blah.o
	gcc blah.o -o blah # Runs third

blah.o: blah.c
	gcc -c blah.c -o blah.o # Runs second

# Typically blah.c would already exist, but I want to limit any additional required files
blah.c:
	echo "int main() { return 0; }" > blah.c # Runs first

使用make时默认会执行第一个目标blah,或者可以指定目标进行生成make blah。上面的Makefile在执行make指令后按照一系列步骤进行调用:

  • make选择目标blah,因为第一个目标是默认目标
  • blah需要blah.o,所以搜索blah.o目标
  • blah.o需要blah.c,所以搜索blah.c目标
  • blah.c没有依赖关系,所以echo命令运行
  • 然后运行该gcc -c命令,因为所有blah.o依赖项都已完成
  • gcc运行top命令,因为所有的blah依赖都跑完了
  • 就是这样:blah是一个编译好的c程序

Makefile使用文件系统时间戳来判断上次编译以来的先决条件是否发生了变化。例如,如果运行上面的Makefile后删除blah.c,那么三个目标都会被重新执行;如果只是编辑blah.c,那么只有前两个目标会被重新执行;如果只是通过touch blah.o更新blah.o的时间戳,那么只有第一个目标会被重新执行;如果不做任何更改,那么所有目标都不会被执行。需要注意的是,时间戳并不总是有效,例如,您可以修改一个文件,然后将该文件的修改时间戳更改为旧的时间戳。如果你这样做了,make会错误地猜测文件没有改变,因此可以被忽略。

全部目标和多个目标

如果有多个目标并希望所有目标都被执行,那么可以使用一个all目标,如下所示

all: one two three

one:
	touch one
two:
	touch two
three:
	touch three

clean:
	rm -f one two three

当规则有多个目标时,将为每个目标都运行命令,如下所示,其中$@是包含目标名称的自动变量

all: f1.o f2.o

f1.o f2.o:
	echo $@
# Equivalent to:
# f1.o:
#	 echo f1.o
# f2.o:
#	 echo f2.o

自动变量和通配符

*通配符

在Makefile中*和%是通配符,但它们的含义完全不同。*在文件系统中搜索匹配的文件名。*使用时最好包装在wildcard函数中,如下所示:

# Print out file information about every .c file
print: $(wildcard *.c)
	ls -la  $?

*不可以直接用在变量定义中,当*没有匹配到文件时如果没有使用wildcard函数包装,会直接保持原样。

thing_wrong := *.o # Don't do this! '*' will not get expanded
thing_right := $(wildcard *.o)

all: one two three four

# Fails, because $(thing_wrong) is the string "*.o"
one: $(thing_wrong)

# Stays as *.o if there are no files that match this pattern :(
two: *.o 

# Works as you would expect! In this case, it does nothing.
three: $(thing_right)

# Same as rule three
four: $(wildcard *.o)

%通配符

%通配符通常在多种情况下使用:

  • 在"匹配"模式下,它匹配一个或多个字符,这种匹配称为stem。
  • 在"替换"模式下,它使用匹配到的stem并在字符串中进行替换。
  • %最常用于规则定义和某些特定函数中

规则

隐式规则

  • 编译C程序:基于n.c生成n.o,使用命令$(CC) -c $(CPPFLAGS) $(CFLAGS) $^ -o $@。
  • 编译C++程序,基于n.cc或n.cpp生成n.o,使用命令$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $^ -o $@。
  • 链接单个目标文件:基于n.o生成n,使用命令$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@。 使用到的变量为
  • CC:编译C程序的程序;默认cc
  • CXX:编译C++程序的程序;默认g++
  • CFLAGS: 给 C 编译器的额外标志
  • CXXFLAGS: 提供给 C++ 编译器的额外标志
  • CPPFLAGS: 提供给 C 预处理器的额外标志
  • LDFLAGS: 在编译器应该调用链接器时提供给编译器的额外标志 基于隐式规则可以编译C/C++程序而不用显式地告诉make怎么做。

TO DO

后续有时间会添加关于更多规则以及变量与函数,还有命令的相关内容。

C++ Makefile 构建工具

本文目录

  • 参考教程
  • Makefile常用内容
    • Makefile基础使用
    • 全部目标和多个目标
    • 自动变量和通配符
    • 规则
  • TO DO

精选文章

  • 分布式ID生成方案全解析:从数据库到雪花算法
  • Redis ziplist、quicklist 和 listpack
  • 多目标优化问题及两种常用解法

按主题探索

  • Redis 数据结构
    从存储布局理解实现
  • Linux 与部署
    服务器、证书与建站实践
  • 算法与深度学习
    解题方法、优化与公式推导
  • SNN / NoC 论文
    互连网络与映射算法

名言警句

学而时习之,不亦说乎?《论语·学而》学而不思则罔,思而不学则殆。《论语·为政》知之为知之,不知为不知,是知也。《论语·为政》三人行,必有我师焉。《论语·述而》工欲善其事,必先利其器。《论语·卫灵公》不积跬步,无以至千里。《荀子·劝学》千里之行,始于足下。《老子·第六十四章》纸上得来终觉浅,绝知此事要躬行。陆游《冬夜读书示子聿》
学而时习之,不亦说乎?
《论语·学而》 一言
← Cmake 常用指令学习 Gdb调试学习 →

相关文章

  • Cmake 常用指令学习 Apr 30, 2023
  • Gdb调试学习 Apr 30, 2023
  • LJson Aug 16, 2023
  • Transfer Server Dec 23, 2023
皖ICP备2023003716号-1 | 公安备案皖公网安备34012202341113 | 违法和不良信息举报邮箱:1141751053@qq.com
Powered by Hugo & Explore Theme & Theme by SimonAKing.