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


47

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

我想学习以下内容:

  • 我如何确定要传递的参数./configure
  • 共享库如何在OS X / Linux下工作-它们在文件系统中的位置,如何./configure && make找到它们,链接到它们时实际发生了什么
  • 共享库和静态链接库之间的实际区别是什么?为什么我不能仅静态链接所有内容(这些天RAM和磁盘空间很便宜),从而避免奇怪的库版本冲突?
  • 我如何知道我已经安装了哪些库以及什么版本?
  • 如何在不破坏正常系统的情况下安装一个库的多个版本?
  • 如果我正在从源代码,并使用包被管理的系统上安装的东西,什么是这样做的最彻底的方法?
  • 假设我设法从源头上轻松地编译了一些东西,那么我该如何打包它,以使其他人不必跳同样的圈呢?特别是在OS X上。
  • 我需要掌握哪些命令行工具才能熟练掌握这些知识?诸如otool,pkg-config等之类的东西

我愿意在这里投入大量时间和精力-我不一定要直接回答上述问题,我宁愿获得有关我可以阅读的书籍/教程/常见问题解答的建议,知识我需要了解实际发生的事情,因此自己解决问题。

Answers:


40

对于直接回答所有问题,我深表歉意,但我不知道任何有用的教程,常见问题解答等。基本上,接下来的八年是制作桌面应用程序(我帮助分发),沮丧和谷歌搜索:

1.如何确定要传递给./configure的参数?

真的练习 自动工具很容易,因为它是一致的。但是,使用cmake或自定义构建脚本还有很多东西。通常,您不必传递任何配置信息,它应该确定您的系统是否可以构建foo-tool。

configure和GNU工具都在/,/ usr和/ usr / local中查找依赖项。如果您在其他任何地方安装任何东西(如果依赖项是由MacPorts或Fink安装的,这会使您感到痛苦),则必须传递一个标志来配置或修改Shell的环境,以帮助GNU工具查找这些依赖项。

2.共享库如何在OS X / Linux下工作-它们在文件系统中的位置,。/ configure && make如何找到它们,链接它们时实际发生了什么

在Linux上,需要将它们安装到动态链接程序可以找到的路径,该路径由LD_LIBRARY_PATH环境变量和/etc/ld.conf的内容定义。在Mac上,大多数开源软件几乎总是一样(除非它是Xcode项目)。除了env变量是DYLD_LIBRARY_PATH

链接器有一个默认路径来搜索库。它是/ lib:/ usr / lib:/ usr / local / lib

您可以通过使用CPATH变量,CFLAGS或其他任何数量的其他环境变量来真正补充(非常复杂)。我建议CFLAGS像这样:

export CFLAGS =“ $ CFLAGS -L / new / path”

-L参数添加到链接路径。

现代的东西使用pkg-config工具。您所安装的现代工具还安装了一个.pc文件,该文件描述了库,库的位置以及如何链接到库。这可以使生活更轻松。但是它不是OS X 10.5附带的,因此您也必须安装它。同样,许多基本部门也不支持。

链接只是“在运行时解析此函数”,实际上这是一个很大的字符串表。

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

当您链接到静态库文件时,代码将成为您的应用程序的一部分。就像该库只有一个巨大的.c文件,然后将其编译到应用程序中一样。

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

您可以静态链接到所有内容,但是,遗憾的是,几乎没有任何构建系统可以使此操作变得容易。您必须手动编辑构建系统文件(例如Makefile.am或CMakeLists.txt)。但是,如果您定期安装需要不同版本的库的东西并且发现并行安装依赖项很困难,那么这可能值得学习。

技巧是将链接线从-lfoo更改为-l / path / to / static / foo.a

您可能可以找到并替换。然后使用ldd foo或otool -L foo检查工具是否未链接到.so或dylib

另一个问题是并非所有库都可以编译为静态库。很多。但是后来MacPorts或Debian可能决定不发货。

4.如何知道我已经安装了哪些库以及什么版本?

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

pkg-config-列出所有

