我正在尝试了解图书馆的工作原理。以下是我对此的一些疑问:
我下载了一个 tarball 并将其解压。当我执行“./configure”时,它会根据我的理解在预定义的目录中搜索某些库文件。
那么它做什么呢?它创建一个 makefile,并且该 makefile 包含这些库的路径?
然后我执行“make”,它会编译源代码并硬编码库的位置?我说得对吗?
我不太明白库是否是具有预定义路径的文件,或者操作系统是否以某种方式通过系统调用访问库。
我在计算机上编译了一些东西,然后将其移动到远程服务器,可执行文件需要 MySQL 库才能运行,服务器有 MySQL,但由于某种原因,在执行文件时它告诉我“找不到 libmysqlclient.so.16”。有解决办法吗?有没有办法知道它试图在哪里找到这个文件或给它另一个路径?
我无法在服务器上编译它,因为它没有编译器,而且我没有安装包的 root 权限。
最后一个问题是,在序列“./configure”,“make”,“make install”中,“make install”命令是否是唯一一个将文件放置在这些文件所在目录之外的命令?
例如,如果软件将安装在 /usr/local/ 中,那么“make install”命令是否是唯一一个需要在之前添加“sudo”的命令?
让我看看我是否理解正确:“./configure”根据系统上各种文件的位置创建 Makefile。“make”根据此 makefile 编译源代码。而“make install”将文件移动到适当的位置。
感谢那些耐心阅读我的问题的人。
答案1
configure
生成一个Makefile
文件,通常还有其他文件,例如config.cache
。这些文件的内容基于您传递给的选项configure
以及对系统的观察。例如,许多程序都有可选组件,并configure
查找每个组件的依赖项并生成仅构建您拥有所有依赖项的组件的 makefile。
如果您运行configure
然后更改系统配置,您应该make distclean
首先删除 makefile 和configure
的缓存(如果程序遵循通常的约定)。configure
再次运行通常在您想要向其传递不同的参数时有效,但当它缓存有关系统的观察结果时则无效。
关于库,该configure
阶段会从源兼容性的角度来查看您拥有的内容。如果libfoo2
与 源兼容libfoo3
但不与libfoo1
,并且您拥有libfoo2
,则生成的 makefile 将能够构建链接的二进制文件libfoo2
或链接的二进制文件libfoo3
但不构建链接的二进制文件libfoo1
(由于源级不兼容,编译将失败)。
当可执行文件被编译和链接时,版本要求变得更加精确:生成的可执行文件需要一个二进制兼容的库(相同的 ABI,而不仅仅是相同的 API)。
可执行文件不会硬编码库的完整路径;它们会硬编码库的名称(-l
链接器的参数),有时-rpath
还会硬编码除目标系统的默认搜索路径之外的运行时库搜索路径 ( )。在运行时查找库是动态链接器。
我建议你稍微玩一下ldd
和strace
。ldd
显示可执行文件所需的库以及系统将在哪里找到它们。strace
显示加载程序时发生的所有系统调用;前几个来自加载所需库的动态链接器。以下是一些实验,您应该尝试理解它们的结果。
ldd /bin/true
strace /bin/true
perl -pe 's/libc\.so/libc.zz/' </bin/true >broken
chmod +x broken
ldd ./broken
strace ./broken
ln -s /lib/libc.so.6 libc.zz.6
LD_LIBRARY_PATH=. strace ./broken
总结您具体问题的答案:
configure
硬编码源兼容性问题。此make
步骤硬编码二进制兼容性问题。库位置在运行时确定。- 如果只有库的位置发生了变化,动态链接器通常会找到它(如果您的库安装在非标准位置,请传递
LD_LIBRARY_PATH
环境变量)。如果您只有不同版本的库,那么它就不是同一个库;您需要获取一个具有您的程序编译所针对的 ABI 版本的库,或者根据您安装库的 ABI 版本编译您的程序。 configure
根据您系统上的内容和传递的参数确定构建配置。make
构建可执行文件和其他位。make install
将位复制到位;只有这个阶段可能需要提升的权限(如果您还没有写入目标目录的权限,例如,如果您要安装到主目录中,则需要提升权限)。configure
configure
覆盖了 makefile,但由于它保留了缓存,因此重新运行不会从头开始。
答案2
我认为,当您在一台计算机上执行 ./configure 时,它会派生出一个特定于该计算机的 makefile,然后当您传输已编译的程序时,库不在 makefile(或可执行文件)知道的位置,因此它会抛出一个错误。正如您所看到的,当您配置时,它检查的库并不是每个库都是必需的。因此它必须根据您的系统生成不同的 makefile。另一个例子是,当您拥有不同的架构时,它需要不同的库,依此类推。
是的,你的顺序是正确的。'make' 是安全命令,仅在当前目录中工作,'make install' 基本上需要 sudo。安装软件时没有 root 权限是很糟糕的。