MakeFile基础入门用法简介

很久以前写的一篇技术备忘了,隐约记得当时是看了APUE 2nd Edition这本书后,下载的源码在CentOS7以及MacOX10.X上都编译不过。在解决编译问题的同时,被APUE源码中的MakeFile中的天书给震惊后,学习了一些相关入门知识。并以看懂并向后来的好奇宝宝们解释APUE的MakeFile含义作为小目标,记录了这篇文章。

1. MakeFile的基础格式

target...:prerequisites
    command
    ...

target 就是我们需要生成的目标文件。可以是可执行文件,也可以是object file中间文件,还可以是其他的标签
prerequisites 就是target所依赖的文件
command 就是生成target需要执行的命令,特别注意的是所有的shell command都可以在这里执行

下面就是一个最朴实的MakeFile文件,没有使用任何技巧

all:foo
foo:hello.o world.o
    gcc -o foo hello.o world.o -I.
hello.o:hello.c hello.h world.h
    gcc -c hello.c
world.o:world.c world.h
    gcc -c world.c
clean:
    rm hello.o world.o

2. 隐晦(高级)规则

我们可以给需要编译的这些文件名称用一个变量来代替,有点像常量的使用方法一样
其实我们看到的那些开源代码的Makefile用了很多隐晦规则
比如test.o一般来说对应的源文件就是test.c,并且调用编译器生成[.o]文件也是固定的。那么我们就不用像上面那样这样写了,而是像下面一样省略

objects=hello.o world.o
all:foo
foo:$(objects)
    gcc -o foo $(objects)
hello.o:hello.h world.h
world.o:world.h
.PHONY:clean
clean:
    rm $(objects)

注释和shell脚本一样用#号,记得命令必须以tab开头
命令前面加一个-减号是告诉make忽略这条命令可能引起的错误
代表了$HOME目录,fengzhao代表了某位

自动化变量
$? 所有比target更新的prerequisites,以空格间隔,如下所示

print:*.c
    lpr -p $?

特别注意的是,make为变量赋值一个含有通配符的变量需要用上wildcard函数,否则通配符就不会被解释
objects=.o #objects真的就只是.o而已
objects:=$(wildcard *.o)#objects会用通配符去展开这个变量得到当前目录下面的中间文件
:= 和 = 的区别是

A=$(B)
B=hello.c world.c#上一行还没有定义B,但是用=已经可以引用到后面定义的B,然后给A赋值

B:=hello.c world.c
A:=$(B)#用:=进行必须引用已经定义了的变量

==?=== 的意思是 hello?=world 如果hello没有定义的话,它就等于world。如果定义了的,那么什么都不做

3. 多个target的语法

target可以是多个
静态模式的形式如下

target:target-pattern:prereq-pattern
    command
    ...

举个例子来说明

objects=hello.o world.o
$(objects):%.o:%.c
    $(CC) -c $(CFLAGS) $< -o $@

第二行的意思就是目标是objects里面那些[.o]文件,把xxx.o中的xxx取出来,找到的xxx.c就是其依赖的文件

==$<== 表示的 prereq-pattern 指代的文件,在这里就是 hello.c world.c
==$@== 表示的 target 指代的文件,在这里就是 hello.o world.o
再看一个加入了filter函数的例子

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

这里的filter就是一个make build-in函数。函数名和参数用空格分隔,参数之间用,分隔

source=hello.c world.c
include ($source:.c=.d)

这个语法的意思是用.d来替换source中的.c(.c必须是结尾处的),然后形成新的新的集合

source=hello.c world.c
include ($source:%.c=%.d)

该语法的效果同上,只不过用的是静态规则

在命了前面加上 @ 可以让命令不显示出来
如果要执行多条(行)命令,且后面的命令依赖前面的命令,需要在命令之间加上 ; 号,并且写在一行
==$^== 表示 prereq 指代的文件集合并且去重
==$*== 表示模式 % 符号前面的部分

x=var1
var2=Hello
y=$(subst,1,2,$(x))

这里的函数subst是把$(x)中的1全部替换成2,所以y最后等于Hello

4. 其它更老的规则

模式变量

prog:CFLAGS=-g

目标变量

%.o:CFLAGS=-O

这两种变量都是,当且仅当特定的目标需要被执行打时候,用设置的变量取代环境变量的值

后缀规则,其实就是老式的隐含规则

.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

库文件的目标是

helloworld.a(hello.o world.o):hello.o world.o
    ar cr helloworld.a hello.o world.o

看APUE的make发现它的makefile写的那叫一个简单,能用隐含规则的全部用上了
比如 all: helloworld 就这么一句,合理推测的话,make会去自动寻找helloworld.c并去调用对应compile规则
比如 objs: hello.o world.o 也是一句,道理同上
还需要注意的是

编译 .c 文件到可执行文件的隐含规则的名字叫

COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c

链接 .c 文件到obj文件的隐含规则的名字叫

LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDDIR) $(LDFLAGS)

没想到看了上面这么多的内容,APUE的makefile还是遇到了小挑战,不过思考后还是解决了

GCC

gcc -c hello.c //将只生成 hello.o

链接

  • ar 命令的作用是把obj文件,打包成一个 .a 库文件,ar rv libtest.a hello.o fibo.o 便于其他的程序链接 libtest.a。其他程序通过 -ltest 就可以链接到这个库
  • nm 命令的作用是查看 ar 命令打包好的 .a 库文件里面由哪些符号构成
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 来自陈浩的一片老文,但绝对营养。 示例工程:3 个头文件*.h,和 8 个 C 文件*.c。 初 编译过程,源文件...
    周筱鲁阅读 4,675评论 0 17
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • makefile关系到整个工程的编译规则,一个工程中的源文件不计其数,按其类型、功能、模块分别放在若干的目录当中,...
    Joe_HUST阅读 1,870评论 0 3
  • @(linux 编程)[开发技能, 工具使用] What is GNU Make Make 是控制工程中通过源码生...
    orientlu阅读 11,319评论 0 26
  • 碧斯诺兰深度了解 我现在所从事的是我们国产的碧斯诺兰这个品牌。碧斯诺兰是 一个非常 有实力的一个公司。在2004年...
    何蓉阅读 379评论 0 3