《GNU make项目管理》笔记--规则(3)

1.管理程序库

程序库(archive library)是一个特殊的文件,该文件内含其他被称为成员的文件。程序库可用来将相关的目标文件聚集成

较容易操作的单元,例如,C的标准程序库lib.a就包含了许多低级的C函数。因为程序库如此常见,所以make对它们的创建、

维护以及引用提供了特别的支持。程序库的建立及修改可通过ar程序来进行。

下面我们看一个例子,程序包结构如下:

根目录

|---makefile

|----|include|

|           |___myutil.h

|           |___myutil2.h

|___|src|

|----myutil.c

|----myutil2.c

|__main.c

各文件内容如下:

main.c:

#include <stdio.h>

#include "myutil.h"

int main(void) {

myprint();

myprint2();

return 0;

}

myutil.h:

void myprint();

myutil.c:

#include <stdio.h>

void myprint(void) {

printf("this is myprint function.\n");

}

myutil2.h:

void myprint2();

myutil2.c:

#include <stdio.h>

void myprint2(void) {

printf("this is myprint2 function.\n");

}

makefile:

VPATH=src include

CPPFLAGS=-I include

main:myutil.o myutil2.o

main.o:myutil.h myutil2.h

myutil.o:myutil.h

myutil2.o:myutil2.h

我们可以把把util类打包成myutil.a,该程序由两个文件组成:myutil.o和myutil2.o。我们可以使用ar命令来创建此程序库。

[email protected]:~/makefile$ ar rv libutil.a myutil.o myutil2.o

ar: creating libutil.a

a - myutil.o

a - myutil2.o

选项r代表我们想要以制定的目标文件来替换程序里的成员;选项v代表ar必须详细地告诉,他做了哪些动作。rv选线给之后

的第一个参数时程序库的文件名,接着是遗传目标文件。执行ar命令之后所显示的信息里,你将会看到它以a来表示目标文件

已被加入程序库里了。

以r选项来使用ar命令,可让我们立即创建或更新一个程序库:

[email protected]:~/makefile$ ar rv libutil.a myutil.o

r - myutil.o

[email protected]:~/makefile$ ar rv libutil.a myutil2.o

r - myutil2.o

一个程序被链接到一个可执行文件的方法有好几种,最简单的方法就是在命令行直接制定该程序库,编译器或连接器将会

以文件的扩展名来判断命令行上特定的类型并做正确的事情:

gcc main.o libmyutil.a -o main

gcc将libmyutil.a视为程序库,并对他们搜索未定义的符号,在命令行上引用程序库的另一个方法就是使用-l选项:

gcc main.o -lmyutil -o main

/usr/bin/ld: cannot find -lmyutil

collect2: error: ld returned 1 exit status

-l选项可省略程序库文件名的前缀以及扩展名,当gcc看到-l想俺想时,就会在系统的标准程序库目录中搜索相应的程序库。

这样,程序员就不必知道程序库的确切位置,而且可以让其所使用的命令行更具有可移植性。若要变更编译器所使用的搜索

路径,可以使用-L选项制定所要搜索的目录以及搜索的次序:

gcc main.o  -L. -lmyutil -o main

2.创建与更新程序库

下面就是一个用来创建程序库的简单规则:

libcounter.a : counter.o lexer.o

$(AR)  $(ARFLAGS) [email protected] $^

然而有一个问题,程序里所有的成员每次都会被替换掉,及时它们并没有被修改,不过我们可以做的更好:

libcounter.a : counter.o lexer.o

$(AR)  $(ARFLAGS) [email protected] $?

在gnu make中,还可以使用能够如下符号来引用程序库里的成员:

libgraphics.a(bitblt.o):bitblt.o

$(AR) $(ARFLAGS)  [email protected]  $<

3.以程序库为必要条件

当程序库作为必要条件时,可以使用标准的文件名语法或-l语法来引用它们。使用文件名语法时:

xpong:$(OBJETS) /lib/x11/libX11.a /lib/X11/libXaw.a

$(LINK) $^ -o [email protected]

连接器将会读取命令行上所列出的程序库文件,以及按正常的方式来处理它们。使用-l语法时,必要条件并非真正的文件

名称:

xpong: $(OBJECTS) -lX11 -lXaw

$(LINK) $^ -o [email protected]

第一种语法将会忽略共享程序库病使用链接行上所指定的程序库,第二种语法会使得make优先选择共享程序库。

有一个小问题,如果makefile已经将程序库文件指定为工作目标,它就不能在必要条件里对该文件使用-l选项,举例来说:

count_words:count_words.o -lcounter -lfl

$(CC) $^ -o [email protected]

libcounter.a:libcounter.a(lexer.o) libcounter.a(counter.o)

运行make,将会显示如下错误:

no rule to make target ‘-lcounter’,needed by ‘count_words‘

这是因为make不会把-lcounter扩展成libcounter.a并去搜索工作目标,make只会去搜索程序库。

要让复杂程序的链接工作没有错误,可能需要使用一些手段,连接器会一次搜索命令行上所指定的程序库。所以,如果程序

库A使用了一个未定义的符号,例如open,而且该符号定义在程序库B中,那么你就必须爱链接命令行上于B之前指定A。否则

一旦连接器读进A并且看到未定义的符号open,再回头来读取B就太迟了,连接器并不会回头来读取前面的程序库。

一个比较相关的问题就是程序见的相互引用,假设程序库B现在引用了程序库A中所定义的符号,我们知道A必须放在B的前面,

不过现在B必须放在A的前面,这个问题的解决方案就是在B之前与之后使用A:-lA -lB -lA。例如:

xpong:xpong.o libui.a libdynamics.a libui.a -lX11

$(CC) $^ -o [email protected]

但是此时$^会被扩展成:xpong.o libui.a libdynamics.a /usr/lib/X11R6/libX11.a,因为$^会自动去掉重复的部分。为了解决这个

问题需要使用S+。

时间: 2024-08-05 07:12:19

《GNU make项目管理》笔记--规则(3)的相关文章

《GNU make项目管理》笔记--规则(2)

1.模式规则 有如下的源代码树: 根目录 |---makefile |----|include| |           |___myutil.h |___|src| |----myutil.c |__main.c 各文件内容如下: main.c: #include <stdio.h> #include "myutil.h" int main(void) { myprint(); return 0; } myutil.h: void myprint(); myutil.c:

《GNU make项目管理》笔记--变量与宏(1)

make包含两种语言.第一种语言用来描述工作与必要条件所组成的依存图.第二种语言是宏语言,用来进行文字替换.像 C预处理器,m4以及宏汇编器. 一个变量名称几乎可以由任何字符自称.包括大部分的标点符号,即使空格也可以使用,但应该避免这么做.事实上只有: .#和=等字符不允许使用在变量名称中. 变量名称是区分大小写的.要取得某个变量的值,请使用$()括住该变量的名称,有一个特例:变量名称若为单一字母(letter) 则可以省略圆括号,所以请直接使用$letter. 你还可以使用花括号来扩展变量,例

GNU/Linux复习笔记(1)

第一次接触GNU/Linux还是大四上学期实习的那两个月在window里装了 个虚拟机玩红帽的系统,那段时间稍微学了一点命令就不玩了.后来大四下学期认识了王总,装了双系统,那段时间又对linux有了进一步认识并产生了很大的 兴趣.直到上学期突然发疯把笔记本装debian8以后才完全进入linux的世界.学习真的是一个螺旋式上升的过程.下面进入正题: ---Linux的基本原则: 1.由目的单一的小程序组成,组合小程序完成复杂任务(KISS:keep it simple,stupid)2.一切皆文

PMP项目管理笔记 项目定义

