学习从源代码编译(在Unix / Linux / OSX上)

当我从软件包(MacPorts / apt-get)安装软件的时候,我经常发现自己需要从源代码编译软件包。 ./configure && make && sudo make install通常就足够了,但是有时候它不起作用 – 如果不行的话,我经常会被卡住。 这几乎总是以某种方式与其他库依赖关系有关。

我想了解以下内容:

  • 如何找出传递给./configure参数?
  • 共享库如何在OS X / Linux下运行 – 它们位于文件系统中的位置, ./configure && make如何find它们,实际上在链接时发生了什么
  • 共享库和静态链接库之间的实际区别是什么? 为什么我不能静态链接所有东西(RAM和磁盘空间这些天很便宜),从而避免奇怪的库版本冲突?
  • 我怎么知道我安装了哪些库,以及哪些版本?
  • 如何在不破坏我的正常系统的情况下安装多个版本的库?
  • 如果我从源代码安装东西,然后通过软件包进行pipe理,那么最干净的方法是什么?
  • 假设我设法从源头上编译了一些东西,那我怎么把它打包起来,这样其他人就不用再跳过这些东西了? 特别是在OS X ….
  • 我需要掌握哪些命令行工具才能熟练使用这些东西? 东西像otool,pkg-config等

我愿意在这里投入相当多的时间和精力 – 我不一定要直接回答上述问题,我更愿意得到关于书籍/教程/常见问题的build议,我可以阅读哪些会给我我需要了解实际情况,从而找出问题所在。

我很抱歉直接回答一切,但我不知道任何有用的教程,常见问题等,基本上是8年的桌面应用程序(我帮助分发),挫折和谷歌search:

如何找出传递给./configure的参数?

实践真的。 Autotools很简单,因为它是一致的。 但是有很多东西用cmake或者自定义的构build脚本。 一般来说,你不需要传递任何东西来configuration,它应该弄清楚你的系统是否可以构buildfoo-tool。

configuration和GNU工具都在/,/ usr和/ usr / local中查找依赖关系。 如果你在其他地方安装了任何东西(如果依赖项是由MacPorts或者Fink安装的话,这会让你感到痛苦),你必须通过一个标志来configuration或者修改shell的环境,以便GNU工具find这些依赖关系。

共享库如何在OS X / Linux下运行 – 它们位于文件系统中的位置,./configure && make如何find它们,实际上在链接时发生了什么

在Linux上,它们需要安装到dynamic链接程序可以find的path,这是由LD_LIBRARY_PATH环境variables和/etc/ld.conf的内容定义的。 在Mac上,大多数开源软件几乎都是一样的(除非是Xcode项目)。 除了envvariables是DYLD_LIBRARY_PATH

有一个链接器search库的默认path。 它是/ lib:/ usr / lib:/ usr / local / lib

你可以通过使用CPATHvariables,或CFLAGS或其他任何环境variables(复杂的方法)来补充它。 我build议像这样的CFLAGS:

导出CFLAGS =“$ CFLAGS -L / new / path”

-L参数添加到链接path。

现代的东西使用pkg-config工具。 现代的东西你安装也安装一个.pc文件,描述图书馆,它在哪里,以及如何链接到它。 这可以使生活更轻松。 但是OS X 10.5并没有提供,所以你也必须安装它。 也有很多基本的deps不支持它。

链接的行为只是“在运行时parsing这个函数”,实际上它是一个大的string表。

共享库和静态链接库之间的实际区别是什么? 为什么我不能静态链接所有东西(RAM和磁盘空间这些天很便宜),从而避免奇怪的库版本冲突?

当你链接到一个静态库文件时,代码将成为你的应用程序的一部分。 这将是,如果有一个巨大的.c文件的库,并将其编译到您的应用程序。

dynamic库具有相同的代码,但是当应用程序运行时,代码会在运行时加载到应用程序中(简化说明)。

你可以静态链接到任何东西,但是,可悲的是几乎没有任何构build系统使这个容易。 您必须手动编辑生成系统文件(例如,Makefile.am或CMakeLists.txt)。 但是,如果您经常安装需要不同版本的库的东西,并且您正在寻找并行安装依赖关系,这可能是值得学习的。

