《GUN Make项目管理》--第二章 规则

文章转载:https://blog.csdn.net/sinat_27953939/article/details/102488082

返回知识列表: GUN Make项目管理知识列表


make命令行选项

make --just-print #显示目标命令但并不实际执行
make --print-data-base #或-p,列出make具有的默认规则和变量
make --no-builtin-rules #或-r,不使用内置规则

第二章、规则

makefile显式规则:

target: prereq1 prereq2
    commands

工作目标: 必要条件1 必要条件2 ...
    命令

自动变量

核心自动变量

$@ #工作目标文件
$% #archive member结构中的文件名元素
$< #第一个必要条件的文件名
$? #时间戳在工作目标之后的所有必要条件
$^ #所有必要条件的文件名
$+ #同$^,允许重复的文件名
$* #工作目标的主文件名

VPATN变量 vpath命令

VPATH = src include #告诉make在src和include中搜索代码文件

vpath pattern directory-list
vpath %.l %.c src #在src目录中寻找.c、.h文件
vpath %.h include #在include中寻找.h文件

模式规则

%.o: %.c
    command

静态模式规则

$(OBJECTS): %.o: %.c #使该规则只作用于变量OBJECTS中的文件
    command

后缀规则(过时)

.c.o:
    command
#相当于
%.o: %.c
    command

.p:
    command
#相当于
%: %.p
    command

# .SUFFIXES设定已知的扩展名
.SUFFIXES: .out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l
# 删除所有已知扩展名
.SUFFIXES:

隐含规则

当make检查一个工作目标时,如果找不到可以更新它的显式规则,就会使用隐含规则。要使用隐含规则:当你将工作目标加入makefile时,只要不指定脚本就行了。

查看内置规则库:

make --print-data-base #或-p,列出make具有的默认规则和变量

假想工作目标

任何不代表文件的工作目标就叫假想工作目标。要声明一个假想工作目标,只需要将该工作目标指定为.PHONY(一个特殊工作目标)的一个必要条件即可。如 声明假想工作目标clean:

.PHONY: clean #声明它的必要条件不代表一个实际的文件,而且应被视为尚未更新
clean:
    rm -f *.o

标准的假想工作目标

all #执行所有工作
install #从已编译的二进制文件进行应用程序的安装
clean #删除产生自源代码的二进制文件
distclean #删除编译过程中产生的任何文件
TAGS #建立可供编辑器使用的标记表
info #从Texinfo源代码来创建GUN info文件
check #执行与应用程序相关的任何测试

特殊工作目标

特殊工作目标是一个内置的假想工作目标,用来变更make的默认行为。除了.PHONY以外,还有以下特殊工作目标:

.INTERMEDIATE #其必要条件会被视为中间文件,make结束时会被自动删除
.SECONDARY #其必要条件会被视为中间文件,但不会被自动删除,但加入档案库(archive)后就会被删除
.PRECIOUS #如果make在运行期被中断,它会删除除它正在更新的工作目标文件,确保不会留下未完成编译的文件。指定.PRECIOUS以阻止其删除行为
.DELETE_ON_ERROR #与.PRECIOUS作用相反,发生错误时删除工作目标文件

自动产生依存关系

一种makefile自动解决头文件依赖问题的解决方案,是通过如下的一个关键脚本:

include $(subst .c,.d,$(SOURCES)) #包含所有.c文件同名的.d文件
%.d: %.c
    $(CC) -M $(CPPFLAGS) $< > $@.$$$$;                 \
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
    rm -f $@.$$$$

解释一下上面的命令:

gcc -M source.c -M选项会搜索代码source.c所引用的所有头文件,并输出成makefile形式的“目标:依赖”形式。

… > @ . @.@.$KaTeX parse error: Can't use function '$' in math mode at position 34: …输出重定向到文件名<code>$̲@.KaTeX parse error: Can't use function '$' in math mode at position 17: …/code>。其中<code>$̲@</code>就是工作目标的…在shell中被扩展为当前所运行shell的进程ID,.$$$$是为了确保产生唯一的文件名。综上,第一行命令用每一个.c文件生成了一个.d.pid文件,.d文件中描述了同名.c文件对应目标文件的头文件依赖。

