1. 目标 依赖 命令

make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。

2. 示例一

在Makefile中的命令,必须要以[Tab]键开始。

#include<stdio.h>
#include"add.h" int main()
{
int result=0;
result = add(2, 3);
printf("2+3=%d\n", result);
}
main: main.o add.o
gcc -o main main.o add.o
main.o : main.c add.h
gcc -c main.c
add.o : add.c add.h
gcc -c add.c
clean:
rm *.o

在默认的方式下,也就是我们只输入make命令。那么,

1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。

2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。

3、如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。

4、如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)

5、当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件edit了。

3. 示例二(变量申明)

objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c

 4. 自动推导,隐晦规则

只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。我们的是新的makefile又出炉了。

objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
rm edit $(objects)

5.

GNU的make工作时的执行步骤入下:(想来其它的make也是类似)

    1、读入所有的Makefile。

    2、读入被include的其它Makefile。

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

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

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

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

    7、执行生成命令。

当make需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自动去找。Makefile文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。

VPATH = src:../headers

上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔。(当然,当前目录永远是最高优先搜索的地方)

%.c是GUNmake语法层,表示的是所有以".c"结尾的文件,而*.c则是linux shell 语法层的,比如:rm -f *.o 类似的。

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

上面的例子中,指明了我们的目标从$object中获取,“%.o”表明要所有以“.o”结尾的目标,也就是“foo.o bar.o”,也就是变量$object集合的模式,而依赖模式“%.c”则取模式“%.o”的“%”,也就是“foo bar”,并为其加下“.c”的后缀,于是,我们的依赖目标就是“foo.c bar.c”。而命令中的“$<”和“$@”则是自动化变量,“$<”表示所有的依赖目标集(也就是“foo.c bar.c”),“$@”表示目标集(也就是“foo.o
bar.o”)。于是,上面的规则展开后等价于下面的规则:

foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o

有些时候,命令的出错并不表示就是错误的。例如mkdir命令,我们一定需要建立一个目录,如果目录不存在,那么mkdir就成功执行,万事大吉,如果目录存在,那么就出错了。我们之所以使用mkdir的意思就是一定要有这样的一个目录,于是我们就不希望mkdir出错而终止规则的运行。

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

clean:

-rm -f *.o

6. 定义命令包

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

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

这里,“run-yacc”是这个命令包的名字,其不要和Makefile中的变量重名。在“define”和“endef”中的两行就是命令序列。这个命令包中的第一个命令是运行Yacc程序,因为Yacc程序总是生成“y.tab.c”的文件,所以第二行的命令就是把这个文件改改名字。还是把这个命令包放到一个示例中来看看吧。

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

我们可以看见,要使用这个命令包,我们就好像使用变量一样。在这个命令包的使用中,命令包“run-yacc”中的“$^”就是“foo.y”,“$@”就是“foo.c”(有关这种以“$”开头的特殊变量,我们会在后面介绍),make在执行命令包时,命令包中的每个命令会被依次独立执行。

