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

4

我知道这可能是一个非常愚蠢的问题,但我对编译语言很陌生(我的领域主要是像PHP、Python或JavaScript这样的脚本语言)。

我正在学习C ++,因为有一个项目只能使用它。

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

sudo ./compiled-program

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


编辑掉你因为这不是愚蠢问题而道歉的部分。 :) - Gordon Gustafson
这绝对不是一个愚蠢的问题。 - jason
7个回答

3
你应该阅读一些关于的内容,特别是静态库和动态库之间的区别。为了引用基本定义,以便你理解:
静态库,也称为存档文件,由一组例程组成,这些例程由编译器、链接器或绑定器复制到目标应用程序中,生成对象文件和独立可执行文件。
动态链接涉及在加载时间或运行时将库(在Windows下可能被称为DLL,在类Unix系统下可能被称为DSO(动态共享对象))的子例程加载到应用程序中,而不是在编译时链接它们。

2

这绝不是一个愚蠢的问题!

一般情况下,您的程序已经链接到一个“共享库”,因此用户需要安装OpenCV(或其他包含共享库的软件包)才能使用。

如果您使用了-static标志编译为静态可执行文件,则所有库都将直接包含在您的可执行文件中,这会使可执行文件变得更大,浪费更多内存,因为它没有使用共享库。

有一些方法可以使您的程序仅链接静态的OpenCV库,但前提是该软件包包含静态库“.a”而不是共享库“.so”。


2
如果您必须构建依赖项,例如OpenCV,则取决于您是进行静态链接还是动态链接。
请参阅此处,其中包含涵盖这些想法的部分:http://en.wikipedia.org/wiki/Library_(computing)。
首先,请尝试在命令行上执行以下操作: ldd compiled-program 您将获得类似于此输出(例如,我在/usr/bin中的python二进制文件上执行了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需要许多额外的东西,例如OpenSSL的一部分libssl,GNU C库(libc)和其他一些东西。
如果您将要将此程序移动到其他系统,则可以希望它们具有与您类似的环境,将其作为源代码分发并使用类似于autotools/GNU Build System的工具进行构建,或者您可以放弃所有这些,并将所有内容静态链接到二进制文件中,这将引入可执行文件所需的所有内容,而无需动态链接。

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

1

这取决于您是编译成共享(动态)库还是编译到可执行文件中(针对静态库进行编译)。

如果您正在编译共享库,则需要分发共享库......否则......不需要。


我刚在cpp文件中添加了三个头文件,例如:#include <opencv/highgui.h>,然后在cpp文件中使用了OpenCV函数。这是否意味着我使用了动态库还是静态库? - Richard Knop
这意味着选择静态还是动态取决于链接器而非编译器。 - Goz
不太好。我不知道使用了哪个链接器,我是通过点击Anjuta IDE的编译按钮进行编译的。 - Richard Knop
@Richard:那么你需要对你的平台进行一些研究。否则,对于你的问题的答案是完全随意的。 - Goz

1

有两种类型的库,静态加载和动态加载。 静态加载的库会与您的二进制文件一起链接,而动态加载的库则在运行时加载。


1

这取决于可执行文件是静态构建还是动态链接。在静态构建的可执行文件中,所需的库文件已编译到可执行文件中,因此不需要携带额外的库文件。在动态链接的可执行文件中,所需的库文件在运行时链接,因此需要在运行时复制库文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接