gpt4 book ai didi

c++ - 是否需要 LD_LIBRARY_PATH(linux) 或 DYLD_LIBRARY_PATH mac

转载 作者:行者123 更新时间:2023-11-30 05:30:39 26 4
gpt4 key购买 nike

我正在使用 openCV 库进行计算机视觉研究,并且在编译时遇到了一些问题,这些问题让我尝试了解操作系统如何将库与源代码链接起来。在互联网上寻找了一段时间以获得良好的概述并阅读 g++/gcc 的手册后,ld...我有一些结论,我希望有更多经验的人来解释我。

首先是我使用的编译行。这是:

-输入:g++ pkg-config --cflags --libs opencv image-conversion.cpp -o image-conversion

  • 输出:可执行代码
  • 输入:pkg-config --cflags --libs opencv
  • 输出:-I/opt/local/include/opencv -I/opt/local/include -L/opt/local/lib -lopencv_shape -lopencv_stitching -lopencv_objdetect -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_core

  • 我的代码需要的库是 -lopenhighgui但我更喜欢以这种方式编译,因为这个库依赖于其他库。问题是当我去 /opt/local/lib要查看库,我有三个文件:
    -libopencv_highgui.3.1.0.dylib
    -libopencv_highgui.3.1.dylib
    -libopencv_highgui.dylib

    我不知道是哪个图书馆的 -lopenhighgui指。我在 g++ 的手册中发现 -l flag 指定库名避免 lib前缀和 *.a *.so (Linux)/ *.dylib (mac) 后缀。执行后otool -L可执行我得到输出:
  • /opt/local/lib/libopencv_highgui.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)

  • 那么为什么它使用这个而不是另一个,它的使用方式是什么?这三个库有什么区别?

    另一个问题是关于链接和执行过程。我已经了解了使用静态库时的链接过程。我的问题是编译动态库时。在下一个示例中:

    -输入: g++ -I/opt/local/include/opencv -I/opt/local/include -L/opt/local/lib -lopencv_highgui image-conversion.cpp -o image-conversion
    我发现从编译到执行一个程序的过程可以分为三个部分。
  • 第一个编译器在标准目录下寻找头文件或目录通过-I标志进行代码解析。
  • 其次,它链接由 -lflag 指定的库。 ,在路径 -L 或标准路径下。这是通过链接器 (ld)
  • 完成的。
  • 第三,在执行时,动态链接器程序 (dyld) 是负责将代码“添加”到 RAM 内存以便执行的程序。

  • 问题是下一个:我在互联网上发现有些人说如果他们不设置 $LD_LIBRARY_PATH (在 linux 中)或 $DYLD_LIBRARY_PATH (在 mac OSx 中)与库的非标准目录(在我的情况下是 export LD_LIBRARY_PATH="/opt/local/lib" ),动态链接器找不到库并且程序执行失败。我发现我的程序没有崩溃,如果我执行 otool (用于查看链接的内容)。我得到了这个(这是所有链接的库的摘要):
    /opt/local/lib/libopencv_shape.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
    /opt/local/lib/libopencv_imgproc.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
    ...
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

    怎么了?我发现 LD_LIBRARY_PATH 可以用来测试新库,但是为什么这个人说他们只需要设置这个变量来执行程序?最后一部分如何工作?我没有设置它,它工作得很好。

    感谢任何人。

    最佳答案

    实际上有两个问题(顺便说一句,这不是一个很好的 SO 实践),所以我将独立回答。

    另外,我将专注于 Linux——这是我熟悉的领域。从问题的文字来看,我认为 Mac 世界中的情况非常相似。

    库命名约定

    在 Linux 环境中使用 .so 文件时,经常会看到动态库通常以三元组形式呈现。例如,库 foo 可能存在于 3 个文件中:libfoo.so、libfoo.so.6、libfoo.so.6.5.4。如果你仔细看,你会发现它们都是同一个文件——通常其中两个只是到第三个的符号链接(symbolic link)。为了进一步讨论,libfoo.so 将被称为非版本库,ibfoo.so.6 被称为主要版本,libfoo.so.6.5.4 *full-versioned。你为什么需要那些?为了更好的版本控制。

    当您链接您的应用程序时,您总是使用链接器规则来进行未版本化的 livbary - 考虑到链接器添加 lib 的事实。和 .so按照规则,它看起来像

    g++    ... -lfoo ...

    当您的应用程序被链接时,链接器会打开 libfoo.so 并检查它的几项内容。它检查的东西之一是所谓的 SONAME标题。此 header 是在链接 .so 库时创建的,它可以具有与当前查看的链接器不同的文件名。例如,它可能有一个主版本文件,链接器会看到它:SONAME = libfoo.so.6。

    当链接器看到 SONAME 时,它会将生成的应用程序文件标记为需要 libfoo.so.6 - 即使您实际要求 libfoo.so .

    通过这样做,链接器保留了库的某个版本。您的应用程序最初是使用版本 6 编译和链接的,因此无论何时运行应用程序,都需要版本 6。

    如果稍后系统升级(或应用程序在不同的系统上运行),其中 foo是不同的版本(比如 7),.so 文件会不同:libfoo.so、libfoo.so.7、libfoo.so.7.6.5。由于您的应用需要 libfoo.so.6 ,它将无法启动 - 这是一件好事,因为谁知道版本 7 是否仍然兼容?如果没有此保护,应用程序将启动并使用不同的库版本,其影响可能是毁灭性的。

    LD_LIBRARY_PATH 搜索

    您的第二个问题是针对 LD_LIBRARY_PATH。确实如此,运行时链接器在查找动态库时会引用此变量。然而,它并不是唯一的咨询对象。除此之外,从默认搜索路径中,还有一个每个应用程序的动态库路径,它在链接时记录在应用程序中,通常由链接器的 rpath 参数控制,例如:
    g++ ... -Wl,rpath,/path/to/so/library

    当这样记录路径时,运行时链接器将在加载应用程序时将这些路径添加到搜索路径列表中。

    可以在没有 LD_LIBRARY_PATH 的情况下为您的应用程序找到库这一事实意味着两件事之一:链接应用程序时记录了 rpath,或 /opt/local/lib实际上包含在您平台上的默认搜索路径中。

    关于c++ - 是否需要 LD_LIBRARY_PATH(linux) 或 DYLD_LIBRARY_PATH mac,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35874768/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com