如何编写 Makefile的更多相关文章

  1. 如何自己编写Makefile

    如何自己编写Makefile   相信很多朋友都有过这样的经历,看着开源项目中好几页的makefile文件,不知所云.在日常学习和工作中,也有意无意的去回避makefile,能改就不写,能用ide就用 ...

  2. 教会你如何编写makefile文件

    最近一直在学习makefile是如何编写的.当我们写的程序文件比较少的时候,敲入gcc /g++,当你在大型工程中,在一个个编译文件的话,你可能就会很郁闷.linux有一个自带的make命令,它让你的 ...

  3. 如何编写makefile

    一:Makefile介绍: Makefile是为自动化编译而生.我们写好makefile文件后,只需要一个make命令,就可以完成整个项目的编译工作,大大提高了开发效率. 也许刚开始学习编程时,你不会 ...

  4. 如何编写Makefile,一份由浅入深的Makefile全攻略

    本文转载整理自陈浩大大的文章(跟我一起写 Makefile),由于原文内容庞大,故梳理出目录结构以便于学习及查阅参考. 一.概述 —— 什么是makefile?或许很多Winodws的程序员都不知道这 ...

  5. 如何编写makefile文件

    最近一直在学习makefile是如何编写的.       当我们写的程序文件比较少的时候,敲入gcc /g++,当你在大型工程中,在一个个编译文件的话,你可能就会很郁闷.linux有一个自带的make ...

  6. 根据给定文件编写Makefile文件 两种方法编译

    实例一 1.分析源文件代码依赖关系 mian.c #include "test1.h" #include "test2.h" #include <stdi ...

  7. 转:教会你如何编写makefile文件

    最近一直在学习makefile是如何编写的.当我们写的程序文件比较少的时候,敲入gcc /g++,当你在大型工程中,在一个个编译文件的话,你可能就会很郁闷.linux有一个自带的make命令,它让你的 ...

  8. Linux下编写 makefile 详细教程

    原文地址: https://www.cnblogs.com/mfryf/p/3305778.html 近期在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到make ...

  9. 如何编写Makefile?

    //swap.c #include<stdio.h> int swap(int *x,int *y) {printf("a=%d b=%d\n",*x,*y); int ...

  10. 为多个文件夹下的C源代码编写Makefile文件

    上一篇文章写了如何为在同一个文件夹下的C源代码,本篇文章为多个文件夹下的C源代码编写Makefile文件. 建立两个文件夹,分别为abs与src.其最终目录结构如下: 1 $ ls * 2 jun.c ...

随机推荐

  1. Codeforces Round #324 (Div. 2) (快速判断素数模板)

    蛋疼的比赛,当天忘了做了,做的模拟,太久没怎么做题了,然后C题这么简单的思路却一直卡到死,期间看了下D然后随便猜了下,暴力了下就过了. A.找一个能被t整除的n位数,那么除了<=10以外,其他都 ...

  2. [Docker]学习笔记--搭建gitlab

    Gitlab 是一个用于仓库管理系统的开源项目.使用Git作为代码管理工具,并在此基础上搭建起来的web服务. 详细介绍可以参照官网,https://about.gitlab.com/ 今天主要是通过 ...

  3. 《从零开始学Swift》学习笔记(Day 36)——静态方法

    原创文章,欢迎转载.转载请注明:关东升的博客 静态方法与静态属性类似,Swift中定义了静态方法,也称为类型方法.静态方法的定义与静态属性类似,枚举和结构体的静态方法使用的关键字是static:类静态 ...

  4. 《从零开始学Swift》学习笔记(Day 26)——可选链

    原创文章,欢迎转载.转载请注明:关东升的博客 在Swift程序表达式中会看到问号(?)和感叹号(!),它们代表什么含义呢?这些符号都与可选类型和可选链相关,下面来看看可选链. 可选链: 类图: 它们之 ...

  5. EasyPlayer-RTSP-Android安卓播放器播放RTSP延迟优化策略,极低延时!

    EasyPlayer-RTSP-Android安卓RTSP播放器低延迟播放延时优化策略 EasyPlayer-RTSP-Android播放器是一款专门针对RTSP协议进行过优化的流媒体播放器,其中我们 ...

  6. SharePoint服务器端对象模型 之 对象模型概述(Part 2)

    (三)Url 作为一个B/S体系,在SharePoint的属性.方法参数和返回值中,大量的涉及到了Url,总的来说,涉及到的Url可以分为如下四类: 绝对路径:完整的Url,包含了协议头(http或h ...

  7. 初学习-python打印乘法表、正方形、三角形

    for x in range(1,4): for o in range(0,x-1): print('*',end='') pass pass print('*') print('\n')print( ...

  8. POCO c++ 使用例子

    .定时器 #include "Poco/Timer.h" #include "Poco/Thread.h" using Poco::Timer; using P ...

  9. MySQL中因为unique key 非空唯一索引存在导致修改主键失败案例

    研发在早期的设计中,由于设计方面的问题,导致在设计表结构的时候,有个表有非空唯一索引而没有主键 在InnoDB存储引擎中,如果没有主键的情况下,有非空唯一索引的话,非空唯一索引即为主键. 那么这就会有 ...

  10. Android学习资源网站大全

    https://github.com/zhujun2730/Android-Learning-Resources 整理了一些 Android 的博客链接.学习资源网站.站在巨人的肩膀上,会看得更远.整 ...