否则,您通常不容易。dylib可能具有与库的版本相同的名称(即foo.0.1.dylib,名称为0.1)。但是,这不是必需的。soname是二进制可计算性功能,如果您更改库中函数的格式,则必须更改soname的主要部分。这样就可以得到例如。适用于2.0库的版本14.0.5 soname。虽然这并不常见。

我对这种事情感到沮丧,并在Mac上为此开发了一个解决方案,接下来我将讨论它。

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

我对此的解决方案在这里:http : //github.com/mxcl/homebrew/

我喜欢从源代码进行安装,并且想要一个易于使用但带有某些软件包管理的工具。因此,使用Homebrew进行构建。wget from source,但请确保安装到特殊前缀:

/ usr / local /地窖/wget/1.1.4

然后,我使用自制程序工具将所有链接符号链接到/ usr / local,因此我仍然拥有/ usr / local / bin / wget和/usr/local/lib/libwget.dylib

稍后,如果我需要其他版本的wget,则可以并行安装它,只需更改链接到/ usr / local树的版本即可。

6.如果我要从源代码上安装东西,否则将使用软件包进行管理,那么最干净的方法是什么?

我相信自制方法是最干净的,所以请使用它或进行等效操作。安装到/ usr / local / pkgs / name / version并进行符号链接或硬链接。

请使用/ usr / local。现有的每个构建工具都会在其中搜索依赖项和标头。您的生活会轻松得多

7.假设我设法从源头上轻松地编译了一些东西,那么我又该如何打包,以使其他人不必跳同样的圈呢?特别是在OS X上。

如果没有依赖关系,则可以将构建目录放到tar目录中,然后交给其他人进行“ make install”安装。但是,您只能对完全相同的OS X版本可靠地执行此操作。在Linux上,它可能适用于具有相同内核版本和libc次要版本的相似Linux(例如Ubuntu)。

在Unix上分发二进制文件不容易的原因是二进制兼容性。GNU人员以及其他所有人经常更改其二进制接口。

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

在Mac上,最好的选择是制作一个Macports软件包。每个人都使用macport。在Linux上,有许多不同的构建系统和组合,我认为没有什么比写一篇博客文章介绍如何在y奇怪的配置中成功构建x工具更好的建议了。

如果制作软件包说明(用于macports或自制软件),那么任何人都可以安装该软件包,它也解决了依赖性问题。但是,这通常并不容易,而且要在主Macports树中包含Macports配方也不容易。另外,macports不支持特殊安装类型,它们为所有软件包提供了一种选择。

我对Homebrew的未来目标之一是可以单击网站上的链接(例如homebrew:// blah,它将下载该Ruby脚本,安装该软件包的deps,然后构建该应用。)尚未完成,但考虑到我选择的设计并不太棘手。

8.要掌握这些知识,我需要掌握哪些命令行工具?诸如otool,pkg-config等之类的东西

otool实际上仅在之后有用。它告诉您所构建的二进制链接到什么。当您确定必须构建的工具的依赖关系时,它是无用的。pkg-config也是如此,因为您将在使用依赖项之前就已经安装了它。

我的工具链是,阅读README和INSTALL文件,并执行configure --help。观看构建输出以检查其是否正常。解析所有构建错误。也许将来,请问serverfault :)


2
有趣的是,Homebrew看起来很像Portage(来自Gentoo Linux的软件包管理器)。听起来很不错。
David Z

12

这是一个巨大的话题,因此让我们从Linux上的共享库(Linux上的ELF和OS X上的Mach-O)开始,Ulrich Drepper很好地介绍了如何编写DSO(动态共享对象),其中介绍了Linux上可用的共享库的一些历史。这里包括他们为什么重要