诀窍是将连接线从-lfoo更改为-l / path / to / static / foo.a

你大概可以find并replace。 之后检查工具不使用ldd foo或otool -L foo链接到.so或dylib

另一个问题不是所有的库都编译为静态库。 很多人做。 但是MacPorts或Debian可能决定不发货。

我怎么知道我安装了哪些库,以及哪些版本?

如果你有这些库的pkg-config文件,很简单:

pkg-config –list-all

否则,你往往不能轻松。 dylib可能有一个soname(即foo.0.1.dylib,soname是0.1),与库的版本相同。 但是这不是必需的。 soname是一个二进制可计算性的function,如果你改变库中函数的格式,你必须碰撞soname的主要部分。 所以你可以得到例如。 版本14.0.5 soname 2.0库。 虽然这不常见。

我对这类事情感到沮丧,并在Mac上为此开发了一个解决scheme,接下来我正在讨论这个问题。

如何在不破坏我的正常系统的情况下安装多个版本的库?

我的解决scheme在这里: http : //github.com/mxcl/homebrew/

我喜欢从源代码安装,并想要一个简单易用的工具,但需要一些软件包pipe理。 所以我build立了自制软件,例如。 wget我自己的来源,但一定要安装一个特殊的前缀:

/usr/local/Cellar/wget/1.1.4

然后我使用自制软件工具将所有这些符号链接到/ usr / local,所以我仍然有/ usr / local / bin / wget和/usr/local/lib/libwget.dylib

后来,如果我需要一个不同版本的wget,我可以并行安装它,只需更改链接到/ usr / local树的版本即可。

如果我从源代码安装东西,然后通过软件包进行pipe理,那么最干净的方法是什么?

我相信Homebrew的方式是最干净的,所以使用它或做同样的事情。 安装到/ usr / local / pkgs /名称/版本和符号链接或硬链接其余的。

请使用/ usr / local。 存在的每个构build工具都会在其中search依赖项和头文件。 你的生活会容易得多

假设我设法从源头上编译了一些东西,那我怎么把它打包起来,这样其他人就不用再跳过这些东西了? 特别是在OS X ….

如果没有依赖关系,你可以build立目录,把它交给其他可以做“安装”的人。 但是,只能在OS X完全相同的版本上可靠地执行此操作。在Linux上,它可能适用于具有相同内核版本和libc次要版本的类似Linux(例如Ubuntu)。

在Unix上分发二进制文件不容易的原因是由于二进制兼容性。 GNU人员和其他人经常改变他们的二进制界面。

基本上不分发二进制文件。 事情可能会以非常奇怪的方式打破。

在Mac上,最好的select是制作macports软件包。 每个人都使用macports。 在Linux上有这么多不同的构build系统和组合,我不认为有什么更好的build议,而不是写一个关于如何在y奇怪的configuration中成功构buildx工具的博客条目。

如果你做了一个包描述(对于macports或homebrew),那么任何人都可以安装这个包,它也解决了依赖性问题。 然而,这通常并不容易,而且在主macports树中包含macports配方也并不容易。 此外macports不支持异国情调的安装types,他们提供了一个select所有包。

Homebrew的未来目标之一就是点击一个网站上的链接(例如,homebrew:// blah),它会下载这个Ruby脚本,安装这个软件包的代码,然后构build应用程序。但是,还没有完成,但考虑到我select的devise不太棘手。

我需要掌握哪些命令行工具才能熟练使用这些东西? 东西像otool,pkg-config等

otool实际上只在事后才有用。 它告诉你什么是build立的二进制链接。 当你搞清楚你必须build立一个工具的依赖关系时,这是没用的。 pkg-config也是如此,因为在使用之前,您已经安装了依赖关系。

我的工具链是读取README和INSTALL文件,并执行configure –help。 观察构build输出来检查它是否理智。 parsing任何构build错误。 也许在将来,问服务器故障:)

这是一个很大的话题,所以我们从Linux上的共享库(Linux上的ELF和OS X上的Mach-O)开始,Ulrich Drepper 对编写DSO (dynamic共享对象)有一个很好的介绍,它涵盖了Linux上共享库的一些历史logging这里包括为什么他们是重要的

