除了使用install_name_tool在链接后更改搜索路径或设置环境变量DYLD_LIBRARY_PATH之外,还有一个命令行链接器指令,它允许指定.dylib为@executable_path吗?我们希望将所有必需的.dylib文件放在应用程序包中。
当然,如果启动的可执行文件可以在启动时立即暂时设置DYLD_LIBRARY_PATH,那也可以。
这里的最终目标是允许自动化的makefile驱动的构建过程,以确保可以收集所需的动态库并将其放置在bundle中,以便可执行应用程序可以找到它们(使用@executable_path)。
注意:@rpath不是一个选项 - 我们需要的框架/ dylib不是由我们构建的。
答案 0 :(得分:2)
您的选择是:
链接库本身时指定-install_name <name>
。 (不是在将可执行文件链接到库时)。我收集你的&#34;注意:&#34;这是不可能的。
在将可执行文件链接到它们之前,使用install_name_tool -id <name>
更改库的安装名称。这样,可执行文件将包含对它们的正确引用。为了完全安全,图书馆应与-headerpad_max_install_names
。
链接后,在可执行文件上使用install_name_tool -change <old> <new>
,这是您正在寻找的替代方案。同样,为了安全起见,可执行文件应该与-headerpad_max_install_names
链接。
不幸的是,这些是你唯一的选择。
如果您的目标是自动化构建,则可以自动更改可执行文件中库的引用。我们使用如下脚本:
#!/usr/bin/perl
use warnings;
use strict;
exit if ("$ENV{'ACTION'}" ne "build");
my $fullpath = "$ENV{'TARGET_BUILD_DIR'}/$ENV{'EXECUTABLE_PATH'}";
open(my $otool, "otool -L '$fullpath' |") || die "otool: $fullpath: $!";
# The first line of otool output is the file name echoed. Consume that.
my $file_echo = <$otool>;
# Process the lines listing dependent libraries
while (my $lib_line = <$otool>)
{
if ($lib_line =~ m%[[:blank:]]+(.*/([^/]*\.dylib))[[:blank:]]+\(compatibility version%)
{
my $lib_orig_path = $1;
my $lib_subpath = $2;
my $command = "install_name_tool -change '$lib_orig_path' '\@executable_path/../Frameworks/$lib_subpath' '$fullpath'";
print "$command\n";
system($command) == 0 or die "system:install_name_tool:$fullpath: $!";
}
}
open(my $timestamp_file, ">", "$ENV{'DERIVED_FILE_DIR'}/fixup_executable_lib_deps.timestamp") or die "open: $!";
print $timestamp_file time;
close($timestamp_file) or die "close: $!";
exit;
该脚本旨在用于Xcode项目的Run Script构建阶段,因此它依赖于Xcode设置的环境变量,但您可以将其更改为足以轻松使用命令行参数。
时间戳文件用作运行脚本构建阶段的输出,因此Xcode可以知道何时不需要重新运行。输入是可执行文件和此脚本文件本身。您可以将这些映射到文件目标。
答案 1 :(得分:0)
Ken Thomases的答案是详细而准确的,但是还有其他选择,而且看起来很好:
Macdylibbundler: (来自网站):“dylibbundler是一个小型命令行程序,旨在使捆绑.dylib尽可能简单。它会自动确定程序需要哪些dylib,复制这些库在应用程序包中,并修复它们和可执行文件以准备分发...所有这一切都在teminal上有一个命令!如果你的程序也使用具有依赖项的插件,它也会工作。