Ulrich还描述了为什么将静态链接视为有害的安全更新是此处的关键点之一。静态链接广泛的公共库(例如zlib)中的缓冲区溢出可能会导致发行版的巨大开销-这种情况在zlib 1.1.3中发生(Red Hat咨询

精灵

链接器ld.so手册页

man ld.so 

介绍了运行时动态链接所涉及的基本路径和文件。在现代Linux系统上,您会看到通过/etc/ld.so.conf.d/添加的其他路径,通常是通过/etc/ld.so.conf中包含的glob添加的。

如果您想查看通过ld.so配置动态可用的内容,可以运行

ldconfig -v -N -X

阅读DSO Howto应该为您提供良好的基础知识,然后继续了解这些原理如何适用于OS X上的Mach-O。

马赫

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

man dyld

马赫格式的文档可从Apple

UNIX构建工具

共同的configuremakemake install过程一般是由GNU自动拥有一个提供在线图书,涵盖了一些配置的历史/建设分裂和GNU工具链。Autoconf使用测试来确定目标构建系统上的功能可用性,并使用M4宏语言来驱动该功能。Automake基本上是Makefile的模板方法,该模板通常称为Makefile.am,它输出一个Makefile.in,其中autoconf(配置脚本)的输出转换为Makefile。

GNU你好程序作为一个很好的例子为理解GNU工具链-和手动包括自动工具的文档。


10

西蒙!我知道你的感受; 我在学习Linux的这一部分上也很努力。根据我自己的经验,我编写了有关您要解决的某些项目的教程(主要是作为我自己的参考!):http : //easyaspy.blogspot.com/2008/12/buildinginstalling-application-from.html。我想您会赞赏我关于如何构建/安装简单Python应用程序的说明。:)

希望这会有所帮助!祝编译愉快。

蒂姆·琼斯


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

尽管Ubuntu存储库中充斥着许多出色的应用程序,但您一定会偶然发现该存储库中没有(或没有Debian软件包)的“必备”工具,或者您需要一个比版本库中的版本新。你是做什么?好吧,您必须从源代码构建应用程序!不用担心,它实际上并不像听起来那样复杂。根据我从成为业余爱好者的经验,这里有一些技巧!(尽管我在本示例中使用Ubuntu,但一般概念应适用于大多数Unix / Linux发行版,例如Fedora,甚至Windows上的Cygwin平台。)

从源代码构建(编译)大多数应用程序的基本过程按以下顺序进行:配置->编译->安装。执行这些操作的典型Unix / Linux命令为:config-> make-> make install。在某些情况下,您甚至会找到显示所有这些都可以组合为单个命令的网页:

$ config && make && make install

当然,该命令假定所有这些步骤都没有问题。这就是乐趣的源头!

入门

如果您以前从未从系统上的源代码中编译过一个应用程序,则可能需要使用一些通用的开发工具(例如gcc编译器套件),一些常见的头文件(将其视为已经编写的代码)进行设置。由正在安装的程序使用的其他人)和make工具。幸运的是,在Ubuntu中,有一个名为metapackage的安装包build-essential。要安装它(或只是确保已经有它!),请在终端中运行以下命令:

$ sudo apt-get install build-essential

现在您已经有了基本设置,下载应用程序源文件并将其保存到您具有读/写权限的目录中,例如“主”目录。通常,这些文件将位于文件扩展名为.tar.gz或的存档文件中.tar.bz2。这.tar只是意味着它是一个“磁带存档”,是保留其相对目录结构的一组文件。的.gz代表的gzip(GNU拉链),这是一个受欢迎的Unix / Linux的压缩格式。同样,.bz2bzip2的缩写,它是一种新的压缩格式,比gzip提供更高的压缩率(更小的压缩文件大小)。

下载源文件后,打开一个终端窗口(Ubuntu菜单中的System Terminal),然后转到保存文件的目录。(我将~/download在此示例中使用。这里,“〜”是您“主”目录的快捷方式。)使用tar命令从下载的存档文件中提取文件:

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

            $ tar -zxvf filename.tar.gz

如果您的文件是bzip2归档文件(例如,以结尾.tar.bz2),请使用以下命令:

            $ tar -jxvf filename.tar.gz

