从源头安装系统
从源头安装入门指南
类别:Linux
导言
本文件适用于希望直接从原始作者安装软件的开源操作系统用户,而不仅仅是依赖其操作系统提供的软件(和版本)。它是为那些不熟悉以源代码形式下载软件概念的人编写的,提供有关相关命令和一般过程的背景资料。
讨论的概念
- 开发和分发:独立的软件开发人员、多操作系统支持、版本(档案)、版本控制
- 发行版:二进制包和包经理
- 下载:http、ftp、小部件、校验和和签名
- 存档文件:tar、zip、gzip
- 常见文件:README和INSTALL;必需依赖项
- 用sed/awk/patch补丁进行补丁
- 构建和安装:配置、制作、制作、perl和python
- 构建和安装文档
- 编译器设置和剥离;处理错误
- 安装后
开发和分配
一个典型的操作系统由数百个不同的应用程序组成。在专有操作系统中,该操作系统的生产者/销售商通常拥有和管理所有软件的开发。然而,开源系统通常是通过获取和集成许多独立团体——甚至单个独立开发人员发明和维护的应用程序来创建的。此外,开源软件项目通常用于各种不同的操作系统——例如基于Linux、基于BSD、Hurd,有时甚至集成到Solaris、Mac甚至Windows等专有操作系统中(如果许可证允许)。
分发维护人员和最终用户有时会将原始软件开发人员称为上游源或简单的上游源。同样,开发人员通常将使用代码的发行版或最终用户称为下游。
大多数开源项目将其源代码存储在可以通过互联网访问的版本控制系统中(仅供匿名用户阅读)。对于此类项目,可以下载最新的“进行中”文件,或下载带有一些发布ID(版本号)的“标记”文件集。然而,这样做通常效率不高;项目通常通过创建包含所有相关文件的存档文件并可供下载来定期发布。对于没有公共版本控制系统的项目,此类定期发布的存档文件是直接获取源代码的唯一方法。
分发、二进制包和从源编译
有许多操作系统发行版负责查找、下载和调整所有最常用的软件包。几个也编译了它,并提供了二进制形式的结果。有很多好处,包括更快的安装,一个查找相关软件的位置,特别是提供相关的安全补丁:分发维护人员关注安全更新,并使最终用户易于注意到和安装它们。
然而,此类发行版通常不包括最新版本的软件;如果您需要比发行版提供的版本更新的版本,那么可能需要自己构建它。软件在安装时通常也非常可定制,特别是能够省略不需要的功能。由于分发需要让广大用户满意,他们倾向于在分发的编译应用程序中包含每个功能;作为最终用户,您或许可以通过自己编译应用程序来更好地调整应用程序。
分发通常包括一个软件包管理器,该管理器保存安装了哪些软件的数据库。在软件包管理器的“背后”更改机器上的软件不是一个好主意;以后可能会发生各种奇怪的行为。如果您的分发有软件包管理器,请阅读此文档以获取背景信息——但请参阅分发的文档,以了解如何在不混淆软件包管理器的情况下安装软件。这通常涉及编写描述软件的软件包规范,然后使用本地软件包管理器编译和安装软件。这适用于所有具有软件包经理的发行版,无论应用程序是以二进制(预编译)还是源代码形式分发。
下载和安全性
下载存档文件的通常方法是使用网页浏览器并单击“下载”按钮,单击链接,或右键单击链接并选择“另存为”。这将使用“http”协议下载文件。相反,一些网站通过旧的“ftp”协议提供文件。许多网页浏览器也支持这一点(单击链接也可以在这里工作)。或者,还有ftp客户端应用程序。
当已知正确的URL时,“wget”或“curl”命令行应用程序也可以在类似unix的操作系统下通过http或ftp获取文件。
发布经常下载的软件的网站通常设置“镜像”网站(有用的人在世界各地保存文件副本)。原始网站通常有可用镜子的列表,您应该选择一个离您很近的镜子。这有助于降低原始发布者的网络带宽成本,通常还允许您更快地下载。
“http”和“ftp”网络协议都可以被犯罪分子或其他不良方拦截,然后他们可以在下载时修改数据。数据也可能在进行中意外损坏(尽管这并不常见)。使用镜像站点时,可能有人修改了那里的文件(即镜像上的文件与原始发布者的文件不同)。因此,验证您下载的内容是否是原始出版商的意图是一个好主意。
许多网站为每个存档文件提供一个md5sum文件,该文件包含文件内容的校验和;有时单个md5sums文件包含许多其他文件的校验和。您应该始终从原始站点获取md5sums文件,而不是镜像。如果可能,您应该通过安全的https协议下载它。然后可以使用unix md5sum
命令行工具计算大存档文件的校验和,并将其与预期值进行比较,以确保内容正常。
要计算单个文件的总和:
md5sum file-to-check
并“手动”根据预期值验证此应用程序的输出。如果值在网页中,您可以在该页面上打开“查找”对话框,并复制粘贴md5sum程序输出的值。只有当值相同时,“查找”才会匹配。
如果软件提供商提供了一个md5sums文件,该文件包含(文件名、校验和)对列表,那么您可以运行:
md5sum -c md5sums-file
它将在您的本地系统中查看md5sums文件中列出的每个文件,计算其校验和,如果它不是预期值,则报告错误。
一些软件提供商签署存档文件,而不是(或)提供md5校验和。在这种情况下,您应该:
- 从他们的网站上下载提供商的公钥(尽可能使用https)
- 下载存档文件的“签名文件”;这将是一个小文件,其基名与下载的文件相同,后缀为“.sig”或“.asc”
- 执行以下步骤
# needed only once for each key, ie each "publisher"
gpg --import {public-key}
gpg --verify {signature-file-name}
验证步骤解密签名文件,显示校验和;然后,它在真实文件上运行校验和算法,并检查它们是否相同。显然,“gpg”应用程序需要在本地安装。
归档文件
归档是一个包含许多其他文件的单个文件。创建此类文件有几种不同的工具,但在所有情况下,该过程都是有效地将所有单个文件附加在一起,然后添加一个包含原始文件的偏移量、长度、名称和其他属性的“索引”,以便再次提取它们。
注:英语中的“存档”一词可能意味着“旧”、不再使用或“备份”副本。虽然存档文件可用于存储备份或很少使用的数据,但它们也便于在网络上传递数据。
“tar”应用程序将多个文件打包到单个“tar格式”存档文件中,这是开源中最常用的格式。Tar最初的意思是“磁带存档”,但格式在磁盘上也很好用。Tar档案不仅记住文件的原始名称,还记住其原始Unix“所有者ID”和文件权限。ownerid很少有用(除非tar归档是在它正在解压的同一台机器上创建的),但文件权限是有用的。按照惯例,tar格式文件通常以“.tar”结尾。包含源代码的tar格式文件有时被称为“tarballs”。
焦油应用程序不会压缩文件内容。然而,源代码文件确实压缩得很好,网络带宽总是太慢太贵,所以焦油文件通常在创建后使用通用压缩应用程序进行压缩。最常用的压缩类型是“gzip”,生成的文件通常后缀为“.tar.gz”或“.tgz”。使用bzip2压缩也很常见,此类文件通常后缀为“.tar.bz2”。偶尔会使用“xz”压缩;文件通常后缀为“.tar.xz”。
焦油应用程序的原始版本是很久以前创建的,并已多次重新实施。可悲的是,这意味着可用的命令行选项因您使用的应用程序版本而异。该功能也因版本而异;特别是一些版本可以在使用压缩时自动检测,并自动解压缩,而另一些版本则需要传递正确的命令行参数来处理压缩文件,还有一些版本要求首先解压缩文件。以下是从tar存档中提取文件的一些示例命令:
# Modern GNU tar options. This works for files compressed
# with gzip and bzip too
tar --extract --file filename
# Same as above
tar -xf filename
# Same as above. Leading "-" is optional
tar xf filename
# explicitly decompress gzip2-compressed file then
# pass uncompressed result directly into tar
gzip -cd filename.tgz | tar xf -
# same as above, but for bzip2-compressed files
bunzip2 -cd filename.tar.bz2 | tar xf -
请注意,如果省略“f”,焦油似乎就会挂起(等待用户输入)。
警告:解压焦油文件可以覆盖本地文件。默认情况下,文件被解压缩到当前目录的子目录中,只要当前目录合适,子目录就应该安全。然而,不要相信使用以下选项的任何说明;它们可能试图诱骗您修改重要的本地文件:
-C or --directory
-P or --absolute-names
--transform or --xform
大多数tar文件的创建是为了在当前目录中打开它们创建一个子目录,所有其他文件都放置到该目录中;例如解包名为“foo-1.2.tar.gz”的文件将创建一个名为“foo-1.2”的子目录,其中包含该目录中的文件。可悲的是,并非所有打包源代码供下载的人都遵循这一惯例;有时tarfile将其内容直接扩展到当前目录中——如果该目录中已经有文件,可能会造成大混乱。因此,最好在解压之前使用以下命令检查tarfile的内容:
# Modern GNU tar
tar --list --file filename
# Same as above
tar -tf filename
# Same as above. Leading "-" is optional
tar tf filename
gzip -cd filename | tar tf -
bunzip -cd filename | tar tf -
档案文件偶尔会以“zip格式”分发。Zip-archives在DOS和Windows世界中或与Java有关中最为常见,但偶尔会在其他地方遇到。Zip格式的工作原理类似于tar和gzip的组合(它使用与gzip相同的压缩,但也有自己的内部“索引”)。Zipfiles不保留原始unix所有者或文件权限。可以使用unzip
命令提取此类文件的内容(假设它是本地安装的)。
在可能的情况下,以普通用户身份登录时,而不是“根”用户登录时,应解压归档文件。这是防止任何意外文件覆盖的额外安全措施。然而,只有当解压存档的用户是根用户时,tar文件中记录的文件所有者设置才会保留。如果这些很重要(这并不常见),那么档案必须“作为根”解封。
常用文件
未打包的源代码存档通常在顶级目录中包含名为README或INSTALL(或两者兼而有之)的文件。您应始终首先阅读这些文档,因为它们提供了有关如何编译、安装和配置下载存档中其余源代码的重要信息。
README或INSTALL中通常可以找到的一个重要信息是必须首先安装的其他软件的列表。您下载的任何程序都需要一些本地标头文件、库文件和/或帮助工具来构建或运行。如果您没有正确获得先决条件,那么应用程序可能无法编译,或可能编译但不运行,或者可能在没有您想要的某些可选功能的情况下构建。
另一个重要信息是可以传递给构建过程的参数集;稍后见。
补丁
有时,已知下载的软件在您的环境中不起作用,并且有人已经想出如何调整它来解决问题。解决问题的人可以sed
或awk
命令、包含多个sed/awk命令的shell脚本或补丁文件的形式发布他们的“调整”。显然,您需要对此类更改保持谨慎,只有在您信任源或能够再次检查更改时才应用它们。
sed
工具对文本文件中的每一行应用正则表达式,并将匹配的文本替换为其他内容。这是一个相当有限的工具,但易于使用和广泛使用。
awk
做类似的事情,但能够对文本文件进行更复杂的转换。
使用“差异”工具创建补丁文件,以比较同一文件的两个版本并输出差异。patch
工具可以获取“差异”的输出,并将其应用于其中一个文件,以将其“转换为”到另一个版本。Patchfiles(即差异的输出)的好处是,它非常易于阅读(很容易看到将做出哪些更改)。
构建系统:配置、制造、制作等
创建您刚刚下载的软件的软件开发人员显然需要某种方法来在自己的机器上编译和安装该软件。无论他们使用的工具需要什么配置文件,几乎总是包含在存档文件中。由于开源开发人员希望尽可能多的人使用他们的软件,他们也做出了一些努力,以便在一系列不同的系统上轻松构建和安装软件。然而,他们无法支持世界上所有可能的配置。
最后,安装过程的重点是将原始源代码转换为本地计算机可以执行的形式,然后将所有必要的文件放入$PATH
变量中列出的目录中,供所有用户使用(以便他们可以执行这些文件)。为解释语言安装模块略有不同;这些文件安装在解释器(例如python或perl)可以找到它们的地方,而不是直接在$PATH中。
配置和制作
用于管理源代码编译和安装的最广泛传播的工具是make
。Make是一个应用程序,它使用包含规则列表的配置文件(称为makefile
),其中大多数形式:
- 当TARGET-FILE比SOURCE-FILE旧时,SOME-ACTION
目标文件是最终产品,或某个中间阶段。源文件是手写的源代码或一些中间工件。该操作通常是调用重新创建目标文件的编译器、链接器或类似程序。本文档太短了,无法详细介绍非常复杂和强大的make
命令;幸运的是,编译软件通常不需要理解makefiles——除非出错。附录A中对makefile语法和行为的简要说明。
不幸的是,尽管makefile语法非常强大,但它仍然不足以处理计算机配置的所有可能方式,以及安装软件的人可能希望编译应用程序的所有可能方式。因此,许多软件包都附带一个名为“配置”的shell脚本和一个名为“Makefile.in”的模板makefile。配置脚本在命令行上获取配置选项列表,并将模板makefile转换为为本地计算机和安装程序的愿望定制的真实makefile。因此,安装顺序通常如下:
# unpack and read documentation
tar xf filename
cd {directory created by above step}
less README
less INSTALL
# generate customised makefile
./configure {some options ...}
# compile everything in the local directory
make
# update global directories
sudo make install
顺便说一句:“配置”脚本由名为autotools的软件自动生成,但这对使用它的人来说无关紧要。
配置通常调用为“./configure”,以避免两个可能的问题:
- 一些用户的
$PATH
变量中没有“.”。特别是,出于安全原因,根用户没有这个 - 一些用户没有“.”作为
$PATH
中的第一个条目,这意味着错误的配置脚本可能会被运行
一般来说,最好作为普通系统用户执行除“安装”以外的所有步骤,而不是root。这避免了错误和一些攻击(尽管安装步骤是作为根完成的,保护程度不高)。然而,将软件安装到全局/bin
或/usr
目录通常需要管理特权(除非您使用“基于用户的软件包管理器”或类似的罕见设置)。
一些项目提供了一个makefile,但没有“配置”脚本;在这种情况下,可以省略上面的“配置”步骤。要么应用程序足够简单,不需要它,要么软件开发人员在手写的makefile中构建了更多的逻辑。
并非所有系统都启用了“sudo”。在这种情况下,请改为使用以下内容:
su # must then enter root password
make install
exit
对于大多数软件,配置和make命令可以在与源代码相同的目录中运行,如上所示。结果是,编译期间生成的新文件与原始文件混合在一起,这有点混乱,但“清理”命令可用于稍后整理。然而,对于某些软件,有必要创建一个临时目录,将当前工作目录更改为该目录,然后在那里执行构建步骤;项目文档应指示是否有必要。有些人认为总是从临时目录构建更好。使用原始源代码旁边的单独目录构建的示例,这是一个常见的约定:
# unpack into a directory {packagename}
tar xf filename
# create separate build directory
mkdir {packagename}-build
# compile everything in the separate build directory
cd {packagename}-build
../{packagename}/configure {some options}
make
# update global directories
sudo make install
其他构建工具
一些项目使用cmake
作为构建工具。cmake
的工作有点像configure
(见上文);它生成一个makefile,其内容取决于传递给cmake命令的选项和本地系统的功能。构建基于cmake的软件包所需的步骤与上面的“配置/制作”示例相同,只是配置步骤被以下部分取代:
cmake . -DCMAKE_BUILD_TYPE=Release {some options ...}
像往常一样,查看项目的文档,了解有关如何构建的说明。
一些项目使用基于python或perl而不是make
的构建工具。这些原则仍然相当相似。
不需要编译的软件通常有一个相当简单和快速的安装过程。特别是,只需将文件复制到相关位置,就可以安装用Perl或Python解释语言编写的应用程序。然而,这些项目在档案文件中包含执行此任务的程序或脚本,而不是要求安装程序手动执行。
环境变量
配置应用程序编译和安装的选项通常作为命令行参数传递给“配置”脚本或make程序。然而,有时配置选项会通过environment variables
传递。这些可以通过将定义放在命令的开头来指定,例如
NAME=tom ENABLE_FOO=no ./configure
在运行命令之前,也可以定义环境变量:
export NAME=tom
export ENABLE_FOO=no
./configure
档案的README或INSTALL文件或项目网站上通常会描述哪些选项可用。有时可以通过运行./configure --help
查看可用的选项。
构建和安装文档
一些项目提供的文档可以“安装”,以便通过普通系统文档查看器(如“man”或“info”)访问。有些以HTML形式提供文档,通常安装在/usr/share/doc
下。有时此文档包含在“标准”存档文件中,有时是单独的(可选)下载。有时文档是作为标准make install
命令的一部分安装的,有时如果您希望安装它,则必须使用单独的命令。有时文档以“即用”形式交付,但有时以一种“原始形式”交付,在安装前必须处理——就像需要编译源代码一样。
现在应该清楚的是,提供文件的各种方法如此广泛,在这里无法提供真正有用的建议。有关指导,请参阅下载档案中的README和INSTALL文件以及项目网站。
其他构建目标
除了编译所有内容(“make”)和安装之前编译的程序(“make install”)或文档的命令外,还有其他一些常见的可能性。
make clean
通常删除所有生成的文件(像文件从存档中解包后那样离开目录)。
调用编译器
如上所述,“make”或“cmake”执行的最常见的步骤是调用编译器。本地系统必须安装适当的编译器。
这也是最有可能失败的步骤(与链接一起)。
如果编译步骤失败,出现无法找到头文件或找不到库文件的错误消息,那么您可能还没有安装所有先决条件——重新阅读README和INSTALL文件。在某些情况下,缺失的先决条件是可选的,在这种情况下,将有一个参数可以传递用于配置,或者一个环境变量可以设置为允许在没有该先决条件的情况下安装软件。仔细检查您指定的参数,如果它们看起来正确,那么项目文档是解决这些问题的最佳资源。
编译器有一系列可能提高性能的选项。然而,只有当你有丰富的经验时,你才应该搞砸这些。如果您需要此文档,只需将编译器选项保留在默认值!
编译和链接的输出(您实际想要的“可执行文件”)通常包含大量数据,这些数据对调试程序有用,但对“正常最终用户”没有用。可以通过在可执行文件上运行strip {filename}
从其中删除此信息。较小的程序将节省磁盘空间,加载速度也略快。除非您打算调试程序,否则使用strip
是一个好主意。
安装后配置
一些应用程序可以通过在应用程序启动时读取配置文件自定义其行为。应用程序通常会在/usr
或/etc
目录的某个地方安装配置文件的默认版本。检查make install
命令的输出,看看安装了哪些配置文件。配置选项也应记录在程序的README或INSTALL或他们的网站上。
附录A:Makefile示例
不幸的是,从源代码构建软件包时,编译错误发生并不罕见。有时可以通过检查makefile来诊断和解决问题(对makefile语法的基本理解可能会有帮助)。以下是基本语法和功能的非常简短的例子;有关更多详细信息,请参阅make
文档或在线提供的众多教程之一。
用于构建名为“prog”的可执行文件的示例makefile具有一个“c”源文件、一个头文件并使用一个库(它也从单个“c”源文件构建)可能如下所示:
prog: prog.c prog.h libmylib.a
gcc -o prog prog.c -L. -lmylib
libmylib.a: libmylib.o
ar -rcs libmylib.a libmylib.o
libmylib.o: libmylib.c libmylib.h
gcc -c -o libmylib.o libmylib.c
条目(规则)的形式是:
target: dependency1 [dependency-n ...]
<tab> command to execute
...
对于每个“规则”,如果目标缺失或超过任何依赖项(基于文件时间戳),则运行命令以(重新)创建目标。然而,首先测试每个依赖项,看看是否有规则将其作为目标。如果是这样,则递归评估该目标,即如果它缺失或超过其依赖项,则对其进行(重建)。
因此,在上述规则中,libmylib.c的更改将导致libmylib.o的重建。然后libmylib.a被再生,最后prog被重建。
Makefiles可能会变得非常复杂,许多文件是自动生成的,但上述原则始终适用。