GNU Make 中文手册v3.8 学习

更新时间:2023-05-31 21:49:53 阅读: 评论:0

这个手册翻译整理: 徐海兵, 先表示一些尊敬. “本人在工作之余,花了18个多月时间完成对info make”的翻译整理,完成这个中文版手册, 工夫不负有心人.
链接器将.o文件中使用的函数和其它.o或者库文件中的相关符号进行合并,对所有文件中的符号进行重新安排(重定位),并链接系统相关文件(程序启动文件等)最终生成可执行程序。
Linux中,共享库文件格式通常为ELF”格式。共享库已经具备了可执行条件。
模块中各个成员的地址(变量引用和函数调用)都是相对地址。使用此共享库的程序在运行时,共享库被动态加载到内存并和主程序在内存中进行连接。多个可执行程序可共享库文件的代码段(多个程序可以共享的使用库中的某一个模块,共享代码,不共享数据)。另外共享库的成员对象可被执行(由libdl.so提供支持)。
make祖冲之是哪个朝代的读取Makefile以后会建立一个编译过程的描述数据库。此数据库中记录了所有各个文件之间的相互关系,以及它们的关系描述(要是我能""到这个数据库,就能使用程序trace,你知道一个大型的projectmakefile有多复杂)
 
当使用make摩托车拉力赛工具进行编译时,工程中以下几种文件在执行make时将会被编译(重新编译):
1. 所有的源文件没有被编译过,则对各个C源文件进行编译并进行链接,生成最后的可执行程序;
2. 每一个在上次执行make之后修改过的C源代码文件在本次执行make时将会被重新编译;
3. 头文件在上一次执行make之后被修改。则所有包含此头文件的C源文件在本次执行make时将会被重新编译。(这就是为什么头文件修改后,很多文件都会被重新compile的原因)
 
首先书写时,可以将一个较长行使用反斜线(\)来分解为多行,这样可以使我们的Makefile书写清晰、容易阅读理解。但需要注意:反斜线之后不能有空格(这也是大家最容易犯的错误,错误比较隐蔽)
口香糖英语编译.c源文件规则的命令可以不用明确给出。这是因为make本身存在一个默认的规则,能够自动完成对.c文件的编译并生成对应的.o文件。它执行命令cc -c来编译.c源文件。
对一个目标文件是N.o”,倚赖文件是N.c”的规则,完全可以省略其规则的命令行,而由make自身决定使用默认命令。此默认规则称为make的隐含规则。
书写规则建议的方式是:单目标,多依赖。就是说尽量要做到一个规则中只存在一个目标文件,可有多个依赖文件。尽量避免多目标,单依赖的方式。这样后期维护也会非常方便,而且Makefile会更清晰、明了。
在这个Makefile中,根据依赖而不是目标对规则进行分组(Wrong!)。上例的Makefile就可以这样来实现:
#sample Makefile
objects = main.o kbd.o command.o display.o \
               inrt.o arch.o files.o utils.o
edit : $(objects)
          cc -o edit $(objects)
$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o inrt.o arch.o files.o : buffer.h
例子中头文件defs.h”作为所有.o文件的依赖文件。其它两个头文件作为其对应规则的目标中所列举的所有.o文件的依赖文件。
但是这种风格的Makefile并不值得我们借鉴。问题在于:同时把多个目标文件的依赖放在同一个规则中进行描述(一个规则中含有多个目标文件),这样导致规则定义不明了,比较混乱。一直的近义词建议大家不要在Makefile中采用这种方式了书写。否则后期维护将会是一件非常痛苦的事情。
include”指示符告诉make暂停读取当前的Makefile,而转去读取include有关于”指定的一个或者多个文件,完成以后再继续当前Makefile的读取。
通常指示符include”用在以下场合:
1. 有多个不同的程序,由不同目录下的几个独立的Makefile来描述其重建规则。它们需要使用一组通用的变量定义或者模式规则。
2. 当根据源文件自动产生依赖文件时;我们可以将自动产生的依赖关系保存在另外一个文件中,主Makefile使用指示符include”包含这些文件。这 样的做法比直接在主Makefile中追加依赖文件的方法要明智的多。其它版本的make已经使用这种方式来处理。(我想看看这方面的例子)
在这些目录下都没有找到我最敬佩的一个人include”指定的文件时,make将会提示一个包含文件未找到的告警提示,但是不会立 刻退出。而是继续处理Makefile的后续内容。当完成读取整个Makefile后,make将试图使用规则来创建通过指示符include”指定的 但未找到的文件,当不能创建它时(没有创建这个文件的规则),make将提示致命错误并退出。
通常我们在Makefile中可使用-include”来代替include”,来忽略由于包含文件不存在或者无法创建时的错误提示(-的意思是告诉make,忽略此操作的错误。make继续执行)。
 