提示:如果您不想记住用于提取档案的所有命令行开关,建议您使用以下一个或两个实用程序:dtrx(我的最爱!)或deco(更受欢迎)。使用这些实用程序中的任何一个,您只需输入实用程序的名称(dtrx或deco)和文件名,其余的全部由它完成。这两个“知道”如何处理您可能会遇到的大多数存档格式,并且它们具有出色的错误处理能力。

从源构建时,可能会遇到两种常见的错误类型:

  1. 当您运行配置脚本(通常名为config或configure)以创建特定于您的安装程序的生成文件时,会发生配置错误。
  2. 当您运行make命令(在生成makefile之后)并且编译器无法找到所需的某些代码时,会发生编译器错误。

我们将研究每个问题,并讨论如何解决它们。

配置和配置错误

提取源代码存档文件后,在终端中,应切换到包含所提取文件的目录。通常,此目录名称将与文件名相同(不带.tar.gz.tar.bz2扩展名)。但是,有时目录名称只是应用程序的名称,而没有任何版本信息。

在源目录中查找README文件和/或INSTALL文件(或名称相似的文件)。这些文件通常包含有关如何构建/编译应用程序以及如何安装应用程序的有用信息,包括有关依赖项的信息。“依赖项”只是成功编译所需的其他组件或库的奇特名称。

阅读READMEand和/或INSTALL文件(并希望查看了该应用程序的任何相关在线文档)之后,请查找名为config或的可执行文件(在文件上设置了“ x”权限)configure。有时文件可能带有扩展名,例如.shconfig.sh)。这通常是一个运行其他实用程序的shell脚本,以确认您具有“健全”的编译环境。换句话说,它将检查以确保您已安装了所需的所有内容。

提示:如果这是基于Python的应用程序,而不是配置文件,则应找到名为的文件setup.py。Python应用程序通常非常易于安装。要以根用户身份安装此应用程序(例如,在Ubuntu下,将sudo放在以下命令的前面),请运行以下命令:

    $ python setup.py install

那应该是您需要做的所有事情。您可以跳过本教程的其余部分,直接继续使用和享受您的应用程序。

在终端中运行配置脚本。通常,您可以(并且应该!)使用常规用户帐户运行配置脚本。

$ ./config

该脚本将显示一些消息,以使您了解它在做什么。通常,脚本会提示您是成功还是失败,如果失败,还会提供一些有关失败原因的信息。如果没有收到任何错误消息,那么通常可以假设一切正常。

如果找不到任何看起来像配置脚本的脚本,则通常意味着该应用程序非常简单,并且与平台无关。这意味着您可以直接跳到下面的构建/编译步骤,因为提供的内容Makefile可以在任何系统上使用。

一个例子

在本教程中,我将使用名为Newsbeuter的基于文本的RSS阅读器作为构建应用程序时可能遇到的错误类型的示例。对于Newsbeuter,配置脚本的名称为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已经安装了该应用程序。但是,由于我正在尝试从源代码构建,因此这是一个提示,config.sh实际上是在寻找针对的开发库(标头)sqlite3。在Ubuntu中,大多数软件包都有一个以结尾的关联开发对应软件包-dev。(其他平台,例如Fedora,通常使用软件包后缀-devel作为开发包。)

要为sqlite3开发包找到合适的包,我们可以使用apt-cacheUbuntu中的实用程序(以及类似的yumFedora中的实用程序):

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

该命令返回了大量结果,因此我们必须做一些侦探工作才能确定哪个是合适的软件包。在这种情况下,适当的软件包为libsqlite3-dev。请注意,有时我们要查找的软件包将带有lib前缀,而不仅仅是相同的软件包名称plus -dev。这是因为有时我们只是在寻找可以被许多不同应用程序使用的共享库。要安装libsqlite3-dev,请在终端中运行典型的apt-get install命令:

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

现在,我们必须config.sh再次运行以确保我们已经解决了该依赖关系问题,并且没有其他依赖关系问题。(虽然在这里我不会显示,但对于Newsbeuter,我也必须安装该libcurl4-openssl-dev软件包。)此外,如果您安装了开发软件包(如libsqlite3-dev),而相关的应用程序软件包(如sqlite3)则没有已经安装的大多数系统将同时自动安装关联的应用程序包。

