应用程序的命令行链接可以为 .dylib 指定 @executable_path
Can command line linking of app specify @executable_path for .dylib
除了在链接后使用 install_name_tool 更改搜索路径,或设置环境变量 DYLD_LIBRARY_PATH 之外,是否有命令行链接器指令允许将 .dylib 指定为是@executable_path?我们想将所有需要的 .dylib 文件放入应用程序包中。
当然,如果启动的可执行文件可以在启动时立即临时设置 DYLD_LIBRARY_PATH,那也可以。
这里的最终目标是允许自动生成文件驱动的构建过程以确保可以收集所需的动态库并将其放置在包中,以便可执行应用程序可以找到它们(使用@executable_path) .
注意:@rpath 不是一个选项——我们需要的框架/dylib 不是我们构建的。
您的选择是:
在 link 使用库本身时指定 -install_name <name>
。 (不是在 link 对库执行可执行文件时)。我从你的 "NOTE:" 那里得知这是不可能的。
使用 install_name_tool -id <name>
更改库的安装名称,然后再 link 针对它们的可执行文件。这样,可执行文件将包含对它们的正确引用。为了完全安全,库应该 link 编辑 -headerpad_max_install_names
。
在 link 编辑可执行文件后,对它使用 install_name_tool -change <old> <new>
,这就是您要寻找的替代方法。同样,为了安全起见,可执行文件应该 link 编辑为 -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 = ;
my $lib_subpath = ;
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 项目的 运行 脚本构建阶段,因此它取决于 Xcode 设置的环境变量,但您可以更改它足够轻松地使用命令行参数。
时间戳文件用作 运行 脚本构建阶段的输出,因此 Xcode 可以知道何时不需要重新 运行。输入是可执行文件和该脚本文件本身。您可以将它们映射到制作文件目标。
Ken Thomases 的回答详细而准确,但还有一个选择,而且似乎是一个不错的选择:
Macdylibbundler: (来自网站):“dylibbundler 是一个小型命令行程序,旨在使捆绑 .dylib 尽可能简单。它会自动确定您的程序需要哪些 dylib,复制这些库在应用程序包中,并修复它们和可执行文件以准备分发......所有这一切都只需在终端上使用一个命令!如果您的程序使用也具有依赖性的插件,它也将起作用。
除了在链接后使用 install_name_tool 更改搜索路径,或设置环境变量 DYLD_LIBRARY_PATH 之外,是否有命令行链接器指令允许将 .dylib 指定为是@executable_path?我们想将所有需要的 .dylib 文件放入应用程序包中。
当然,如果启动的可执行文件可以在启动时立即临时设置 DYLD_LIBRARY_PATH,那也可以。
这里的最终目标是允许自动生成文件驱动的构建过程以确保可以收集所需的动态库并将其放置在包中,以便可执行应用程序可以找到它们(使用@executable_path) .
注意:@rpath 不是一个选项——我们需要的框架/dylib 不是我们构建的。
您的选择是:
在 link 使用库本身时指定
-install_name <name>
。 (不是在 link 对库执行可执行文件时)。我从你的 "NOTE:" 那里得知这是不可能的。使用
install_name_tool -id <name>
更改库的安装名称,然后再 link 针对它们的可执行文件。这样,可执行文件将包含对它们的正确引用。为了完全安全,库应该 link 编辑-headerpad_max_install_names
。在 link 编辑可执行文件后,对它使用
install_name_tool -change <old> <new>
,这就是您要寻找的替代方法。同样,为了安全起见,可执行文件应该 link 编辑为-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 = ;
my $lib_subpath = ;
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 项目的 运行 脚本构建阶段,因此它取决于 Xcode 设置的环境变量,但您可以更改它足够轻松地使用命令行参数。
时间戳文件用作 运行 脚本构建阶段的输出,因此 Xcode 可以知道何时不需要重新 运行。输入是可执行文件和该脚本文件本身。您可以将它们映射到制作文件目标。
Ken Thomases 的回答详细而准确,但还有一个选择,而且似乎是一个不错的选择:
Macdylibbundler: (来自网站):“dylibbundler 是一个小型命令行程序,旨在使捆绑 .dylib 尽可能简单。它会自动确定您的程序需要哪些 dylib,复制这些库在应用程序包中,并修复它们和可执行文件以准备分发......所有这一切都只需在终端上使用一个命令!如果您的程序使用也具有依赖性的插件,它也将起作用。