Ulrich还介绍了为什么静态链接被认为是有害的,这里的安全更新的关键之一。 缓冲区溢出在一个公共库(如zlib),这是广泛链接静态可能会导致分配巨大的开销 – 这发生在zlib 1.1.3( 红帽咨询 )

ELF

链接器ld.so手册页

 man ld.so 

解释了运行时dynamic链接中涉及的基本path和文件。 在现代的Linux系统上,您会看到通过/etc/ld.so.conf.d/添加的其他path,通常通过/etc/ld.so.conf中的glob include添加。

如果你想通过你的ld.soconfigurationdynamic查看可用的dynamic,你可以运行

 ldconfig -v -N -X 

阅读DSO如何应该给你一个良好的基础知识水平,然后继续了解这些原则如何适用于OS X的Mach-O。

Mach-O的

在OS X上,二进制格式是Mach-O。 链接器的本地系统文档是

 man dyld 

Mach格式文档可从Apple获得

UNIX构build工具

通常的configuremakemake install过程通常由GNU autotools提供,它有一本在线书籍 ,其中涵盖了一些configure / build分割和GNU工具链的历史。 Autoconf使用testing来确定目标构build系统上的function可用性,它使用M4macros语言来驱动它。 Automake基本上是一个Makefiles的模板方法,通常被称为Makefile.am的模板输出一个Makefile.in,输出的autoconf(configuration脚本)转换成一个Makefile。

GNU hello程序是理解GNU工具链的一个很好的例子,手册中包含了autotools文档。

西蒙! 我知道你的感受; 我也在努力学习Linux的这一部分。 根据我自己的经验,我写了一篇关于您所提到的一些项目的教程(主要是作为我自己的参考!): http : //easyaspy.blogspot.com/2008/12/buildinginstalling-application-from.html 。 我想你会感激我的关于如何简单的Python应用程序来build立/安装的说明。 🙂

希望这有助于! 并开心编译。

Tim Jones


在Ubuntu Linux中从源代码构build/安装应用程序