配置成功运行后,结果将是创建一个或多个make文件。这些文件通常被命名Makefile(请记住,文件名大小写在Unix / Linux中很重要!)。如果构建包包含子目录(例如src)等,则这些子目录中的每个子目录也将包含一个Makefile

编译和编译错误

现在,我们准备好实际编译应用程序了。通常将其称为“建筑”,而该名称是从现实中构建建筑的过程中借用的。应用程序的各个“部分”(通常是多个源代码文件)被组合在一起以形成整个应用程序。make实用程序管理构建过程,并调用其他应用程序(例如编译器和链接器)实际完成工作。在大多数情况下,您只需从运行配置的目录中运行make(使用普通用户帐户)。(在某些情况下,例如编译使用Qt库编写的应用程序,您将需要运行另一个“包装”应用程序,例如qmake。同样,请始终检查README和/或INSTALL文档以了解详细信息。)

与上面的配置脚本一样,当您在终端中运行make(或类似的实用程序)时,它将显示一些有关正在执行的消息以及所有警告和错误。通常,您可以忽略警告,因为它们主要针对应用程序开发人员,并且告诉他们某些标准行为被违反。通常,这些警告不会影响应用程序功能。另一方面,必须处理编译器错误。使用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找不到头文件。如本例所示,您想查看错误消息的第一行,然后逐步查找问题的根本原因。

看完Newsbeuter文档(我应该在开始之前就应该做的,但是本教程的这一部分并没有什么意义!),我发现它需要一个名为STFL的第三方库。那么在这种情况下我们该怎么办?好吧,我们实际上对所需的库重复了相同的过程:获取该库并为其执行configure-build-install过程,然后继续构建所需的应用程序。例如,对于STFL,我必须安装libncursesw5-dev软件包才能正确构建。(通常,在安装另一个必需的应用程序后,不必在原始应用程序上重做配置步骤,但也不会造成任何伤害。)

成功安装STFL工具包后,Newsbeuter的制作过程成功运行。生成过程通常会在中断的地方(错误发生时)进行处理。因此,任何已成功编译的文件都不会重新编译。如果要重新编译所有内容,可以运行make clean all删除所有已编译的对象,然后再次运行make。

正在安装

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

$ make install

检查此过程的输出是否有任何错误。如果一切成功,则应该能够在终端中运行命令名称,它将启动。(如果是GUI应用程序,则在命令行的末尾加上&,否则,直到该应用程序完成运行后,您才能使用终端会话。)

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

从本质上讲,这就是从Ubuntu中构建和安装应用程序的过程,尽管可能需要迭代。完成几次后,它将成为您的第二天性!


蒂姆,我很想阅读您的教程,但是您发布的链接无效。
gareth_bowles

6

好吧,./configure --help将为您提供大量信息,有关GNU自动工具生成的配置文件。大多数情况归结为--with /-不启用功能(这些功能可能需要一个额外的参数,例如“ shared”来表示在何处查找库)。

其他重要的选项是--prefix(大多数情况下默认为/ usr / local /),用于说明要安装的位置(如果要构建软件包,通常希望将其作为--prefix = / usr或--prefix = / opt /您的包裹)。

在Linux上,通常在我的gcc中搜索/ lib,/ usr / lib和/ usr / local / lib,并将它们包含在ldconfig的默认配置中。除非您有充分的理由,否则您将在这里找到您的库。但是,/etc/ld.so.conf可能会列出其他条目。

通过尝试运行“ gcc -l”并查看其是否错误来配置并找到它们。您可以在CFLAGS参数中添加“ -L”以添加额外的搜索路径。

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

大多数软件都假设动态库,尤其是使用libtool的情况下,因此,您可能会发现非平凡的应用不能正确静态地构建。

ls -l是找到已安装库的最佳选择。

那就是我信息不足的地方;如何与包装搭配使用:不知道。可能的话,我会尽量将它们包装成一个包装,以避免出现问题。


