您的位置:首页 > 其它

深入理解软件构建系统原理与最佳实践阅读笔记

2013-11-18 22:54 459 查看
深入理解软件构建系统原理与最佳实践 仲田译

Software Build Systems Principles and Experience (by Peter Smith)

——书非借不能读也

前言

2013年11月16日17:11:52

*ide的build向shell脚本或make等更高级的构建系统的发展是对效率的提升。

shell:

cc -0 sorter.exe mainc.c sort.c files.c tree.c merge.c

makefile:

#begin

SOURCE = mainc.c sort.c files.c tree.c merge.c

OBJECTS = $(SOURCE:.c=.o)

sorter: $(OBJECTS)

$(CC) -o $@ $^

-include $(SOURCE:.c=.d)

%.d: %.c

@$(CC) -MM $(CPPFLAGS) $< | sed `s#\(.*\)\.o: #\l.o\1.d: #g` > $@

#end

*隐藏构建的细节,让使用人员只看到他们关心的部分:

#begin

SOURCE := mainc.c sort.c files.c tree.c merge.c

PROGRAM := sorter

LIBRARYS := libc libz

include framewrok.mk

#end

本书讲这种方案只适合与中小规模的产品,原因是例如引入了第三方的库之后必然要修改至少一方的构建系统。

*让开发环境保持一种可维护的状态,以以提升生产的效率。

*本书讲统计发现构建系统降低开发人员的平均生产率约12%,或者更高,这一点我深表赞同,我们每次重新构建10分钟呀。

10%损失的多数表现:

1. 错误的信赖关系导致编译失败

2. 错误的信赖关系导致无效的软件实体

3. 编译速度太慢

4. 花时间更新构造描述文件

*10%的效率损失即10%的财务损失,如果有10人的团队,则一年下来,大致是一个人拿工资不干活。

*单体构建:整个代码库编译只产生一个可执行的程序

组件构建:在把源代码划分成多个层级,分别分别单独编译,最终构建可执行的程序

第一部分

基础知识

第一章

2013年11月16日18:02:47

*把某种形式的数据(即输入)转化成另一种形式的数据(即输出),构造系统可以管理这其中涉及的各项活动。

*我对软件构建系统总体的理解:定义【目标】,定义目标的【信赖项】,定义信赖项长成目标的【生成规则】,构建系统保证在【信赖项】有变化时,根据【生成规则】重新生成【目标】。

计划构建系统还可以干什么事情只是举例,抓住核心才能以不变应万变。

*编译型语言构建的关键元素:

1. 版本控制工具:如CVS, Subversion, Git

2. 源树与目标树:源文件集合与编译后生成的目标文件的集合

3. 编译工具:根据输入生成输出的一种工具

4. 构造机器:计算机设备,编译工具在上面运行

5. 发布打包(release package)与目标机器 :分发给最终的用户,及输出的目标程序运行的计算机设备

*对单元测试理解的纠正:单元测试包更重要的使用应该是在目标机器上执行概念设计中的用例,其实也可以这样来理解:单元测试上开发人员来保证类及函数的正确性,冒烟测试来对应这里的单元测试的构建

*区别如下概念:

编译器:把源文件编译成目标文件(如cl)

编译工具:compilation tool, 把输入转换成输出的工具(如gcc, javac)

构造工具:build tool, 所处的层面比编译工具更高,它必须源文件与目标文件的关系,对整个构造过程进行居中协调,即构造工具调用必要的编译工具来最终构造出输出结果(如make, ant, scons, cmake, eclipse等)

*原生编译环境:native compilation 目标机器与构造机器是同一类

跨平台编译环境:cross-compilation 目标机器与构造机器是不同的操作系统或不同的cpu的环境

2013年11月18日21:20:51

构造描述(build description): 即写在makefile中的内容,

或是写在如SConstruct(Scons类型的python编译工具)的描述文本,如程序stock由两个文件生成:

Program("stock",["ticker.c", "currency.c"])

每种构造工具在描述构造过程时都有自己的语法,包括描述文件信赖关系和编译命令的语法。

健全性构造(Sanity build):即软件能否正字编译的检测,如进行【每日构造(dayly build)】,【每夜构造(nightly build)】

构造管理工具(build-managerment):与版本控制工具沟通,检出构造树,启动编译系统对软件进行编译,在构造完成之后向开发人员发出通知。可看成是构造系统之上的管理工具。

作者定义好的管理工具的特性:

*根据预先确定的计划,或在新代码提交之后进行构

*提供一套排除机制,让多个构造任务排除使用机器资源池

