ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 打包 分发自由软件的标准形式是源代码。无论软件是否以源代码的形式(例如解释性语言Perl、Python和PHP等等)运行,还是必须首先编译(例如C、C++和Java等),这一点是毋庸置疑的。通过编译好的软件,大多数用户可能无需自己编译源代码,而只需安装预先编译的二进制包(见本章后面的[the section called “二进制包”](# "二进制包"))。然而,这些二进制包依然来自主源代码分发包。原因是源代码包明确定义了发布版本。当项目分发“Scanley 2.5.0”时,真正的含义是“源代码文件的目录树,当编译(如果需要)和安装后将产生Scanley 2.5.0”。 对于源代码发布的式样有一个相对严格的标准。可能会有与标准的偏差出现,但是那只是例外,不是规则。除非有强有力的理由,否则你的项目也应该遵守这个标准。 ### 格式 源代码必须以标准格式传输目录树。对于Unix和类Unix的操作系统,习惯上是TAR格式,压缩为**compress**、 **gzip**、**bzip**或**bzip2**。对于微软Windows,分发目录树的标准方法是*zip*格式,也是压缩格式,所以不必再进一步压缩归档文件。 **TAR文件** *TAR*代表了“Tape ARchive”,因为tar格式用线性数据流表示了目录树,所以非常适于将目录保存到磁带。这个特性也使之成为已单个文件分发目录树的标准。生成压缩的tar文件(*tarballs*)也非常简单。在某些系统上,**tar**命令可以自己产生压缩归档;在另外一些系统上,则需要使用单独的压缩程序。 ### 命名和布局 打包的名称必须包含软件名称和发布版本号,然后是特定归档类型的格式后缀名。例如Scanley 2.5.0在Unix上使用GNU Zip(gzip)压缩的包类似: scanley-2.5.0.tar.gz 或者是在Windows上使用zip压缩: scanley-2.5.0.zip 所有的这些归档解压后,都应该能在当前目录创建一个名为`scanley-2.5.0`的单独目录。这个新目录中,所有的源代码应该是处于准备好进行编译(如果需要编译)的布局。在新目录树的最上层,应该有一个`README`文件,解释了软件是什么,发布版本是哪个,并给出了其他资源的指针,例如项目站点以及其他有用的文件等。`README`旁边也应该有一个`INSTALL`,说明在所有支持的操作系统上构建和安装软件的方法。就像[Chapter 2, *起步*](# "Chapter 2. 起步")的[the section called “如何为你的软件应用许可证”](# "如何为你的软件应用许可证")所说明的,应该有`COPYING`或`LICENSE`,说明软件分发的条款。 也应当有一个`CHANGES`文件(有时称为`NEWS`),解释了发布版本的新功能。`CHANGES`文件按照逆向的历史顺序,汇集了所有发布版本的变更列表,所以最新的发布位于文件最顶部。完成这个列表通常是稳定发布分支的最后一项工作;一些项目会随着开发列出所有的片段,而另外一些项目更倾向于在最后阶段,让某人根据版本控制日志组合信息一次完成。这个列表类似下面: ~~~ Version 2.5.0 (20 December 2004, from /branches/2.5.x) http://svn.scanley.org/repos/svn/tags/2.5.0/ New features, enhancements: * Added regular expression queries (issue #53) * Added support for UTF-8 and UTF-16 documents * Documentation translated into Polish, Russian, Malagasy * ... Bugfixes: * fixed reindexing bug (issue #945) * fixed some query bugs (issues #815, #1007, #1008) * ... ~~~ 根据具体情况,这个列表可能会很长,但是不需要包含所有的小bug修正和特性提升。它的目的仅仅是给用户一个印象,通过升级到最新版本将会获得哪些好处。实际上,习惯上会将变更列表包含在声明邮件(见本章后面的[the section called “测试和发布”](# "测试和发布"))中,所以在编写时要考虑你的读者。 **CHANGES还是ChangeLog** 传统上,名为*ChangeLog*的文件会列出项目的每个变更—也就是提交到版本控制系统的每个修订版本。ChangeLog文件有许多种格式;具体的格式并不重要,但都需要包含相同的信息:变更的日期、作者和简介(或仅仅是该变更的日志信息)。 `CHANGES`文件有所不同。尽管它也是变更的列表,但是仅应该包含对特定读者比较重要的变更,而且准确日期和作者之类的元数据也可以省略。为了避免混淆,不要使用可替换的术语。一些项目使用“NEWS”而不是“CHANGES”,尽管避免了与“ChangeLog”混淆的可能,但却有些用词不当,因为文件CHANGES保留了所有发布版本的变更信息,所以在最顶部的新闻之后是许多旧闻。 文件ChangeLog可能会渐渐消失。当CVS是版本控制系统的唯一选择时使用这个文件非常重要,因为变更数据很难从CVS中获取。然而,在许多现在的版本控制系统中,ChangeLog中保存的信息可以在任意时间从版本控制版本库中获取,所以再使用一个静态文件保存这些信息变得毫无意义—实际上,不仅仅是毫无意义,因为ChangeLog仅仅是重复版本库已经保存的日志信息。 目录树中源代码的布局与项目版本控制系统检出的源代码的布局应当相同,或者尽可能的近似。通常情况下,会有些区别,例如因为发布包会包含一些用于配置和编译(见本章后面的[the section called “编译和安装”](# "编译和安装"))的生成文件,或者因为它包含了非本项目维护的,而用户一般不会拥有的第三方软件,。但是,即使发布的目录树与版本控制系统中的开发目录树完全一致,发布包本身也不应当是一个工作拷贝(见[*工作拷贝(working copy)*](#))。发布版本代表了一个静态参考点—源文件特定的,不可改变的配置。如果它是工作拷贝,就会存在用户不小心作出更新的风险,而用户还会以为使用的是发布版本,尽管实际上已经有所不同。 请牢记无论打包方式如何,这个发布包应该是一样的。这个发布版本—精确的引用了某人所说的“Scanley 2.5.0”—是zip文件或tarball解压缩所创建的目录树。所以项目可以提供所有这些下载: scanley-2.5.0.tar.bz2 scanley-2.5.0.tar.gz scanley-2.5.0.zip ...但是通过解压他们创建的源代码树必须相同。源代码树是分发物;具体的形式只是为了方便使用。源代码包也可以有些许的差异:例如,在Windows包中,文本文件必须以CRLF作为行结束符(回车和换行),而Unix包应该使用LF。不同操作系统下如果因为编译的原因需要有不同的布局,源包的布局也可以有所不同。然而,这些都是些无关紧要的变形。同一发布版本不同包的基本源代码文件必须相同。 ### 大写还是不大写 当通过名称引用一个项目时,人们通常会以正常的名词进行大写,如果是缩略词则也要大写:”MySQL5.0“,”Scanley2.5.0“等等。是否在包名上大写也取决于项目。例如,`Scanley-2.5.0.tar.gz`或`scanley-2.5.0.tar.gz`都可以(我个人倾向于后者,因为我不喜欢让人去按shift键,不过很多项目使用有大写的包)。重要的是解压tarball得到的目录使用相同的大小写。不应该有什么意外:用户总是预计解压得到的目录会和压缩包使用相同的名称。 ### 预发布 当发送预发布或候选发布时,合格者成为发布号码的一部分,所以在包的名称中要包含这个名字。例如,在之前[the section called “版本号组成部分”](# "版本号组成部分")提到的alpha和beta系列的发布包名称为: scanley-2.3.0-alpha1.tar.gz scanley-2.3.0-alpha2.tar.gz scanley-2.3.0-beta1.tar.gz scanley-2.3.0-beta2.tar.gz scanley-2.3.0-beta3.tar.gz scanley-2.3.0.tar.gz 第一个解压后进入目录`scanley-2.3.0-alpha1`,第二个是`scanley-2.3.0-alpha2`,以此类推。 ### 编译和安装 对于需要从源代码编译的安装的软件,有许多经验丰富的用户希望能够遵循的标准步骤。例如,以C、C++或特定其他编译语言编写的程序,在类Unix系统下的标准是输入: ~~~ $ ./configure $ make # make install ~~~ 第一个命令自动检测构建过程中需要的环境,第二个命令在原地构建软件(但不安装),最后一个命令是在系统上安装。前两个命令作为普通用户执行,而第三个以root用户。设置系统的详细信息可以看Vaughan、Elliston、Tromey和Taylor编写的优秀图书*GNU Autoconf, Automake, and Libtool*。它作为New Riders的treeware发布,内容也可以在网上[http://sources.redhat.com/autobook/](http://sources.redhat.com/autobook/)免费得到。 这不是唯一的标准,只是传播最广泛的一个。Ant([http://ant.apache.org/](http://ant.apache.org/))构建系统也渐渐流行,特别是Java编写的项目,它拥有自己的构建和安装的标准步骤。另外,特定的编程语言,例如Perl和Python都有大多数使用这些语言所推荐的相同方法(例如Perl模块使用命令**perl Makefile.pl**)。如果不是清楚适应于项目的标准,可以询问资深的开发者;你可以安全的假定*某些*标准更加合适,即使一开始并不清楚是什么。 无论你的项目适合哪个标准,则如非必要一定不能与之偏离。标准安装过程对于许多系统管理员已经成为条件反射。如果在你的项目`INSTALL`文件中看到了熟悉的实施步骤,他们就会认识到你的项目遵守了一般的习惯,也就会轻松的完成其他的事情。另外,就像在[Chapter 2, *起步*](# "Chapter 2. 起步")的[the section called “下载”](# "下载")中讨论的,拥有标准的构建程序可以让潜在的开发者满意。 在Windows中,构建和安装的标准比较薄弱。对于需要编译的项目,通常要提供一个适用于标准微软开发环境(Developer Studio、Visual Studio、VS.NET和MSVC++等等)工作空间/项目模型的目录树。取决于项目的本性,可以通过Cygwin([http://www.cygwin.com/](http://www.cygwin.com/))环境提供类Unix的构建选项。当然,如果你使用的语言或编程框架使用自己的构建和安装习惯—例如Perl或Python—你应当使用该框架标准的方法,无论是Windows、Unix、Mac OS X或任何其他操作系统。 要乐于花费额外的精力让项目遵守相关的构建或安装标准。构建和安装是切入点:如果一定需要,在这之后可以更加困难,但是如果用户或开发者一开始就需要使用意想不到的步骤与软件进行交互则是一种耻辱。 ### 二进制包 尽管正式发布是源代码包,大多数用户会从二进制包安装,可以通过他们操作系统的软件分发机制得到,也可以从项目站点或第三方手工获取。这里“二进制”并不一定是“已编译”;它仅仅意味着一种预配置形式的包,允许用户在自己的电脑上无需执行一般的基于源代码的构建和安装程序,便可以进行安装。在RedHat GNU/Linux上,这是RPM系统;在Debian GNU/Linux上,则是(`.deb`)系统;在MS Windows,通常是`.MSI`文件或自安装的`.exe`文件。 无论这些二进制包是由项目相关的人组装,还是由关系较远的第三方组装,用户都会*认为*其等同于项目的官方发布版本,会根据二进制包的行为在项目bug跟踪系统上发起问题。因此,项目能否为打包者提供明确的指导方针就非常有意义,应该与他们更紧密的合作,认识到他们是否能够清楚和准确的产生软件。 打包者需要知道的主要问题是是否应当一直根据官方源代码版本发布他们的二进制包。有时,打包者会喜欢获取版本库较晚版本的代码,或者选择在发布后包含某个变更,从而为用户提供特定的bug修正或其他改进。打包者认为通过最新的代码,他是在为用户谋利益,但实际上这样会导致许多混乱。项目已经准备好了接受某个发布版本以及trunk和分支上(那些故意运行最前沿代码的人发现的)的bug报告。当一个bug来自这些源,回应者通常可以能确认bug在该快照出现,而且已经被修正,用户可以升级或等待下个发布。如果是一个还未知的bug,拥有精确的发布版本时,重现就会比较简单,在跟踪系统中也比较容易分类。 项目没有准备好根据未指明媒介或混血的版本接受bug报告。此类bug很难重现;另外,因为无法预期与来自发布之后开发的孤立变更进行交互的结果,所以产生的不正常也不应该成为对开发者进行谴责理由。我曾经非常沮丧的浪费了许多时间,因为某个bug似乎*消失了*,而实际上应该出现:某人运行的是轻微补丁的版本,基于(但不相同)官方发布版本,当预期的bug没有出现时,每个人都会尝试寻找原因。 在有一些情况下,打包者也确实需要在原发布基础上做出一些修改。要鼓励打包者向项目开发者提出这个问题,并描述他们的方案。他们可能得到许可,即使失败,也至少会让项目知道他们的目的,项目也可以关注一些不寻常的bug报告。开发者可以在项目站点上设置一个免责声明,并告知所有的打包者在合适的地方放置同样的东西,这样该二进制包的用户就可以知道他们获取的东西与项目官方发布并不完全相同。这种情形并没有任何敌意,但不幸的是经常会有这种结果。打包者与项目开发者有些不太一样的目标。打包者主要希望为用户提供最佳的开箱即用体验。开发者也希望如此,但他们也需要确保自己知道别人所用软件的版本,这样可以获取到一致的bug报告,并作出兼容性的保证。有时这些目标会有冲突。当发生这种情况时,需要牢记项目无法控制打包者,两种方式都承担了各自的义务。诚然项目通过产生软件为打包者提供了服务。但是打包者也是在为项目服务,通过提供这种单调的工作让软件更广泛的传播。当然可以不认可打包者,但是不要迁怒于他们;只需要尽自己的可能将工作做好。