4

“如何确定要传递给./configure的参数?”

通常:./configure --help会告诉您您想要的内容。

“如何知道已安装的库和版本?”

这取决于系统。一种方法是只执行一个,find /|grep libname|less因为通常库文件的文件名中包含版本。

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

同样,取决于系统和库。sudo make altinstall将为您创建一个版本名称。库文件通常会自行版本化。但是请记住;由于版本通常会创建指向“规范化”名称的符号链接,因此可能会造成问题。

“如果我要从源代码上安装东西,否则将使用软件包来管理它,最干净的方法是什么?”

在./configure中使用--prefix参数并将其放在某个位置/opt是遵循的好习惯。

免责声明:我绝不是专家,但是我在cmd系列(slackware,CentOS,redhat,ubuntu,misc others和OS X)上使用Linux已有5年以上。


4

为了回答您的问题,前几天我找到了一个很好的方法来查看您已经安装了哪些库以及版本(这在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

4

西蒙

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

2.)库位于动态链接器路径中。通常在/etc/ld.so.conf中设置。链接器搜索合适的库,就像PATH环境变量与找到的第一个相匹配。

3)这通常会导致问题,因为当库的版本更改时,您必须重新编译所有内容。如果您进行一些搜索,您可能会发现很多原因导致静态链接是个坏主意。我已经很久没有做这件事了,我无法在这里详细说明。

4.)这有点困难。您需要检查库路径以确保完全确定。库通常具有指向已安装版本的符号链接。

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

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

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

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

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

8.)使用ldd并找出链接到哪个版本或找不到与可执行文件链接的库的方法,可能会解决很多问题。pkg-config将为您提供很多帮助,但仅限于使用它的软件。尽管最近流行,它也不是默认自动工具构建系统的一部分。


4

静态库不是一个好主意-如果您需要升级该库(例如,解决安全问题),则需要重新编译依赖该库的所有内容。

我不喜欢“ make install”的想法可能会弄乱我的系统,但是正如其他人所说,在/ usr / local中安装东西而不是使用--prefix在其他地方安装通常会减轻很多麻烦。因此,我将/ usr / local更改为我的常规(非特权)用户。这样就可以保证“ make install”不会与重要的系统文件混在一起。(这显然在多用户系统上不起作用。不过,这对于虚拟服务器非常有用。)


4

尽管问题列表中没有明确列出,但您在序言中提到:

./configure && make && sudo make install 通常就足够了,但有时它不起作用-否则,我经常卡住。

当我陷入Debian或Ubuntu的困境时,我将使用auto-apt来自动安装包含配置文件找不到的软件包。

看到:

您可能会发现方便的另一个工具是CheckInstall,它会将与之make install一起安装的应用程序添加到已安装软件包的列表中:https : //help.ubuntu.com/community/CheckInstall


3

对于OS X:

  • 如何确定要传递给./configure的参数?

./configure-帮助

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

使用共享库可以使您升级库而无需重新编译使用它的所有内容。

  • 共享库如何在OS X / Linux下工作-它们在文件系统中的位置,。/ configure && make如何找到它们,链接它们时实际发生了什么

系统库位于/ usr / lib中。

您自己编译的库位于/ usr / local / lib中(/ usr / local是./configure的默认--prefix标志)。

环境变量DYLD_FALLBACK_LIBRARY_PATH和LD_LIBRARY_PATH使您可以指定要查找的文件夹,因此/ usr / local / lib应该位于列表的开头。

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

将所有内容安装到/ usr / local-使用上述环境变量,/ usr / local / lib中的版本优先于您环境中的/ usr / lib中的版本。

  • 如果我要从源代码上安装东西,否则将使用软件包管理该系统,最干净的方法是什么?

安装到/ usr / local。在Ubuntu中,我首先尝试使用checkinstall创建一个deb包。

  • 假设我设法从源头上轻松地编译了一些东西,那么我该如何打包它,以使其他人不必跳同样的圈呢?特别是在OS X上。

我会说,在博客文章中记录编译步骤。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.