Xcode 应用程序的命令行链接能否为.dylib指定@executable\u路径

Xcode 应用程序的命令行链接能否为.dylib指定@executable\u路径,xcode,macos,clang,dylib,Xcode,Macos,Clang,Dylib,除了在链接后使用install_name_工具更改搜索路径,或设置环境变量DYLD_LIBRARY_PATH外,是否有命令行链接器指令允许.dylib的规范为@executable_PATH?我们希望将所有必需的.dylib文件放入应用程序包中 当然,如果启动的可执行文件可以在启动后立即临时设置DYLD_LIBRARY_路径,那么这也会起作用 这里的最终目标是允许一个自动化的makefile驱动的构建过程,以确保所需的动态库可以被收集并放置在bundle中,以便可执行应用程序可以找到它们(使用@

除了在链接后使用install_name_工具更改搜索路径,或设置环境变量DYLD_LIBRARY_PATH外,是否有命令行链接器指令允许.dylib的规范为@executable_PATH?我们希望将所有必需的.dylib文件放入应用程序包中

当然,如果启动的可执行文件可以在启动后立即临时设置DYLD_LIBRARY_路径,那么这也会起作用

这里的最终目标是允许一个自动化的makefile驱动的构建过程,以确保所需的动态库可以被收集并放置在bundle中,以便可执行应用程序可以找到它们(使用@executable\u path)

注意:@rpath不是一个选项--我们需要的框架/动态库不是我们自己构建的。

您的选项是:

  • 在链接库本身时指定
    -install\u name
    。(不在针对库链接可执行文件时)。我从你的“便条”中推断,这是不可能的

  • 在将可执行文件链接到库之前,请使用
    install\u name\u tool-id
    更改库的安装名称。这样,可执行文件将包含对它们的正确引用。为了完全安全,这些库应该与
    -headerpad\u max\u install\u名称链接起来

  • 链接可执行文件后,在其上使用
    install\u name\u tool-change
    ,这是您正在寻找的替代方法。同样,为了安全起见,可执行文件应该链接到
    -headerpad\u max\u install\u name

不幸的是,这些是你唯一的选择

如果您的目标是自动化构建,那么很有可能自动更改对可执行文件中库的引用。我们使用如下脚本:

#!/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;
#/usr/bin/perl
使用警告;
严格使用;
如果(“$ENV{'ACTION'}”ne“build”),则退出;
my$fullpath=“$ENV{'TARGET\u BUILD\u DIR'}/$ENV{'EXECUTABLE\u PATH'}”;
打开(my$otool,“otool-L'$fullpath'|“))| | die“otool:$fullpath:$!”;
#otool输出的第一行是回显的文件名。把它吃掉。
我的$file_echo=;
#处理列出依赖库的行
而(我的$lib_行=)
{
如果($lib_line=~m%[[:blank:]+(.*/([^/]*\.dylib))[[:blank:]+\(兼容性版本%)
{
my$lib_orig_path=$1;
我的$lib_子路径=$2;
my$command=“install\u name\u tool-更改“$lib\u orig\u path”\@executable\u path/。/Frameworks/$lib\u子路径“$fullpath”;
打印“$command\n”;
系统($command)==0或“系统:安装工具:$fullpath:$!”;
}
}
打开(my$timestamp_file,“>”、“$ENV{'DERIVED_file_DIR'}/fixup_executable_lib_deps.timestamp”)或死在“open:$!”;
打印$timestamp_文件时间;
关闭($timestamp_文件)或死“关闭:$!”;
出口
该脚本设计用于Xcode项目的运行脚本构建阶段,因此它取决于Xcode设置的环境变量,但您可以将其更改为使用命令行参数

时间戳文件用作运行脚本构建阶段的输出,以便Xcode可以知道何时不需要重新运行。输入是可执行文件和此脚本文件本身。您可以将这些文件映射为文件目标。

您的选项有:

  • 在链接库本身时指定
    -install\u name
    。(而不是在针对库链接可执行文件时)。我从您的“注意:”中得知这是不可能的

  • 在链接可执行文件之前,请使用
    install\u name\u tool-id
    更改库的安装名称。这样,可执行文件将包含对它们的正确引用。为了完全安全,库应已链接到
    -headerpad\u max\u install\u name

  • 链接可执行文件后,使用
    install\u name\u tool-change
    ,这是您正在寻找的替代方法。同样,为了安全起见,应将可执行文件链接到
    -headerpad\u max\u install\u 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;
!/usr/bin/perl
使用警告;
严格使用;
如果(“$ENV{'ACTION'}”ne“build”),则退出;
my$fullpath=“$ENV{'TARGET\u BUILD\u DIR'}/$ENV{'EXECUTABLE\u PATH'}”;
打开(my$otool,“otool-L'$fullpath'|“))| | die“otool:$fullpath:$!”;
#otool输出的第一行是回显的文件名。使用它。
我的$file_echo=;
#处理列出依赖库的行
而(我的$lib_行=)
{
如果($lib_line=~m%[[:blank:]+(.*/([^/]*\.dylib))[[:blank:]+\(兼容性版本%)
{
my$lib_orig_path=$1;
我的$lib_子路径=$2;
my$command=“install\u name\u tool-更改“$lib\u orig\u path”\@executable\u path/。/Frameworks/$lib\u子路径“$fullpath”;
打印“$command\n”;
系统($command)==0或“系统:安装工具:$fullpath:$!”;
}
}
打开(my$timestamp_file,“>”、“$ENV{'DERIVED_file_DIR'}/fixup_executable_lib_deps.timestamp”)或死在“open:$!”;
打印$timestamp_文件时间;
关闭($timestamp_文件)或死“关闭:$!”;
出口
该脚本设计用于Xcode项目的运行脚本构建阶段,因此它取决于Xcode设置的环境变量,但您可以将其更改为使用命令行参数


时间戳文件用作运行脚本构建阶段的输出,这样Xcode就可以知道何时不需要重新运行它。输入是可执行文件和此脚本文件本身。您可以将它们映射到文件目标。

Ken Thomases的答案详细而准确,但是还有一个选项,而且似乎是一个不错的选项:

(来自网站):“dylibbundler