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

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

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

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

sudo ./compiled-program 

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

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

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

[…]

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

不是一个愚蠢的问题!

这个工作的“正常”方式是,你的程序已经链接到“共享库” – 在这种情况下,用户需要OpenCV(或者包括共享库的任何包)来工作。

如果您编译为静态可执行文件(使用-static)标志,那么它和所有库将直接包含到您的可执行文件中,从而导致一些较大的可执行文件浪费更多的内存,因为它没有使用共享图书馆。

有一些方法可以编译你的程序, 将你的OpenCV库链接成静态的,但是只有当这个bundle包含一个静态库“.a”和一个共享库“.so”时才能完成。

如果必须针对依赖性构建代码(如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需要很多额外的东西,比如libssl (OpenSSL的一部分),GNU C库( libc )等等。

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

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

这取决于你正在编译的共享(动态)库或编译到您的可执行文件(编译对静态库)。 如果您正在编译共享库,则需要分发共享库…否则,您不需要。

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

这取决于可执行文件是否是静态构建的或动态链接的 。 在一个静态构建的可执行文件中,库文件的可执行需求被编译到可执行文件中,并且不需要携带额外的库文件。 在动态链接的可执行文件中,库文件的可执行需求在运行时被链接,因此在运行时需要库文件的副本。