5

我正在尝试在 XCode 中创建一个 mac 应用程序,它的一些实现在动态库中。

我在我的 XCode cocoa 项目中添加了一个新目标(动态库),在与框架和预编译头文件进行了一番斗争之后,让 dynlib 编译 - 并从调试器成功运行。

但是,当独立运行时,很明显 dynlib 位于错误的位置。“未加载库:/usr/local/lib/testlib.dynlib”。在 Windows(我更常用的平台)上,Dll 可以放在与 exe 相同的文件夹中,也可以放在系统路径上的任何位置。

我希望我的应用程序在其应用程序包中的某处寻找它的 dynlib(并且某些文档似乎证实这是正确的方法),但我不知道如何。

是否可以在 XCode 中配置项目,以便将 dylib 实际上复制到应用程序包中,在应用程序查找它的地方?


看来我不需要使用 otool 来重置搜索路径。如果我编辑目标信息 -> 构建 -> 部署 -> 安装目录,我可以从 XCode 内部更改 dyld 将为 dylib 查找的路径。默认情况下,对于新的动态库项目,路径设置为/usr/local/lib. 我已更改为./- otool 确认 ./ 现在是 dyld 正在寻找这个特定动态模块的地方。不幸的是 ./ 似乎并没有真正引用我的应用程序包中的任何目录:(

所以,我的问题(在另一个线程中没有回答)现在是:1.如何在 Target Info -> ... -> Installation Directory 设置中输入有意义的相对路径,以及 2.如何让 XCode 自动将dylib“目标”复制到应用程序捆绑目标的捆绑文件夹中的相对位置?

4

3 回答 3

6

最后。找到了一些官方文档。它可以完全在 XCode 中完成。

我正在修改库的已安装目录设置:它需要: @executable_path/../Frameworks

然后我需要在库中添加一个“复制文件”构建步骤,以将其实际复制到 Frameworks 文件夹中。

简单的。自动的。

于 2009-12-02T14:36:41.400 回答
1

我相信您不会在编译时将动态库复制到应用程序包中。

应用程序正在文件系统中寻找一个点,但它只是在应用程序包中没有找到它之后才这样做。您需要otool在编译后使用该命令修改二进制文件(使用构建脚本)。

您将在之前提出的问题中找到答案: 如何在 Xcode 中创建动态库

祝你好运。

于 2009-12-02T11:28:17.543 回答
0

经过大量研究,我得到了它,我试图用我的应用程序打包一些 openCV dylib,因为我收到“库未加载:....”错误。

Dylibs 有一个安装名称,表明您第一次安装它们的位置(macports 将它们安装在 /opt/local/lib/ 上)。他们也有通往其他 dylib 的路径,他们需要工作。例如,如果您有名为“libopencv_core.2.4.8.dylib”的 dylib,您可以使用以下命令检查安装名称和它使用的其他 dylib 的路径:

otool -L libopencv_core.2.4.8.dylib

该命令的输出是:

libopencv_core.2.4.8.dylib:
/opt/local/lib/libopencv_core.2.4.dylib (compatibility version 2.4.0, current version 2.4.8)
/opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.8)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

1- 第一行:您正在检查的文件的名称。

2- 第二行:安装您正在检查的 dylib 的名称。(macports 将它们安装在 /opt/local/lib/ 中)

3- 第三行:它需要工作的其他 dylib 的路径,这些路径并非在所有 OSX 系统中。(macports 将它们安装在 /opt/local/lib/ 中,因为您以前安装了它们,这就是为什么如果您将应用程序分发到其他 mac 会出现“找不到库”错误)

4 & 5 - 第 4 和 5 行:所有 macOSX 系统中的 dylib。您不需要将它们复制到您的项目中。

现在我们知道了这一点,我们的目标是:

1- 更改 dylibs 中的所有路径(安装名称和其他所需 dylibs 的路径),因为我们将把我们的 dylibs 放在应用程序的“Frameworks”目录中,当我们移动应用程序或将其复制到其他 mac我们希望 dylib 在我们应用程序目录内的“frameworks”文件夹中相互查找:我们将使用的路径是:

@executable_path/../Frameworks/nameOFTheDylib.dylib

(注意这两点非常重要!)

2-将我们需要的所有dylib复制到xCode,但不是/opt/local/lib文件夹中的所有dylib,只是我们需要的:(它们都太多了,可能500Mb)我们需要遵循来自我们知道我们需要的 dylib(通常是 4 或 5 个)和包含的 dylib 的链接,因为这 4 或 5 个需要它们才能工作。

Y终于这样做了:

a) 更改路径:

1- 将所有 /opt/local/lib 文件复制到桌面。

2- 删除 lib 文件夹中所有不是 .dylib 档案的文件。

3-将此脚本放入我们刚刚复制到桌面的 lib 文件夹中(连同 dylibs):

(将这段文字复制到 textEdit 并保存为 theNameYouPrefer.sh)

#!/bin/bash
echo empieza el script