读懂第二行命令需要先了解shell中的sed命令。sed的s命令是执行字符串替换,将模式\($*\).o[ :]*替换为\1.o $@ : 主要作用是将.d文件名追加到.d文件中的工作目标中。

看文字有点绕,举个例子一个hello world程序main.c,gcc -M main.c > main.d生成的main.d的内容如下:

main.o: main.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
 /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/bits/long-double.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h \
 /usr/include/x86_64-linux-gnu/bits/types/__FILE.h \
 /usr/include/x86_64-linux-gnu/bits/types/FILE.h \
 /usr/include/x86_64-linux-gnu/bits/libio.h \
 /usr/include/x86_64-linux-gnu/bits/_G_config.h \
 /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/x86_64-linux-gnu/bits/sys_errlist.h

执行上述sed命令之后,通过创建并删除一个main.d.2196821968的临时文件,生成main.d内容为:

main.o main.d : main.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
 /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/bits/long-double.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h \
 /usr/include/x86_64-linux-gnu/bits/types/__FILE.h \
 /usr/include/x86_64-linux-gnu/bits/types/FILE.h \
 /usr/include/x86_64-linux-gnu/bits/libio.h \
 /usr/include/x86_64-linux-gnu/bits/_G_config.h \
 /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/x86_64-linux-gnu/bits/sys_errlist.h

第三行命令很明显,清理临时文件.d.pid。

管理程序库

ar命令选项:

r #replace,替换或创建库文件
v #verbosely,显示详细信息
t #列出程序库中的目标文件名

gcc链接程序库文件:

gcc a.o libc.a /lib/libfl.a -o main #需要指定路径,不建议使用
gcc a.o -lc -lfl -o main #方便,便于移植
gcc a.o -L. -lc -lfl -o main #指定库搜索路径,-L必须放到系统程序库之前,且作用于所有-l选项

makefile中创建和链接程序库

libcounter.a: counter.o lexer.o
    $(AR) $(ARFLAGS) $@ $^ #更新.a时,其中的成员全部更新

libcounter.a: counter.o lexer.o
    $(AR) $(ARFLAGS) $@ $? #只更新新的成员

libcounter.a: libcounter.a(lexer.o) libcounter.a(counter.o) #libcounter.a(lexer.o)
libgraphics.a(bitblt.o): bitblt.o
    $(AR) $(ARGLAGS) $@ $< #libcounter.a(lexer.o)# 引用库文件中的成员,在隐含规则中,可以省略

以程序库为必要条件

#可以使用路径名
xpong: $(OBJECTS) /lib/X11/libX11.a /lib/X11/libXaw.a
    $(LINK) $^ -o $@

#也可以使用-l语法,会优先搜索共享程序库
xpong: $(OBJECTS) -lX11 -lXaw
    $(LINK) $^ -o $@

如果makefile已经将程序库文件指定为工作目标,它就不能在必要条件里对该文件使用-l选项。如果要在makefile里进行程序库的编译工作,必须使用文件名的语法。

程序库在命令行上的顺序很重要,程序库A、B循环引用的一个解决方法是:-lA -lB -lA。但是makefile的自动变量$^会丢弃重复的部分,此时就应该使用$+

双冒号规则

通常当一个工作目标多次出现时,所有必要条件都会被衔接成一个列表,只会执行一个命令脚本进行更新,前面的规则会被后面的覆盖掉。

对于双冒号规则,相同的工作目标会被视为一个独立的实体,可以以不同的命令来更新同一个工作目标,实际执行的命令取决于哪个依赖文件被更改。

file-list:: generate-list-script
    chmod +x $<
    generate-list-script $(files) > file-list

file-list:: $(files)
    generate-list-script $(files) > file-list
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值