项目的定义 项目是为创造独特的产品,服务或成果而进行临时性的工作. 项目是组织的经营需要与战略目标服务的. PMBOK 指南描述的项目管理知识,从本质上讲,是用来管理中等或以上规模,跨部门,跨专业的目的.PMP考试中的项目,通常也是这类项目. 项目的三个特新 1.临时性 2.独特性 3.渐进明细性     项目许多地方需要渐进明细,例如    1.项目的范围    2.项目的计划    3.项目的目标    项目管理特别强调项目的特性和项目的计划都是逐渐细化出来的,因为:     项目的各种情况

Gnu make学习笔记

# 单行注释# 多行注释:脚本语言大多是行注释:若想多行注释,建议每行首用#号.可替代方法是行尾续行符,但这样不太好 # Makefile规则结构# target:[prerequisites]# command# 或者# target:[prerequisites]; command# 其中每条command需要以Tab开始,遵从shell语法.如果用";"隔开的话,就不用Tab了# 注意不要轻易以Tab开头,以Tab开头的命令都被交给系统shell去接手了# make后执行的默认是

2017.07.06 IT项目管理笔记整理 第二章

软件开发的目标--按时按预算开发出满足用户真实需要的软件.软件项目需求概述:软件开发的目标:按时按预算开发出满足用户真实需要的软件.需求:一个软件项目的开始阶段.软件需求的定义:1).用户解决问题或达到目标所需的条件或能力.2).系统或系统部件要满足合同.标准.规范或其他正式文档所需要具有的条件或能力 3).一种反映上面(1)或(2)所描述的条件或能力的文档说明. 软件需求4个抽象的层次 原始问题的描述.用户需求.系统需求和软件设计描述. 编写用户需求文档的原则 1标准的格式 2)使用一致的语言

2017.07.06 IT项目管理笔记整理 第五章软件项目风险管理

风险是不确定的事件,一旦发生,将会造成消极影响.风险发生的概率越高,造成的影响越大,就越是高风险,否则就是中等风险或低风险. 风险的三要素:一个未来的事件,事件发生的概率,事件的影响 风险的分类:(1)从风险的范围角度上看,风险分为三种类型:项目风险:潜在的项目预算.进度.人员.资源.用户和需求等方面的问题.技术风险:实现和交付产品过程中所应用的各种技术所包含的风险.技术的正确性.不确定性.复杂性.技术陈旧等因素都可带来技术风险.商业风险:与市场.企业产品策略等因素有关的风险. (2)从风险可预

2017.07.06 IT项目管理笔记整理 第四章

进度是对执行的活动和里程碑所制定的工作计划日期表. 进度问题是项目生命周期内造成项目冲突的主要原因. 时间管理原则: 1.区分重要与紧急的关系 2.适当运用Pareto原则 3.合理预算 4.有限反应 5.果断决策 6.大胆.完整的授权 7.例外管理 8.效能与效率 9.活动与效果 时间管理技巧: 1.每日计划 2.预料 3.分析时间 4.最后时限 5.上交问题 6.合并 7.反馈 8.计划躲避 9.可见性 10.习惯软件项目进度管理的主要过程: 1活动定义,确定项目团队成员和项目干系人为完成项

2017.07.07 IT项目管理笔记整理 第10章 敏捷软件开发

什么是敏捷软件开发方法 1.敏捷方法是一类软件开发流程的泛称: 2.敏捷方法是相对于传统的瀑布式软件过程提出的: 3.敏捷方法可以用敏捷宣言(4条).敏捷原则(12条)来概括: 4.敏捷原则通过一系列的敏捷实践来体现出来: 敏捷开发软件的特点:1敏捷软件开发更强调程序员与业务专家.用户之间的紧密合作,面对面的沟通,认为这种方式更有效 2能够很好地根据需求的变化编写代码 3频繁交付新的软件版本 4采用紧凑和自组织的软件开发团队 5更注重个体在软件开发中的作用 敏捷软件开发的方法有:1极限编程 2.