EXECFILE=${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}
OLDLIBPATH="/opt/local/lib/"
NEWLIBPATH="@executable_path/../Frameworks/"
ACTUALPATH=`pwd`
# space separated list of libraries
for TARGET in ${ACTUALPATH}/* ; do
TARGET=$(basename $TARGET)
    if [ ${TARGET: -6} == ".dylib" ]
    then
        echo otool -DX ${TARGET}
        TARGETID=`otool -DX ${TARGET}`
        echo ${TARGETID}

        echo install_name_tool -id ${NEWLIBPATH}${TARGET} ${TARGET}
        echo `install_name_tool -id ${NEWLIBPATH}${TARGET} ${TARGET}`

        for DYLIB in ${ACTUALPATH}/* ; do
        DYLIB=$(basename $DYLIB)
            if [ ${DYLIB: -6} == ".dylib" ]
            then
                echo install_name_tool -change ${TARGETID} ${NEWLIBPATH}${TARGET} ${DYLIB}
                echo `install_name_tool -change ${TARGETID} ${NEWLIBPATH}${TARGET} ${DYLIB}`
            else
                if [ ${DYLIB: -3} == ".sh" ]
                then
                    echo soyYo
                else
                    echo mkdir ${ACTUALPATH}/eliminadas/
                    echo `mkdir ${ACTUALPATH}/eliminadas/`
                    echo mv ${DYLIB} ${ACTUALPATH}/eliminadas
                    echo `mv ${TARGET} ${ACTUALPATH}/eliminadas`
                fi
            fi
        done
    else
if [ ${TARGET: -3} == ".sh" ] || ![ -h ${TARGET} ]
        then
            echo noMeElimino
        else
            echo mkdir ${ACTUALPATH}/eliminadas/
            echo `mkdir ${ACTUALPATH}/../eliminadas/`
            echo mv ${TARGET} ${ACTUALPATH}/eliminadas/${TARGET}
            echo `mv ${TARGET} ${ACTUALPATH}/../eliminadas`
        fi
    fi
done

echo finaliza el script

4-执行它:

cd Desktop/lib
sudo ./theNameYouPrefer.sh

将它作为 sudo 运行非常重要,因为 dylib 可以被写保护。

此时,您应该更改了所有 dylibs 路径。您可以使用以下命令在一些 dylib 中检查它:

otool -L theDylibYouPrefer.dylib

b) 只选择所需的 dylib,而不是所有 lib 文件夹:

1-将lib文件夹重命名为lib2:lib =====> lib2

2- 在桌面的 NEXT TO lib2 文件夹中创建另一个文件夹(使用您喜欢的名称,例如 exampleFolder)。

3-在exampleFolder中复制您知道肯定需要它们的重要dylib,在我的情况下它们是:libopencv_core.2.4.8.dylib、libopencv_highgui.2.4.8.dylib、libopencv_imgproc.2.4.8.dylib、libopencv_objdetect。 2.4.8.dylib

4- 脚本:将其复制到 exampleFolder 中,紧挨着重要的 dylib。我对脚本不太了解,所以这个有点脏:

#!/bin/bash
echo empieza el script

EXECFILE=${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}
OLDLIBPATH="/opt/local/lib/"
NEWLIBPATH="@executable_path/../Frameworks/"
ACTUALPATH=`pwd`
# space separated list of libraries
for TARGET in ${ACTUALPATH}/* ; do
TARGET=$(basename $TARGET)
    if [ ${TARGET: -6} == ".dylib" ]
    then
        echo otool -DX ${TARGET}
        TARGETID=`otool -L ${TARGET}`
echo ${TARGETID}

echo :::::::::::::::::::::::::::

ELIM=`echo ${TARGETID} | sed 's/([^)]*)/UUU/g'`
echo $ELIM
#echo ${TARGETID} | sed 's/([^)]*)/UUU/g'
ELIM=`echo $(awk '{gsub("@executable_path/../Frameworks/", "");print}' <<< ${ELIM})`
echo $ELIM

ELIM=`echo $(awk '{gsub(" UUU", "");print}' <<< ${ELIM})`
echo $ELIM

ELIM=`echo $(awk '{gsub(":", "");print}' <<< ${ELIM})`
echo $ELIM

IFS=' ' read -a ARRAY <<< $ELIM

for element in ${ARRAY[@]}
do
    echo $element
    if [[ ${element} == */* ]]
    then
        echo "NO FRAMEWORK";
    else
        echo `mkdir ${ACTUALPATH}/../copy`
        echo `cp ${ACTUALPATH}/../lib2/${element} ${ACTUALPATH}/${element}`
    fi
done


    else
if [ ${TARGET: -3} == ".sh" ] || ![ -h ${TARGET} ]
        then
            echo noMeElimino
        else
            echo mkdir ${ACTUALPATH}/eliminadas/
            echo `mkdir ${ACTUALPATH}/../eliminadas/`
            echo mv ${TARGET} ${ACTUALPATH}/eliminadas/${TARGET}
            echo `mv ${TARGET} ${ACTUALPATH}/../eliminadas`
        fi
    fi
done

echo finaliza el script

5- 多次执行此脚本,直到您意识到 exampleFolder 中的文件数量没有改变。

6-你需要的dylibs都在exampleFolder里面!就我而言,我有 61 个 dylib。(记得我们开始的时候我放了 4 个 dylib)

7-您需要做的最后一件事是将xCode中的“Frameworks”文件夹放入其中。之后记得转到“构建阶段”并添加“复制文件”阶段:“编辑器”=>“添加构建阶段”=>“添加复制文件构建阶段”并在“复制文件”阶段中单击加号图标并添加您在“Framewroks”文件夹中找到的所有 DYLIBS。您需要的目的地是框架。

就是这样,我或多或少是这样理解的。

于 2014-02-26T01:57:02.173 回答