unix/linux make

4 篇文章 0 订阅

GNU:make

参考文档

程序的编译和链接

一般来说,无论是C还是C++,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。编译时,编译器需要的是语法的正确,函数与变量的声明的正确。只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件( .o 文件或 .obj 文件)。链接时,主要是链接函数和全局变量。所以,我们可以使用这些中间目标文件( .o 文件或 .obj 文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File)

makefile使用

基本写法:

target ... : prerequisites..
	command 
  • target:可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(label)。
  • prerequisite:生成该target所依赖的文件和/或target
  • command:该target要执行的命令(任意的shell命令)

核心规则:执行make时,make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。makefile只有一个最终目标,第一条规则的目标为最终目标

示例:一个包含3个头文件和8个c文件的的工程的Makefile内容

# Makefile中第一行一定是最终目标
edit : main.o kbd.o command.o display.o \
        insert.o search.o files.o utils.o
    cc -o edit main.o kbd.o command.o display.o \
        insert.o search.o files.o utils.o

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
search.o : search.c defs.h buffer.h
    cc -c search.c
files.o : files.c defs.h buffer.h command.h
    cc -c files.c
utils.o : utils.c defs.h
    cc -c utils.c
clean :
    rm edit main.o kbd.o command.o display.o \
        insert.o search.o files.o utils.o

注:clean不是文件,它是一个动作,冒号后面什么也没有


伪目标

“伪目标”并不是一个文件,只是一个标签(label),由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显式地指明这个“目标”才能让其生效。当然,“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义。为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显式地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”

稳健的make clean做法

.PHONY : clean
clean :
    -rm edit $(objects)

.PHONY 表示 clean 是一个“伪目标”。而在 rm 命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。当然, clean 的规则不要放在文件的开头,不然,这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean从来都是放在文件的最后”。只要有这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只有“make clean”这样

伪目标一般没有依赖的文件。但是,我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”,只要将其放在第一个。 如果你的Makefile需要一口气生成若干个可执行文件,但你只想简单地敲一个make完事,可以使用伪目标的特性

all : prog1 prog2 prog3
.PHONY : all

prog1 : prog1.o utils.o
    cc -o prog1 prog1.o utils.o

prog2 : prog2.o
    cc -o prog2 prog2.o

prog3 : prog3.o sort.o utils.o
    cc -o prog3 prog3.o sort.o utils.o

解释:Makefile中第一个目标是默认目标,即all。make通过隐式规则推导出all是一个伪目标,伪目标是一个标签不会生成文件,所以不会产生all文件,但是all依赖于其它三个目标,于是,其它三个目标的规则总是会被决议。也就达到了我们一口气生成多个目标的目的。

这里的显式.PHONY : all 不写的话一般情况也可以正确的执行,这样make可通过隐式规则推导出, “all” 是一个伪目标,执行make不会生成“all”文件,而执行后面的多个目标。建议:显式写出是一个好习惯。

伪目标也可以成为依赖

.PHONY : cleanall cleanobj cleandiff

cleanall : cleanobj cleandiff
    rm program

cleanobj :
    rm *.o

cleandiff :
    rm *.diff

make cleanall将清除所有要被清除的文件。cleanobjcleandiff这两个伪目标有点像“子程序”的意思。我们可以输入make cleanallmake cleanobjmake cleandiff命令来达到清除不同种类文件的目的


隐含规则

如果要使用隐含规则生成你需要的目标,你所需要做的就是不要写出这个目标的规则。那么,make会试图去自动推导产生这个目标的规则和命令,如果 make可以自动推导生成这个目标的规则和命令,那么这个行为就是隐含规则的自动推导。

foo : foo.o bar.o
    cc –o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)

等价于

foo : foo.o bar.o
    cc –o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
foo.o : foo.c
    cc –c foo.c $(CFLAGS)
bar.o : bar.c
    cc –c bar.c $(CFLAGS)

常用隐含规则

  1. 编译C程序的隐含规则:
    <n>.o 的目标的依赖目标会自动推导为 <n>.c ,生成命令是$(CC) –c $(CPPFLAGS) $(CFLAGS)
  2. 编译C++程序的隐含规则:
    <n>.o 的目标的依赖目标会自动推导为 <n>.c 或<n>.cc,并且其生成命令是 $(CXX) –c $(CPPFLAGS) $(CXXFLAGS) 。(建议使用 .cc 作为C++源文件的后缀,而不是 .C )
  3. 链接Object文件的隐含规则:
    <n> 目标依赖于 <n>.o ,通过运行C的编译器来运行链接程序生成(一般是 ld ),其生成命令是: $(CC) $(LDFLAGS) <n>.o $(LOADLIBES) $(LDLIBS) 。这个规则对于只有一个源文件的工程有效,同时也对多个Object文件(由不同的源文件生成)的也有效

还含有其它规则,这些规则在make执行中是有顺序也就是优先级的

隐含规则总使用的变量
在隐含规则中的命令中,基本上都是使用了一些预先设置的变量。你可以在你的makefile中改变这些变量的值,或是在make的命令行中传入这些值,或是在你的环境变量中设置这些值,无论怎么样,只要设置了这些特定的变量,那么其就会对隐含规则起作用。

例如,第一条隐含规则——编译C程序的隐含规则的命令是 $(CC) –c $(CFLAGS) $(CPPFLAGS) 。Make默认的编译命令是 cc ,如果你把变量 $(CC) 重定义成 gcc ,把变量 $(CFLAGS) 重定义成 -g ,那么,隐含规则中的命令全部会以 gcc –c -g $(CPPFLAGS) 的样子来执行了。

变量分为命令相关(如CC),参数相关(CFLAGS),无默认值则为空
在这里插入图片描述
在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值