makefile(摘自linux_c编程一站式学习)

GNU make 的官方手册建议这样写:


all: main
main: main.o stack.o maze.o
gcc $^ -o $@
clean:
-rm main *.o
.PHONY: clean
sources = main.c stack.c maze.c
include $(sources:.c=.d)
%.d: %.c
set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$

sources 变量包含我们要编译的所有.c 文件,$(sources:.c=.d)是一个变量替换语法,把sources 变
量中每一项的.c替换成.d,所以include这一句相当于:


include main.d stack.d maze.d


类似于C语言的#include 指示,这里的include表示包含三个文件main.d、stack.d和maze.d,这三
个文件也应该符合Makefile的语法。如果现在你的工作目录是干净的,只有.c文件、.h文件
和Makefile ,运行make 的结果是:


$ make
Makefile:13: main.d: No such file or directory
Makefile:13: stack.d: No such file or directory
Makefile:13: maze.d: No such file or directory
set -e; rm -f maze.d; \
cc -MM maze.c > maze.d.$$; \
sed 's,\(maze\)\.o[ :]*,\1.o maze.d : ,g' < maze.d.$$ >
maze.d; \
rm -f maze.d.$$
set -e; rm -f stack.d; \
cc -MM stack.c > stack.d.$$; \
sed 's,\(stack\)\.o[ :]*,\1.o stack.d : ,g' < stack.d.$$ >
stack.d; \
rm -f stack.d.$$
set -e; rm -f main.d; \
cc -MM main.c > main.d.$$; \
sed 's,\(main\)\.o[ :]*,\1.o main.d : ,g' < main.d.$$ >
main.d; \
rm -f main.d.$$
cc
-c -o main.o main.c
cc
-c -o stack.o stack.c
cc
-c -o maze.o maze.c
gcc main.o stack.o maze.o -o main


一开始找不到.d文件,所以make 会报警告。但是make 会把include的文件名也当作目标来尝试更
新,而这些目标适用模式规则%.d: %c,所以执行它的命令列表,比如生成maze.d的命令:


set -e; rm -f maze.d; \
cc -MM maze.c > maze.d.$$; \
sed 's,\(maze\)\.o[ :]*,\1.o maze.d : ,g' < maze.d.$$ >
maze.d; \
rm -f maze.d.$$
 
注意,虽然在Makefile中这个命令写了四行,但其实是一条命令,make 只创建一个Shell进程执行这
条命令,这条命令分为5个子命令,用;号隔开,并且为了美观,用续行符\拆成四行来写。执行步骤为:


1. set -e命令设置当前Shell进程为这样的状态:如果它执行的任何一条命令的退出状态非零则
立刻终止,不再执行后续命令。


2. 把原来的maze.d删掉。


3. 重新生成maze.c的依赖关系,保存成文件maze.d.1234(假设当前Shell进程的id是1234)。注
意,在Makefile中$有特殊含义,如果要表示它的字面意思则需要写两个$,所以Makefile中的
四个$传给Shell变成两个$,两个$在Shell中表示当前进程的id,一般用它给临时文件起名,
以保证文件名唯一。


4. 这个sed 命令比较复杂,就不细讲了,主要作用是查找替换。maze.d.1234的内容应该
是maze.o: maze.c maze.h main.h,经过sed 处理之后存为maze.d,其内容是maze.o maze.d:
maze.c maze.h main.h。


5. 最后把临时文件maze.d.1234删掉。
不管是Makefile本身还是被它包含的文件,只要有一个文件在make 过程中被更新了,make 就会重新
读取整个Makefile以及被它包含的所有文件,现在main.d、stack.d和maze.d都生成了,就可以正常
包含进来了(假如这时还没有生成,make 就要报错而不是报警告了),相当于在Makefile中添了三
条规则:


main.o main.d:main.c main.h stack.h maze.h
maze.o maze.d: maze.c maze.h main.h
stack.o stack.d: stack.c stack.h main.h


如果我在main.c中加了一行#include "foo.h",那么:


1、main.c的修改日期变了,根据规则main.o main.d: main.c main.h stack.h maze.h要重新生
成main.o和main.d。生成main.o的规则有两条:


main.o: main.c main.h stack.h maze.h
%.o: %.c
# commands to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<


第一条是把规则main.o main.d: main.c main.h stack.h maze.h拆开写得到的,第二条是隐含规
则,因此执行cc命令重新编译main.o。生成main.d的规则也有两条:


main.d: main.c main.h stack.h maze.h
%.d: %.c
set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
因此main.d的内容被更新为main.o main.d: main.c main.h stack.h maze.h foo.h 。


