125

每次从源代码编译某些东西时,都会经历相同的 3 个步骤:

$ ./configure
$ make
$ make install

我理解,将安装过程分成不同的步骤是有意义的,但我不明白,为什么这个星球上的每个编码人员都必须一遍又一遍地编写相同的三个命令才能完成一项工作。从我的角度来看,让./install.sh包含以下文本的源代码自动交付一个脚本是完全有意义的:

#!/bin/sh
./configure
make
make install

为什么人们会分别做这三个步骤?

4

4 回答 4

126

因为每一步做不同的事情

准备(设置)构建环境

./configure

这个脚本有很多你应该改变的选项。喜欢--prefix--with-dir=/foo。这意味着每个系统都有不同的配置。还./configure检查应该安装的缺少的库。这里的任何错误都会导致无法构建您的应用程序。这就是为什么发行版的软件包安装在不同的地方,因为每个发行版都认为将某些库和文件安装到某些目录会更好。据说运行./configure,但实际上你应该总是改变它。

例如,看看Arch Linux 软件包站点。在这里,您将看到任何包都使用不同的配置参数(假设它们使用构建系统的自动工具)。

构建系统

make

这实际上make all是默认的。每个品牌都有不同的行动要做。有些是在构建,有些是在构建后进行测试,有些是从外部 SCM 存储库中检出。通常你不必提供任何参数,但有些包再次以不同的方式执行它们。

安装到系统

make install

这会将软件包安装在 configure 指定的位置。如果您愿意,您可以指定./configure指向您的主目录。但是,许多配置选项都指向/usror /usr/local。这意味着你必须实际使用sudo make install,因为只有 root 可以将文件复制到 /usr 和 /usr/local。


现在您看到每个步骤都是下一步的先决条件。每一步都是为使事情顺利进行的准备工作。发行版使用这个比喻来构建包(如 RPM、deb 等)。

在这里你会看到每一步实际上都是不同的状态。这就是为什么包管理器有不同的包装器。下面是一个包装器示例,可让您一步构建整个包。但请记住,每个应用程序都有不同的包装器(实际上这些包装器的名称类似于 spec、PKGBUILD 等):

def setup:
... #use ./configure if autotools is used

def build:
... #use make if autotools is used

def install:
... #use make all if autotools is used

./configure这里可以使用自动工具,即makemake install。但另一个可以使用 SCons、Python 相关设置或其他不同的东西。

正如您所见,拆分每个状态使维护和部署变得更加容易,尤其是对于包维护者和发行版。

于 2012-06-09T13:44:13.207 回答
33

首先,应该是./configure && make && make install因为每个都取决于前者的成功。部分原因是进化,部分原因是开发工作流程的便利。

最初,大多数Makefiles 只包含编译程序的命令,而安装则留给用户。一个额外的规则允许make install将编译后的输出放在一个可能正确的地方;您可能仍然有很多充分的理由不想这样做,包括不是系统管理员,根本不想安装它。此外,如果我正在开发软件,我可能不想安装它。我想进行一些更改并测试我目录中的版本。如果我将有多个版本,这将变得更加突出。

./configure去检测环境中可用的和/或用户想要的,以确定如何构建软件。这不是需要经常更改的东西,而且通常需要一些时间。同样,如果我是一名开发人员,不值得花时间不断地重新配置。更重要的是,由于make使用时间戳来重建模块,如果我重新运行configure,标志可能会发生变化,现在我的构建中的一些组件将使用一组标志进行编译,而其他组件将使用一组不同的标志进行编译,这可能会导致不同的,不相容的行为。只要我不重新运行configure,我就知道我的编译环境保持不变,即使我更改了源代码。如果我重播configure,我应该make clean首先,删除任何已构建的源以确保统一构建事物。

三个命令连续运行的唯一情况是用户安装程序或构建软件包时(例如,Debian 的 debuild 或 RedHat 的 rpmbuild)。并且假设可以给包装一个 plain configure,这通常不是包装的情况,至少--prefix=/usr是需要的。make install包装商在做这个部分时喜欢处理假根。由于有很多例外,因此./configure && make && make install对于许多更频繁地这样做的人来说,制定规则会很不方便!

于 2012-06-09T13:47:09.643 回答
4

configure如果发现缺少依赖项,可能会失败。

make运行默认目标,即 Makefile 中列出的第一个目标。这个目标通常是all,但并非总是如此。所以只有make all install当你知道那是目标时,你才能做到。

所以 ...

#!/bin/sh

if ./configure $*; then
  if make; then
    make install
  fi
fi

或者:

./configure $* && ./make && ./make install

之所以包含,$*是因为通常必须提供configure.

但为什么不让人们自己做呢?这真的是一场大胜吗?

于 2012-06-09T13:37:58.073 回答
4

首先,./configure 并不总能找到它需要的所有东西,或者在其他情况下,它会找到它需要的所有东西,但不是它可以使用的所有东西。在这种情况下,您会想知道它(并且您的 ./install.sh 脚本无论如何都会失败!)从我的角度来看,具有意外后果的非失败的经典示例是编译大型应用程序,如 ffmpeg 或 mplayer。如果它们可用,它们将使用库,但如果它们不可用,它们仍然会编译,从而禁用某些选项。问题是您稍后会发现它是在不支持某种格式的情况下编译的,因此需要您返回并重做它。

./configure 以交互方式做的另一件事是让您可以选择自定义应用程序将在系统上安装的位置。不同的发行版/环境有不同的约定,您可能希望遵守系统上的约定。此外,您可能希望在本地安装它(仅供您自己使用)。传统上 ./configure 和 make 步骤不以 root 身份运行,而 make install(除非它是为您自己安装的)必须以 root 身份运行。

特定的发行版通常会提供以对发行版敏感的方式执行此 ./install.sh 功能的脚本 - 例如,源 RPMs + spec 文件 + rpmbuildslackbuilds

(脚注:话虽如此,我同意 ./configure; make; make install; 会变得非常乏味。)

于 2012-06-09T13:38:34.890 回答