使Xcode嵌入必要的dylib

时间:2017-02-03 11:12:57

标签: xcode macos macos-sierra dylib

我正在尝试做一些非常简单和典型的事情,它在我的Xcode项目中使用动态链接库,然后部署嵌入的所有必要库。

但是我必须以错误的方式做某事,因为Xcode 8不允许我嵌入.dylib文件,只有框架!下面的图片是当我尝试向嵌入式Binaires添加任何内容时发生的事情,dylib只是没有显示,Add Other ...将它们添加到项目中但不添加到嵌入式二进制文件。

Xcode not allowing me to add any of the dylibs as embedded binaries

必须有一种非常简单的方法,但我找不到它......

后记

显然,因为我确实需要运行一个调用install_lib_tool的脚本,所以我制作了一个非常通用的脚本,它将改变在其路径中有/local/的任何东西到嵌入式副本的路径:

#!/bin/sh

app=$BUILT_PRODUCTS_DIR/$EXECUTABLE_PATH
fw_path=$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH
app_dyl_list=(`ls $fw_path | grep dylib`)

function change_paths {
    local bin=$1
    echo change_path $bin
    dyl_list=(`otool -L $bin | grep local | awk '{print $1}'`)

    for dyl in ${dyl_list[*]}; do
        libname=$(basename $dyl)
        libname=${libname%%.*}
        actual_libname=(`ls $fw_path | grep $libname | xargs basename`)
        install_name_tool -change $dyl "@executable_path/../Frameworks/$actual_libname" $bin
        printf "\t%s edited\n" $actual_libname
    done
}

change_paths $app
for dyl_bin in ${app_dyl_list[*]}; do
    change_paths $fw_path/$dyl_bin
done

然后,只需在复制dylib之后添加一个Run Script步骤,就可以在没有参数的情况下运行它(环境变量包含所需的一切)。

2 个答案:

答案 0 :(得分:14)

我从未使用过“嵌入式库”,而是使用复制阶段复制所有需要的第三方库以及项目中各种目标创建的库。您只需将想要从“框架”和“产品”轮廓节点复制的dylib拖到此复制阶段(或通过“+”按钮添加它们)。如果启用了XCode(默认情况下),XCode也会自动为每个lib签名:

enter image description here

另请参阅“安装目录”设置。您应该将此值设置为 @executable_path /../ Frameworks (假设这是您的实际框架文件夹,至少是推荐的文件夹)。 XCode使用该值来设置dylib的ID,这对于使它们正确加载至关重要

enter image description here

您还可以使用MacDependency之类的工具来查看.app.dylib.framework个套餐的详细信息。它还将向您显示库所依赖的其他dylib以及它所期望的路径。该路径必须与链接库的ID相同,否则加载将失败。

另一个非常有用的工具是 otool ,它附带了XCode。它提供类似MacDependency等信息。以下是dylib的依赖关系列表,其中包含它所期望的路径和版本:

Mikes-iMac:Debug mike$ otool -L libcdbc.dylib
libcdbc.dylib:
    @executable_path/../Frameworks/libcdbc.dylib (compatibility version 1.0.0, current version 1.0.0)
    @executable_path/../Frameworks/libwbbase.dylib (compatibility version 1.0.0, current version 1.0.0)
    @executable_path/../Frameworks/libgrt.dylib (compatibility version 1.0.0, current version 1.0.0)
    @executable_path/../Frameworks/libgmodule-2.0.0.dylib (compatibility version 3401.0.0, current version 3401.2.0)
    @executable_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 3401.0.0, current version 3401.2.0)
    @executable_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 3401.0.0, current version 3401.2.0)
    @executable_path/../Frameworks/libmysqlcppconn.7.1.1.8.dylib (compatibility version 7.0.0, current version 7.1.1)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 307.4.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)

关于加载器路径的另一个讨论在这里:How to set dyld_library_path in Xcode

如果您创建的应用程序或库需要来自系统位置的dylib而不是相对的,那么它可能意味着您将错误的lib链接到它。在“链接二进制”构建阶段,您可以选择要链接的库,选择对话框会列出所有项目目标。此外,对于链接器列表,您只需将dylib从项目大纲中的“Products”节点拖到其中即可进行设置。此外,对于此类库,设置正确路径的要求也适用。您可以使用在复制阶段后更改ID的脚本,或者将这些库的副本保存在其他位置,将其更改一次(例如,在下载之后)并将其从那里复制到最终应用程序。< / p>

答案 1 :(得分:0)

通过“ Embedded Binaries”选项嵌入的dylib现在可以正常工作(已在Xcode版本10.2 beta 4中进行了检查)。