Makefile文件规则

makefile文件由一组依赖关系和规则构成。每个依赖关系由一个目标(一般为可执行文件)和要创建这个目标所需依赖的一组源文件构成。而规则定义了目标的创建方式。

依赖关系的写法是:目标名称+冒号+空格或制表符tab,最后是由空格或制表符隔开的文件列表,如:

myapp: main.o b.o f.o

main.o: main.c a.h

b.o: b.c a.h b.h

f.o: f.c b.h f.h

make命令假设在makefile文件中的第一个目标myapp是想创建的目标文件,确定创建所需依赖的源文件,先检查有没有现成的文件,再看makefile文件中有没有说明如何创建该文件,如果都没有则将报告一个错误。这样找到目标文件那一条线上的所有文件。同时make命令能自行判断出创建所需文件的正确顺序。

还可以定义伪目标如 all: myapp myall.1,就将创建myapp以及其帮助文件。

 

规则:

首先提一条可能有点奇怪的makefile语法,就是空格和tab是有区别的,规则所在的行必须以tab开头,用空格将导致make不能正常工作。这有历史上的原因。

大多数规则都会包含一个简单的命令,该命令是可以在命令行窗口执行的。

myapp: main.o b.o f.o  

  gcc -o myapp main.o b.o f.o

main.o: main.c a.h  

  gcc -c main.c

b.o: b.c a.h b.h  

  gcc -c b.c

f.o: f.c b.h f.h  

  gcc -c f.c

如果我们想通过make实现:清除make过程中产生的中间文件、安装目标至指定目录下等等任务,可以在Makefile文件末尾加如下:

clean:  

  -rm main.o b.o.f.o

install: myapp

    @if [ -d $(INSTDIR) ]; \   

    then \   

    cp myapp $(INSTDIR);\   

    chmod a+x $(INSTDIR)/myapp;\  (设置所有用户可执行)   

    chmod og-w $(INSTDIR)/myapp;\  (设置去除other用户和同组用户的可写权限)   

    echo "Installed in $(INSTDIR)";\  

  else \   

    echo "sorry, $(INSTDIR) does not exist";\  

  fi

增加了2个新目标clean和install。

"clean: "表示没有依赖关系定义,只定义了规则。rm前带减号-,可让make命令忽略rm命令的执行结果,即使rm出错(如删除对象不存在)也不会返回和显示error,make clean都会成功。

install目标需要依赖myapp,因此必须先创建myapp。从myapp到install目标是通过一段shell脚本完成的。每行代码以反斜杠\结束,是使所有shell脚本命令在逻辑上处于同一行,作为一个整体传递给一个shell执行。同时以符号@开头可以使得make在执行这条规则前不会在stdout显示这些命令本身。

这其中有些脚本执行的执行需要你先具有root权限。

 

make命令最常用的3个选项是:

-f <makefilename>: 指定进行make所需的makefile文件名。默认会自动查找匹配名为makefile的文件,如找不到则再找名为Makefile的文件。Makefile也是最多人采用的命名,因为它也会出现在所在目标文件列表首位。如:make -f Makefile123。

-k 出现错误时仍然继续执行。该命令可以一次列出所有未成功编译的源文件。

-n 让make命令在正式执行操作前输出将要执行的操作步骤。

 

make命令的常用宏定义:

$@ 当前目标文件名

$< 当前所依赖的源文件的名称

$* 当前所依赖的源文件的名称(不带后缀名)

$? 当前目标所依赖的源文件列表中比当前目标文件还要新的文件

 

同时常会看到下面2个特殊字符:

-: 表示让make命令忽略所有错误。

@: 告诉make指令在执行某命令前不在标准输出显示该命令。@结合echo很有用。

 

内置规则

以上都对创建目标文件的规则(每个操作步骤)都做出了精确定义。其实,make命令自带有大量的内置规则,这些内置规则可以极大简化makefile文件中的内容。可以将文件makefile中用于制作目标的规则去掉,而只需指定依赖关系。makefile文件将相对变得很简单,如以下相应部分:

main.o: main.c a.h

b.o: b.c a.h b.h

f.o: f.c b.h f.h

 

make使用.<old_suffix>.<new_suffix>来定义一条通用规则,可以从旧后缀名文件创建新后缀名文件。如:

.cpp.o  

  $(CC) -xc++ $(CFLAGS) -I$(INCLUDE) -c $<

这里的$<表示具体使用时的依赖源文件(旧后缀名文件)的名称(带后缀名)。-xc++是告诉gcc编译器源文件是一个C++文件。

 

make用于函数库管理的语法是lib(file.o),用于将file.o文件合并入lib.a文件中,其内置规则常见形式如下:

.c.a:  

  $(CC) -c $(CFLAGS) $<  $(AR)

  $(ARFLAGS) $@ $*.o

第一条规则是编译源文件生成目标文件;第二条规则中宏$(AR)和$(ARFLAGS)的默认取值通常是命令ar和选项rv,表示用ar命令将新的目标文件添加到函数库中。

 

对于大型的项目,我们往往会将各个函数库下的源文件分不同的子目录存放。使用make完成这一工作的方法有2个:

1.在子目录中编写单独的makefile文件,用于编译该子目录下的源文件,并将它们保存到一个函数库中,最后将该库文件复制到上一级目录中:

mylib.a:  

  (cd mylib_directory;$(MAKE))

此后,执行make mylib.a,命令将首先切换到子目录下,并执行make命令。这两个命令被括号括起来,表示确保它们用同一个shell处理。

2.定义一些新宏,通过在已知宏($@, $<)的尾部追加字母得到:字母D表示目录,字母F表示文件,并用如下的规则替换相应的内置规则:

.c.o  

  $(CC) $(CFLAGS) -c $(@D)/$(<F) -o $(@D)/$(@F)

以上表示编译子目录中的源文件并将生成的目标文件置于子目录下。

接着进一步定义:

mylib.a: mylib/b.o mylib/f.o  

          ar -rv mylib.a $?

则函数库将被更新。

 

利用gcc -MM和makedepend工具等都可以自动生成依赖关系清单。

 

 

 

 

 

 

 

 

 

 

 

原文链接: https://www.cnblogs.com/edgarli/archive/2012/09/18/2691671.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    Makefile文件规则

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/63169

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 上午10:47
下一篇 2023年2月9日 上午10:47

相关推荐