尽pipeUbuntu存储库充满了很多优秀的应用程序,但是在某个时候,您一定会遇到不在存储库(或者没有Debian软件包)的“必备”工具,或者您需要比版本库中更新的版本。 你是做什么? 那么,你必须从源代码构build应用程序! 别担心,这听起来并不复杂。 这里有一些提示,根据我从一个等级业余的经验! (当我在这个例子中使用Ubuntu时,一般的概念应该适用于大多数Unix / Linux发行版,比如Fedora,甚至Windows上的Cygwin平台。

从源代码构build(编译)大多数应用程序的基本过程遵循以下顺序:configure – > compile – > install。 执行这些操作的典型Unix / Linux命令是: config – > make – > make install 。 在某些情况下,您甚至可以find显示所有这些可以合并为一个命令的网页:

 $ config && make && make install 

当然,这个命令假定在这些步骤中没有任何问题。 这是有趣的地方!

入门

如果你之前还没有在你的系统上编译过源代码的应用程序,那么你可能需要用一些通用的开发工具来设置它,例如gcc编译器套件,一些常见的头文件(把它看作是已经存在的代码由您正在安装的程序使用的其他人编写)和make工具。 幸运的是,在Ubuntu中,有一个叫做build-essential的metapackage将会安装这个。 要安装它(或只是确保你已经拥有了它),在terminal运行这个命令:

 $ sudo apt-get install build-essential 

现在您已经具备了基本设置,下载应用程序源文件并将其保存到您具有读/写权限的目录(例如“主目录”)。 通常情况下,这些文件将位于文件扩展名为.tar.gz.tar.bz2的归档文件中。 .tar仅仅意味着它是一个“磁带存档”,它是一组保存其相对目录结构的文件。 .gz代表gzip(GNU zip),这是一种stream行的Unix / Linux压缩格式。 类似地, .bz2代表bzip2,这是一种比gzip提供更高压缩(更小的压缩文件大小)的更新的压缩格式。

下载源文件后,打开一个terminal窗口(从Ubuntu菜单的系统terminal),并切换到您保存文件的目录。 (在这个例子中我将使用~/download ,这里“〜”是你的“home”目录的一个快捷方式)。使用tar命令从下载的归档文件中提取文件:

如果您的文件是gzip压缩文件(例如,以.tar.gz结尾),请使用以下命令:

  $ tar -zxvf filename.tar.gz 

如果你的文件是一个bzip2档案文件(例如,以.tar.bz2结尾),使用命令:

  $ tar -jxvf filename.tar.gz 

提示:如果你不想记住所有的命令行开关来提取档案,我build议获得一个(或两个)这些实用程序:dtrx(我最喜欢!)或装饰(更受欢迎)。 使用这些工具中的任何一个,只需input实用程序(dtrx或deco)的名称和文件名,就可以完成剩下的工作。 这两个“知道”如何处理大多数你可能会遇到的档案格式,他们有很好的error handling。

从源代码构build时,您可能遇到两种常见的错误types:

  1. 运行configuration脚本(通常命名为config或configure)以创build特定于您的设置的生成文件时,会发生configuration错误。
  2. 编译器错误发生在运行make命令时(在生成makefile之后),编译器无法find它需要的代码。

我们将看看这些,并讨论如何解决它们。

configuration和configuration错误

解压缩源代码归档文件后,在terminal中,应该切换到包含解压缩文件的目录。 通常情况下,这个目录名称将与文件的名称相同(不带.tar.gz.tar.bz2扩展名)。 但是,有时目录名称只是应用程序的名称,没有任何版本信息。

在源代码目录中查找一个README文件和/或一个INSTALL文件(或者名称相似的东西)。 这些文件通常包含有关如何构build/编译应用程序并进行安装的有用信息,包括有关依赖关系的信息。 “依赖关系”只是成功编译所需的其他组件或库的一个奇特名称。

阅读README和/或INSTALL文件(并希望查看应用程序的任何相关联机文档)后,查找名为configconfigure的可执行文件(在文件上设置“x”权限)文件。 有时文件可能有一个扩展名,例如.sh (例如, config.sh )。 这通常是一个运行其他实用程序的shell脚本,以确认你有一个“理性”的编译环境。 换句话说,它将检查以确保你已经安装了你需要的一切。

提示:如果这是一个基于Python的应用程序,而不是configuration文件,则应该find一个名为setup.py的文件。 Python应用程序通常安装起来非常简单。 以root用户身份安装这个应用程序(例如,把sudo放在Ubuntu下面的命令前面),运行这个命令:

  $ python setup.py install 

这应该是你需要做的一切。 您可以跳过本教程的其余部分,直接使用和享受您的应用程序。

在terminal中运行configuration脚本。 通常,您可以(也应该)使用常规用户帐户运行您的configuration脚本。

 $ ./config 

该脚本将显示一些消息,让你知道它在做什么。 通常,脚本会告诉您是成功还是失败,如果失败,还会提供一些关于失败原因的信息。 如果你没有得到任何错误信息,那么你通常可以认为一切正常。

如果您没有find任何看起来像configuration脚本的脚本,那么通常意味着该应用程序非常简单,并且与平台无关。 这意味着你可以直接跳到下面的构build/编译步骤,因为提供的Makefile应该可以在任何系统上工作。

一个例子

在本教程中,我将使用名为Newsbeuter的基于文本的RSS阅读器作为构build应用程序时可能遇到的错误types的示例。 对于Newsbeuter,configuration脚本的名字是config.sh 。 在我的系统上,当我运行config.sh ,出现以下错误:

 tester@sitlabcpu22:~/download/newsbeuter-1.3$ ./config.sh Checking for package sqlite3... not found You need package sqlite3 in order to compile this program. Please make sure it is installed. 

经过一番研究,我发现,事实上, sqlite3应用程序已经安装。 但是,因为我试图从源代码构build,这是一个提示,什么config.sh实际上是寻找sqlite3的开发库(头)。 在Ubuntu中,大多数软件包都有一个关联的开发对象包,以-dev结尾。 (其他平台,比如Fedora,经常使用包的后缀-devel作为开发包。)

为了find适合sqlite3开发包的软件包,我们可以使用Ubuntu中的apt-cache工具(以及类似的Fedora中的yum工具):

 tester@sitlabcpu22:~/download/newsbeuter-1.3$ sudo apt-cache search sqlite 

这个命令返回了一个很大的结果列表,所以我们必须做一些侦察工作来确定哪个是合适的包。 在这种情况下,适当的包就是libsqlite3-dev 。 请注意,有时我们正在寻找的软件包将具有lib前缀,而不仅仅是相同的软件包名称加上-dev 。 这是因为有时候我们只是在寻找一个可以被许多不同的应用程序使用的共享库。 要安装libsqlite3-dev ,请在terminal中运行典型的apt-get install命令:

 tester@sitlabcpu22:~/download/newsbeuter-1.3$ sudo apt-get install libsqlite3-dev 

现在,我们必须再次运行config.sh以确保我们已经解决了这个依赖关系问题,并且我们没有任何依赖关系问题。 (虽然我不会在这里展示它,但在Newsbeuter的情况下,我也必须安装libcurl4-openssl-dev包)。另外,如果你安装了开发包(如libsqlite3-dev )和关联应用程序包(例如, sqlite3 )尚未安装,大多数系统将自动同时安装关联的应用程序包。

当configuration成功运行时,结果将是它将创build一个或多个make文件。 这些文件通常被命名为Makefile (请记住,在Unix / Linux中,文件名大小写是重要的!)。 如果构build包包含子目录(如src等),那么这些子目录中的每一个都将包含一个Makefile

构build和编译错误

现在,我们准备实际编译应用程序。 这通常被称为build筑,这个名字是从现实世界的build设过程中借用的。 通常是多个源代码文件的应用程序的各个“部分”被组合在一起以形成整个应用程序。 make实用程序pipe理构build过程并调用其他应用程序(如编译器和链接器)来实际执行该工作。 在大多数情况下,只需从运行configuration的目录运行make(使用常规用户帐户)即可。 (在less数情况下,例如编译使用Qt库编写的应用程序,您将需要运行另一个“包装”应用程序,例如qmake,同样,请再次查阅README和/或INSTALL文档以获取详细信息。

与上面的configuration脚本一样,当您在terminal中运行make(或类似的实用程序)时,它将显示一些关于正在执行的内容以及任何警告和错误的消息。 您通常可以忽略警告,因为它们主要针对应用程序的开发人员,并告诉他们存在一些正在违反的标准做法。 通常,这些警告不会影响应用程序function。 另一方面,编译器错误必须处理。 有了Newsbeuter,当我运行make时,事情进行了一段时间,但后来我得到一个错误:

 tester@sitlabcpu22:~/download/newsbeuter-1.3$ make ... c++ -ggdb -I/sw/include -I./include -I./stfl -I./filter -I. -I./xmlrss -Wall -Wextra -DLOCALEDIR=\"/usr/local/share/locale\" -o src/configparser.o -c src/configparser.cpp c++ -ggdb -I/sw/include -I./include -I./stfl -I./filter -I. -I./xmlrss -Wall -Wextra -DLOCALEDIR=\"/usr/local/share/locale\" -o src/colormanager.o -c src/colormanager.cpp In file included from ./include/pb_view.h:5, from src/colormanager.cpp:4: ./include/stflpp.h:5:18: error: stfl.h: No such file or directory In file included from ./include/pb_view.h:5, from src/colormanager.cpp:4: ./include/stflpp.h:33: error: ISO C++ forbids declaration of \u2018stfl_form\u2019 with no type ./include/stflpp.h:33: error: expected \u2018;\u2019 before \u2018*\u2019 token ./include/stflpp.h:34: error: ISO C++ forbids declaration of \u2018stfl_ipool\u2019 with no type ./include/stflpp.h:34: error: expected \u2018;\u2019 before \u2018*\u2019 token make: *** [src/colormanager.o] Error 1 

只要遇到第一个错误,make过程就会停止。 处理编译器错误有时可能是棘手的业务。 你必须查看有关这个问题的一些线索的错误。 通常情况下,问题是一些头文件,通常具有扩展名.h.hpp ,缺失。 在上面的错误的情况下,它是(或应该是)清楚问题是stfl.h头文件不能被find。 如本例所示,您需要查看错误消息的第一行,并找出问题的根本原因。

在查看Newsbeuter文档(在开始之前我应该​​完成的,但是这个教程的这个部分不会很有意义!)之后,我发现它需要一个名为STFL的第三方库。 那么在这种情况下我们做什么? 那么,我们基本上重复这个完全相同的过程为所需的库:获取库并执行configure-build-install过程,然后,恢复构build所需的应用程序。 例如,在STFL的情况下,我必须安装libncursesw5-dev包才能正确构build。 (通常,在安装另一个需要的应用程序之后,没有必要在我们的原始应用程序上重新进行configuration步骤,但是它也不会伤害到它)。

成功安装STFL工具包后,Newsbeuter的make过程成功运行。 make过程通常会在离开的地方(在错误的地方)出现。 因此,任何已经编译成功的文件都不会被重新编译。 如果你想重新编译所有东西,你可以运行make clean all来移除任何编译的对象,然后再次运行make。

安装

构build过程成功完成后,即可安装该应用程序。 在大多数情况下,要将应用程序安装到文件系统的公共区域(例如, /usr/bin/usr/share/bin等),您将需要以root身份运行安装。 安装实际上是整个过程中最简单的一步。 要安装,在terminal运行:

 $ make install 

检查此进程的输出是否有错误。 如果一切顺利,您应该能够在terminal中运行命令名称并启动。 (追加到命令行的末尾,如果是GUI应用程序,或者直到应用程序运行完毕才能使用terminal会话。)

从源代码构build应用程序时,通常不会在Ubuntu中的GUI菜单中添加图标或快捷方式。 您将需要手动添加。

而这基本上就是在Ubuntu中构build和安装应用程序的过程,虽然可能是迭代的。 这样做了几次之后,它会成为你的第二天性!

那么./configure –help会给你很多的信息,用于GNU autotools生成的configuration文件。 其中大部分归结为 – – / – 不启用function(这些可能需要一个额外的参数,如“共享”,以说明在哪里可以find库)。

其他重要的是–prefix(默认是/ usr / local /大部分时间)说要安装到哪里(如果你正在构build你通常想要的包–prefix = / usr或者–prefix = /select/ YourPackage)。

在Linux上,/ lib,/ usr / lib和/ usr / local / lib通常在我的gcc中search,并包含在ldconfig的默认configuration中。 除非你有充分的理由,否则这是你想要图书馆的地方。 但是/etc/ld.so.conf可能会列出额外的条目。

通过试图运行“gcc -l”并查看是否有错误来configuration和查找它们。 您可以将“-L”添加到您的CFLAGS参数,以添加额外的path进行search。

您可以安装多个版本,并且链接到较旧版本的软件将与其保持链接(运行ldd以查找Linux上的绑定),但是新的编译通常针对系统上最新版本的dynamic库。

大多数软件都采用dynamic库,尤其是在使用libtool的情况下,所以您可能会发现不平凡的应用程序无法正确构build。

ls -l是find安装库的最佳select。

这就是我没有信息的地方。 如何与软件包打好:不知道。 如果可能的话,我尝试把东西包装起来,以避免这个问题。

“如何找出传递给./configure的参数?

通常:./configure –help会告诉你你想要什么。

“我怎么知道我安装了哪些库,以及哪些版本?

这取决于系统。 一种方法是只做一个find /|grep libname|less因为通常库文件的文件名是版本号。

“如何在不破坏我的正常系统的情况下安装多个版本的库?”

再次依赖于系统和库。 sudo make altinstall会为您创build一个版本名称。 图书馆文件通常自己虽然。 请记住, 由于版本经常创build符号链接到“规范化”名称,这可能会破坏事情。

“如果我是从一个系统上安装源代码的软件,那么最简单的方法是什么?

使用./configure中的–prefix参数并将它们放在/opt是一个很好的做法。

免责声明:我绝不是专家,但是我已经从cmd行 (slackware,CentOS,redhat,ubuntu,misc others和OS X)使用linux超过5年。

为了回答一下你的问题,我发现一个很好的方法来看看你已经安装了什么库和版本(这是在Linux Debian,所以也应该与其他版本一起工作)。

 dpkg --list 

你应该得到一个这样的输出很长的列表

 ii libssl0.9.8 0.9.8c-4etch5 SSL shared libraries ii libssp0 4.1.1-21 GCC stack smashing protection library ii libstdc++5 3.3.6-15 The GNU Standard C++ Library v3 ii libstdc++5-3.3 3.3.6-15 The GNU Standard C++ Library v3 (development ii libstdc++6 4.1.1-21 The GNU Standard C++ Library v3 

西蒙,

1.)./configure –help提供了大量的信息。 我build议检查一下。 它通常有适当的时候编译静态/dynamic链接库的选项。

2.)Libaries生活在dynamic链接器path中。 这通常在/etc/ld.so.conf中设置。 链接器search适当的库,就像find第一个匹配的PATH环境variables。

3.)这通常会导致问题,因为在库版本更改时必须重新编译所有内容。 如果你做一些search,你可能会发现为什么静态链接是一个坏主意的原因。 我没有这么长时间没有这样做,我不能在这里详细说明。

