10

我一直在为这个概念苦苦挣扎,我无法真正理解和之间的区别-change-id手册页指出

 -id name
              Changes  the  shared  library identification name of a dynamic shared library to name.  If the Mach-O binary is not a dynamic
              shared library and the -id option is specified it is ignored.

-change old new
              Changes  the dependent shared library install name old to new in the specified Mach-O binary.  More than one of these options
              can be specified.  If the Mach-O binary does not contain the old install name in a specified -change  option  the  option  is
              ignored.

到目前为止,我已经尝试过-change. 假设我有以下结构

Test.App
|_Contents
    |_MacOS
    |   |_test -----> item A
    |_Library
        |_test_library.dylib     --->item B
        |_another_library.dylib  --->item C

现在假设我在 itemB 上运行了以下内容

$ otool -L test_library.dylib
   test_library.dylib
   /some/path/another_library.dylib  -->item D

上面的结果表明,test_library.dylib取决于another_library.dylib现在是否需要更改another_library.dylib我会这样做的位置

install_name_tool -change /some/path/another_library.dylib some/new/path/another_library.dylib  test_library.dylib 

这将改变项目 D 的位置。我的问题是做install-name_tool -id什么以及何时使用它?

4

3 回答 3

11

安装名称

术语安装名称指的.dylib是最终用户系统中文件的确切路径,因此运行时链接器可以找到并加载动态库。

名称可以是:

  • 绝对的,系统库就是这种情况。这些在最终用户和开发人员的系统上都位于相同的位置。
  • 相对的,这是与应用程序捆绑在一起的库的情况。在最终用户的系统上,.dylib它们将被嵌入到应用程序包中,而在开发者系统上,它们将被预先构建或在其他地方/usr/local/opt/local或者它们将作为应用程序构建的一部分从源代码构建。

后者是主要问题,因为在.dylib构建时,它的安装名称被链接器标记到 中.dylib,这就是在运行时可以找到并加载它的地方。显然,这不适用于最终用户系统,因为该路径仅存在于开发人员的系统上,因此解决方案是在将应用程序包放在一起时install_name_tool修改库的安装名称以及引用这些库的可执行文件.

占位符

由于可执行文件/应用程序包可以安装在最终用户系统的不同位置,您可以使用占位符系统来抽象安装名称位置:

  • @executable_path:主可执行文件的完整路径。
  • @loader_path: 引用可执行文件的完整路径或.dylib.
  • @rpath:主可执行文件中设置的 RPATH。这也可以使用更改install_name_tool

因此,例如在 macOS 应用程序包中,可执行文件将在其中,TheApp.app/Contents/MacOS/TheApp而库将在其中,TheApp.app/Contents/Frameworks因此您可能希望使用 path 引用库@executable_path/../Frameworks/Library.dylib

@executable_path/../Frameworks然而,最好将主可执行文件的 RPATH 设置为,并使用@rpath/Library.dylib.

install_name_tool

install_name_tool有两个主要选项:

-id:这将设置文件本身的安装名称,并且当某些东西与. 您可以在构建后立即“更正”安装名称,但这是一个不寻常的工作流程,因为库如何知道使用它的环境?.dylib.dylib.dylib

-change:这会更改引用可执行文件(或 dylib)中的安装名称。.dylib

当名称与-id名称不匹配时会发生什么-change?没有。一旦运行时链接器发现任务完成,该-change选项是正确的重要选项。.dylib

xcodedevtools

您显然会使用脚本编写所有修复程序,但这有点乏味,因此我开发了copy_dylibs.py脚本来为您完成所有工作。您将其配置为在链接您的应用程序可执行文件后运行,它会查看您的可执行文件以递归查找.dylib要复制到应用程序包中的文件。然后它会修复它们的安装名称,而保留原始.dylib文件。

于 2016-02-05T09:14:15.743 回答
4

install_name_tool -id用于更改install nameof dylib,你可以在终端中使用otool -D查看一个dylib install name,它会为你显示默认值,/some/path/another_library.dylib是默认install nameanother_library.dylib,当然你可以在终端中更改它使用install_name_tool -id,就这样在终端中使用终端

install_name_tool -id /some/path/another_library_newname.dylib /some/path/another_library.dylib

现在,你使用otool -D /some/path/another_library.dylib,你会发现install nameis/some/path/another_library_newname.dylib

这是我在图片中的例子

于 2018-12-12T07:15:03.913 回答
1

id在链接时install name使用并在运行时使用。它们都是提供给链接器定位dylib的信息。我跟着这个教程

让我举个例子,

$ cat a.cc
#include <iostream>
void a() { std::cout << "a()" << std::endl; }
$ clang++ -c a.cc
$ clang++ -o liba.dylib -dynamiclib a.o
$ otool -L liba.dylib
liba.dylib:
        liba.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)

如您所见,第一行是id. 让我们链接 libb.dylib,

$ cat b.cc
#include <iostream>
void a();
void b() { std::cout << "b()" << std::endl; a(); }
$ clang++ -c b.cc
$ clang++ -o libb.dylib -dynamiclib b.o -L. -la
$ otool -L libb.dylib
libb.dylib:
        libb.dylib (compatibility version 0.0.0, current version 0.0.0)
        liba.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)

请注意第二行,id这里使用了 for liba.dylib。让我们将 id 更改为foo/liba.dylib并再次链接,

$ install_name_tool -id foo/liba.dylib liba.dylib
$ otool -D liba.dylib
liba.dylib:
foo/liba.dylib
liba.dylib:
        foo/liba.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)

因此,您会看到-D-L所有输出电流idfoo/liba.dylib

让我们再次与 liba.dylib 再次链接,

$ clang++ -o libb.dylib -dynamiclib b.o -L. -la
$ otool -L libb.dylib
libb.dylib:
        libb.dylib (compatibility version 0.0.0, current version 0.0.0)
        foo/liba.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)

看到不同?查找 liba.dylib 的运行时位置更改为foo/liba.dylib第二

基本上,它告诉 libb.dylib 从current_dir/foo

于 2020-04-18T21:35:03.890 回答