2、由于main.d被Makefile包含,main.d被更新又导致make 重新读取整个Makefile,把新的main.d包
含进来,于是新的依赖关系生效了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Linux C编程一站式学习》是由宋劲杉编写的一本关于Linux C编程的教材,主要介绍了Linux系统下C语言的基础知识和常用编程技巧。这本教材以文章简洁明了、逻辑性强、实例丰富等特点而受到广大编程学习者的欢迎。 《Linux C编程一站式学习》首先从Linux环境的搭建开始,介绍了Linux操作系统的基本概念和架构,包括文件系统、进程管理、内存管理等方面的知识。随后,教材详细介绍了C语言的基本语法、数据类型、运算符等内容,帮助读者建立起对C语言的基本理解。 接下来,教材介绍了Linux下的C编程工具和开发环境,包括GCC编译器、Makefile文件、调试工具等,使读者能够顺利地进行C程序的编译和调试。同时,还提供了大量的实例代码和实践项目,帮助读者通过实际操作加深对C语言和Linux编程的理解。 此外,《Linux C编程一站式学习》还专门介绍了Linux下的网络编程、多线程编程、进程间通信等高级主题。这些内容有助于读者深入了解Linux系统的底层机制和编程技巧,提升自己的编程能力。 总而言之,《Linux C编程一站式学习》是一本系统全面介绍Linux下C编程的教材,适合初学者和有一定编程基础的读者阅读。通过学习此书,读者能够掌握Linux环境下的C语言编程技能,为进一步深入学习和应用打下坚实的基础。 ### 回答2: 《Linux C编程一站式学习》是由宋劲杉编写的一本关于Linux C编程的教材。该书主要针对初学者,通过系统地介绍Linux系统、C语言及相关编程知识,帮助读者快速入门并掌握Linux C编程。 这本书共包含七个章节,分别是Linux的基础知识、Linux常用命令、Linux系统编程基础、C语言基础、C语言高级特性、Linux C编程实例和Makefile的使用。 在第一章的基础知识部分,作者详细介绍了Linux操作系统的历史、特点以及常见的发行版。第二章中,读者将学习到如何使用常用的Linux命令进行文件操作、目录管理以及常见的文本处理任务。 第三章和第四章分别介绍了Linux系统编程的基础知识和C语言的基础知识。在这两章中,读者将学习到如何使用系统调用、文件I/O、进程控制和信号处理等Linux系统编程的关键技术,同时也将学会C语言的基本语法、数据类型、函数等知识。 第五章则深入讲解了C语言的高级特性,包括指针、内存管理、结构体、位运算等。这些知识对于理解和编写复杂的C程序非常重要。 第六章和第七章给出了一些实例,通过实际的代码演示如何使用Linux C编程进行文件操作、进程间通信、网络编程等。 此外,《Linux C编程一站式学习》还介绍了Makefile的使用,这是一个用于自动化编译和构建项目的工具,对于更加高效地管理和组织C程序非常有用。 总之,通过阅读《Linux C编程一站式学习》,读者可以全面了解Linux系统、C语言和相关编程知识,并通过实例的演示掌握Linux C编程的技巧和方法,是一本非常实用的学习资料。 ### 回答3: 《Linux C编程一站式学习》是宋劲杉先生所著的一本关于Linux下C编程的书籍。这本书以实例为基础,讲解了Linux下C编程的各个方面,涉及了C语言基础知识、Linux系统调用、进程管理、线程编程、文件操作等内容。 书籍以通俗易懂的语言和丰富的实例详细介绍了C语言的基本语法和开发环境的搭建,对初学者非常友好。在讲解Linux系统调用时,通过介绍进程管理、线程编程以及进程间通信等内容,帮助读者深入理解Linux操作系统的原理和机制。 值得一提的是,书中重点讲解了gcc编译器的使用方法和调试技巧,使读者能够更好地理解和掌握C语言程序的编译和调试过程。此外,书中还介绍了常见的Linux工具和库函数,如make、gdb、pthread等,帮助读者提高开发效率和代码质量。 总体来说,《Linux C编程一站式学习》是一本非常实用的Linux C编程入门教材。通过阅读本书,读者可以系统地学习并运用C语言进行Linux下的程序开发。无论是新手入门还是有一定经验的开发者,都可以从中受益。此外,书籍中的实例代码也可以帮助读者进一步加深对C语言的理解和应用。 推荐这本书给对Linux C编程感兴趣的读者,它会成为你学习和掌握Linux下C编程的良好指南。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值