Makefile中符号$”有特殊的含义(表示变量或者函数的引用),在规则中需要使用符号$”的地方,需要书写两个连续的($$”)。
Maekfile中表示文件名时可使用通配符。可使用的通配符有:*”、?”和[]”。
Makefile中这些统配符并不是可以用在任何地方,Makefile中统配符可以出现在以下两种场合:
1. 可以用在规则的目标、依赖中make在读取Makefile时会自动对其进行匹配处理(通配符展开);
2. 可出现在规则的命令中,通配符的通配处理是在shell在执行此命令时完成的。
除这两种情况之外的其它上下文中,不能直接使用通配符。而是需要通过函数wildcard来实现。
比如变量定义中使用的通配符不会被统配处理(因此在变量定义中不能使用通配符,否则在某些情况下会出现非预期的结果,下一小节将会详细讨论)。在 Makefile有这样一个变量定义:objects = *.o”。它表示变量objects”的值是字符串*.o”(并不是期望的空格分开的.o文件列表)。当需要变量objects”代表所有.o文件 列表示,需要使用函数wildcard”(objects = $(wildcar *.o)任务栏跑到右边去了怎么办)。
在规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数wildcard”,它的用法是:$()
Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。
般我们可以使用$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前 目录可生成的.o文件列表。因此在一个目录下可以使用如下内容的Makefile来将工作目录下的所有的.c文件进行编译并最后连接成为一个可执行文件:
#sample Makefile
objects := $(patsubst %.c,%.o,$(wildcard *.c))
北京丰台foo : $(objects)
        cc -o foo $(objects)
使用伪目标有两点原因:
1. 避免在我们的Makefile中定义的只执行命令的目标(此目标的目的为了执行执行一些列命令,而不需要创建这个目标)和工作目录下的实际文件出现名字冲突。
2. 提高执行make时的效率,特别是对于一个大型的工程来说,编译的效率也许你同样关心。
:make的并行和递归执行过程中。此情况下一般会存在一个变量,定义为所有需要make的子目录。对多个目录进行make的实现方式可以是:在一个规则的命令行中使用shell循环来完成。如下:

SUBDIRS = foo bar baz
subdirs:
     
for dir in $(SUBDIRS); do \
         
$(MAKE) -C $$dir; \
     
done
但这种实现方法存在以下几个问题:
1. 当子目录执行make出现错误时,make不会退出。就是说,在对某一个目录执行make失败以后,会继续对其他的目录进行make。在最终执行失败的情 况下,我们很难根据错误提示定位出具体是在那个目录下执行make时发生错误。这样给问题定位造成了很大的困难。为了解决这个问题,可以在命令行部分加入 错误监测,在命令执行错误后主动退出。不幸的是,如果在执行make时使用了-k”选项,此方式将失效。
2. 另外一个问题就是使用这种shell的循环方式时,没有用到make对目录的并行处理功能,由于规则的命令是一条完整的shell命令,不能被并行处理。 有了伪目标之后,我们可以用它来克服以上实现方式所存在的两个问题。

SUBDIRS = foo bar baz
.
PHONY: subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
       $(MAKE) -C $@
foo: baz
上边的实现中有一个没有命令行的规则foo: baz”,此规则用来限制子目录的make顺序。它的作用是限制同步目录foo”和baz”的make过程(在处理foo”目录之前,需要等待 baz”目录处理完成)。提醒大家:在书写一个并行执行makeMakefile时,目录的处理顺序是需要特别注意的。

本文发布于:2023-05-31 21:49:53,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/822671.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:文件   规则   使用   进行   执行   目标   目录   需要
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图