运行时库#

为了说明即使是一个简单的程序也依赖于外部运行时库,下面是报告此类依赖关系的 ldd 实用程序的输出:

$ ldd tabulate.exe
        ntdll.dll => /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll (0x7ff88f2b0000)
        KERNEL32.DLL => /cygdrive/c/WINDOWS/System32/KERNEL32.DLL (0x7ff88e450000)
        KERNELBASE.dll => /cygdrive/c/WINDOWS/System32/KERNELBASE.dll (0x7ff88b9e0000)
        cygwin1.dll => /usr/bin/cygwin1.dll (0x180040000)
        cyggfortran-5.dll => /usr/bin/cyggfortran-5.dll (0x3efd20000)
        cygquadmath-0.dll => /usr/bin/cygquadmath-0.dll (0x3ee0b0000)
        cyggcc_s-seh-1.dll => /usr/bin/cyggcc_s-seh-1.dll (0x3f7000000)

其它编译器或同一编译器的其它版本可能需要不同的动态库。只要你在同一台计算机上运行程序 —— 或者更准确地说,在同一环境中 —— 应该没有问题。但是,当找不到这样的库时,你会(希望)收到一条错误消息,并且程序会立即停止。

因此,最好知道需要哪些库。在 Linux 和类似 Linux 的环境中,ldd 实用程序很有帮助。在 Windows 上,你可能想要使用 dependency walker(最新版本,可以很好地与 Windows 10 配合使用,可在此处找到:https://github.com/lucasg/Dependencies

你应该知道的另一件事是程序试图在哪里找到这些库。这本身就是一个庞大的主题,充满了复杂性和历史。在这里,我们只是触及表面:

在 Linux 上:

  • 使用环境变量 LD_LIBRARY_PATH。它由要搜索的目录列表组成,每个目录通过冒号 (:) 与其它目录分隔。例如: /usr/lib:/usr/local/lib —— 典型的系统目录。

  • 在链接步骤中,你还可以使用选项设置 RPATH,即放入可执行文件本身的目录列表。

  • 然后有几个系统目录被搜索。

在 Windows 上:

  • 包含可执行程序的目录也可能包含动态库。

  • 使用环境变量“PATH”。再次列出要搜索的目录,但现在分隔字符是分号 (;)。

  • 搜索一组系统目录。

不幸的是,细节可能会从一个版本的操作系统更改为下一个版本。以上只是一个指示——使用“ldd”或“dependency walker”之类的工具来找出加载了哪些库以及在哪里找到它们。

如果你想与世界各地的同事或客户或简单的用户共享你的程序,你必须注意,除了程序之外,你还要分发它所依赖的库。更多信息:见下文。