关于外部库编译程序使用的问题

Posted

技术标签:

【中文标题】关于外部库编译程序使用的问题【英文标题】:question about compiled program usage of external libraries 【发布时间】:2010-11-22 22:10:11 【问题描述】:

我知道这可能是一个非常愚蠢的问题,但我是编译语言的新手(我的领域主要是 php、Python 或 javascript 等脚本语言)。

我正在为一个项目学习 C++,它是我唯一可以使用的语言。

我在 Ubuntu 10.10 中编写了一个程序,然后编译了它。我可以像这样从 cmd 运行生成的二进制文件,它可以工作:

sudo ./compiled-program

但是,我在程序中使用了一些外部库(OpenCV)。这是否意味着我将运行该程序的所有计算机都必须安装 OpenCV?还是 OpenCV 捆绑在已编译的二进制文件中?它可以在没有安装 OpenCV 的 PC 上运行吗?

【问题讨论】:

编辑了你的道歉,因为它不是一个愚蠢的问题。 :) 这绝对不是一个愚蠢的问题。 【参考方案1】:

您应该阅读一些关于libraries 的内容,尤其是静态库和动态库之间的区别。引用基本定义以便您明白这一点:

静态库,也称为 存档,由一组例程组成 复制到目标中 由编译器、链接器应用, 或活页夹,生成目标文件和 一个独立的可执行文件。

[...]

动态链接涉及加载 库的子程序(可能是 称为 DLL,尤其是在 Windows,或作为 DSO(动态共享 object) 在类 Unix 系统下) 成 一个应用程序在加载时或 运行时,而不是将它们链接到 在编译时

【讨论】:

【参考方案2】:

根本不是一个愚蠢的问题!

这种工作的“正常”方式 - 是您的程序已链接到“共享库” - 在这种情况下,是的,用户需要 OpenCV(或任何包含共享库的捆绑包)才能工作。

如果您编译为 static 可执行文件,(使用 -static)标志,那么它和 all 库将直接包含在您的可执行文件中,这有点更大的可执行文件会浪费更多的内存,因为它没有使用共享库。

您可以通过多种方式编译您的程序以将您的 OpenCV 库链接为静态 - 但只有在捆绑包包含静态库“.a”而不是共享库时才能这样做“.so”。

【讨论】:

【参考方案3】:

如果您必须针对依赖项(如 OpenCV)构建代码,则取决于您是进行静态链接还是动态链接。

请参阅此处,其中包含涵盖这些想法的部分:http://en.wikipedia.org/wiki/Library_(computing)

对于初学者,请尝试在命令行上执行此操作:

ldd compiled-program

你会得到这样的输出(例如,我在python 二进制文件中的/usr/bin 上做了ldd):

birryree@lilun:/usr/bin$ ldd python
        linux-gate.so.1 =>  (0xb7ff7000)
        libpthread.so.0 => /lib/i686/cmov/libpthread.so.0 (0xb7fd5000)
        libdl.so.2 => /lib/i686/cmov/libdl.so.2 (0xb7fd1000)
        libutil.so.1 => /lib/i686/cmov/libutil.so.1 (0xb7fcd000)
        libssl.so.0.9.8 => /usr/lib/i686/cmov/libssl.so.0.9.8 (0xb7f82000)
        libcrypto.so.0.9.8 => /usr/lib/i686/cmov/libcrypto.so.0.9.8 (0xb7e2a000)
        libz.so.1 => /usr/lib/libz.so.1 (0xb7e16000)
        libm.so.6 => /lib/i686/cmov/libm.so.6 (0xb7df0000)
        libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7caa000)
        /lib/ld-linux.so.2 (0x80000000)

Python 需要很多额外的东西,例如 libssl(OpenSSL 的一部分)、GNU C 库 (libc) 等等。

现在,如果您要将这个东西转移到其他系统,您要么希望他们有一个与您的环境相似的环境,将其作为源代码分发并使用类似autotools/GNU 构建系统的东西来构建它,或者您可以放弃所有这些并将所有内容静态链接到您的二进制文件中,这将带来可执行文件所需的所有内容,而无需动态链接。

【讨论】:

【参考方案4】:

如果您已针对 OpenCV “编译”,那么运行您的应用程序的机器也需要它。您需要在安装应用时复制这些库,或确保它们已安装。

【讨论】:

【参考方案5】:

这取决于您是针对共享(动态)库进行编译还是将其编译为可执行文件(针对静态库进行编译)。如果您正在针对共享库进行编译,则需要分发共享库......否则......你不需要。

【讨论】:

我刚刚在 cpp 文件中添加了三个头文件,例如:#include 然后在 cpp 文件中使用 OpenCV 函数。这是否意味着我使用了动态或静态库? 这意味着两者都不是......静态或动态的选择取决于链接器而不是编译器。 那不好。我不知道使用了什么链接器,我通过单击编译按钮在 Anjuta IDE 中进行编译。 @Richard:那么您需要对您的平台进行一些研究。否则你的问题的答案是完全任意的。【参考方案6】:

有两种库,静态和动态加载。 静态加载的库与您的二进制文件连接,而动态加载的库在运行时加载。

【讨论】:

【参考方案7】:

这取决于可执行文件是statically-built 还是dynamically linked。在静态构建的可执行文件中,可执行文件需要的库文件被编译到可执行文件中,并且不需要携带额外的库文件。在动态链接的可执行文件中,可执行文件需要的库文件在运行时链接,因此在运行时需要库文件的副本。

【讨论】:

以上是关于关于外部库编译程序使用的问题的主要内容,如果未能解决你的问题,请参考以下文章

WebAssembly 编译器错误:使用外部库编译时未定义符号

添加外部库后,AndroidManifest.xml 中的应用程序图标问题

OpenCV c++ 应用程序部署与外部库

使用 Tomcat 运行带有外部库的应用程序时出现 NoClassDefFoundError

Typescript Compiler - 捆绑外部库

交叉编译时如何使用外部库?