4.)这有点困难。 您需要检查自己的库path,以便绝对确定。库通常具有到安装的版本的符号链接。

例如libssh2.so.1 – > libssh2.so.1.0.0

通常人们通过滚动自己的debian软件包或使用其他技术来pipe理他们安装的库和程序。 我使用stow( http://www.gnu.org/software/stow/ )pipe理已安装的软件,这非常简单,并使用符号链接安装库。 我发现它更容易,因为我不必构build/安装/testingdeb / rpm包。

5.)库的多个版本可以正常安装在库目录中。 链接到可执行文件的库将保持链接到它们链接的版本。 在可执行文件上运行ldd会告诉您可执行文件链接到的库。

6.)就像我之前提到的,滚动你自己的debian包或者使用stow可能是最干净的解决scheme。

7.)我不能说Mac OSX,但对于Linux发行版的包装系统是最好的方法。

8.)可能很多挫折将通过使用ldd和找出什么版本被链接到什么版本或与可执行文件链接的库无法find解决。 pkg-config会帮助你很多,但是只能用于使用它的软件。 这不是默认autotools构build系统的一部分,虽然这些日子很stream行。

Static libraries are not a good idea–if you need to upgrade the library (to fix a security problem, for example), you'll need to recompile everything with a dependency on that library.