*在构造开始、完成、成功与失败时向各种组发送电子邮件

*在每次构建成功时自动升级版本号

*在归档文件中存放可供测试人员使用的最终软件包

*在构造成功之后自动进行健全性测试

*能测试出最近检入错误代码人员的名单

商用与开源构造管理工具如:Build Forge, ElectricCommander, CruiseControl, Hadson等

构造系统的质量:易用性,正确性,性能,可伸缩性

扫盲:

*JSP: JavaServer Page

ASP: Active Server Page

PHP: Hypertext Preprocessor

*静态分析工具:

Converity Prevent

Klocwork Insight

FindBugs

第2章

基于Make的构造系统

2013年11月18日21:55:48

make的语法的理解有助于理解任务构造系统底层的基础概念,所以以前学习陈浩的跟我学Makefil还是有用的,虽然自己不能写,但至少能大致的看的懂。

gcc -g(要求包含调试信息) -c(要求生成目标文件即add.o) add.c

gcc -g -o(要求连接) calculator add.o

信赖关系图(dependency graph):不仅列出了参与构造过程的文件,还展示了这些文件以之间的信赖关系。诸如Make等的构造工具,使用信赖关系图来判断要对哪些文件进行编译,以及如何编译

规则(rule):定义信赖项,及生成规则

增量式构造(incremental build):根据信赖关系图来进行判断,只在要信赖项的时间戳大小生成项的时间戳才进行生成

culculator : add.c calc.c mult.c sub.c numbers.h

gcc -g -o calculator add.c calc.c mult.c sub.c

这个简单的规则能运行, 但是每次全部编译所有文件太浪费了

优化如下:

SRCS = add.c calc.c mult.c sub.c

OBJS = $(SRCS:.c=.o)

PROG = calculator

CC = gcc

CFLAGS = -g

$(PROG): $(OBJS)

$(CC) $(FLAGS) -o $@ $^

$(OBJS): nubmer.h

clean:

rm -f $(OBJS) $(PROG)

install : $(PROG)

cp $(PROG) $(INSTALL_ROOT)/bin

说明:

1. $@是代表规则左边所提到的文件,$^是代表规则右边所提到的文件

2. clean规则没有信赖项,则没有时间戳可以检查

最终版本如下:

SRCS = add.c calc.c mult.c sub.c

HEADERS = nubmer.h

PROG = calculator

include framework.mk

#framework.mk中的内容:

OBJS = $(SRCS:.c=.o)

CC = gcc

INSTALL_ROOT = /usr/local

ifdef DEBUG

CFLAGS = -O -g

else

CFLAGS = -O

endif

$(PROG): $(OBJS)

$(CC) $(FLAGS) -o $@ $^

$(OBJS): $(HEADERS)

clean:

rm -f $(OBJS) $(PROG)

install : $(PROG)

cp $(PROG) $(INSTALL_ROOT)/bin

第三章

程序的运行时结构

2013年11月19日21:45:17

尽是一些基础的概念,这里略去

第四章

文件类型与编译工具

2013年11月19日22:02:51

诸如Make和Ant等的构造工具,则负责在较高层次对构造过程进行居中协调,如决定需要对哪些文件进行编译,使用哪些编译工具等。

GCC工具链:

1. C预算理器 C Preprocessor, 用户扩展宏定义

2. C编译器 C compiler 用户把源代码编译成汇编语言

3. 汇编器 assembler 把汇编语言转换成目标文件

4. 连接器 linker 用于把不同的目标文件连接成单个可执行程序

gcc -E main.c //只进行宏替换

gcc -S main.c //生成汇编语言代码

gcc -c main.c //编译成目标文件

gcc -o hello main.c //生成可执行程序

ar -rs mymath.a sort.o sine.o cosin.o tan.o //打包成静态程序库也称为归档文件

gcc -o prog main.o mymath.a

unix中nm 与 objdump 与 hexdump 命令可以用来查看一定的目标文件的连接信息,具体略

gcc -c -fPIC sqit.c //创建位置无关代码 position-independent code

gcc -shared -o libmymath.so sort.o sine.o cosin.o tan.o //打包成动态程序库

gcc -c main.c

gcc -o prog main.o -L. -lmymath //连接动态连接库

export LD_LIBRARY_PATH=. //增加当前目标到动态连接库的搜索路径

ldd prog

c在编译时执行类型检查,而c++在连接时执行类型检查

java、c#等语言的编译工具略

扫盲:

GCC:GNV Compiler Collection

ELF: Excutable and Linking Format 目标文件使用可ELF结构来存储程序的各个组件

little endian:小字节序

big endian:大字节序
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