I don't like the idea of "make install" potentially messing with my system, but as others have said, it's usually a whole lot less pain to install things in /usr/local instead of using –prefix to install somewhere else. So, I've chowned /usr/local to my regular (non-privileged) user. That way "make install" is pretty much guaranteed to not mess with important system files. (This obviously won't work on multi-user systems. It's great for virtual servers, though.)

Although it wasn't explicitly in your list of questions, you mention in your preface:

./configure && make && sudo make install is usually enough, but sometimes it doesn't work – and when it doesn't, I frequently get stuck.

When I get stuck on on Debian or Ubuntu I will use auto-apt which will automagically install the packages that contain the files that configure can't find.

看到:

Another tool you might find handy is CheckInstall, it adds applications installed with make install to your list of installed packages: https://help.ubuntu.com/community/CheckInstall

For OS X:

  • How do I figure out what arguments to pass to ./configure?

./configure –help

  • What are the actual differences between a shared and a statically linked library? Why can't I just statically link everything (RAM and disk space are cheap these days) and hence avoid weird library version conflicts?

Using shared libraries allows you to upgrade the library without recompiling everything that makes use of it.

  • How shared libraries work under OS X / Linux – where they live on the filesystem, how ./configure && make finds them, what actually happens when they are linked against

System libraries live in /usr/lib.

Libraries you compile yourself live in /usr/local/lib (/usr/local being the default –prefix flag for ./configure).

Environment variables DYLD_FALLBACK_LIBRARY_PATH and LD_LIBRARY_PATH let you specify which folders to look in, so /usr/local/lib should be there at the start of the list.

  • How can I install more than one version of a library without breaking my normal system?

Install everything to /usr/local – with the environment variables above, the version in /usr/local/lib takes precedence over the version in /usr/lib in your environment.

  • If I am installing stuff from source on a system that is otherwise managed using packages, what's the cleanest way of doing so?

Install to /usr/local. In Ubuntu, I try and use checkinstall first, to create a deb package.

  • Assuming I manage to compile something fiddly from source, how can I then package that up so other people don't have to jump through the same hoops? Particularly on OS X….

Document the compilation steps in a blog post, I'd say.