XCode中的动态库

时间:2009-12-02 11:22:55

标签: cocoa xcode dylib

我正在尝试在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.如何在目标信息中输入有意义的相对路径 - > ... - >安装目录设置,和 2.如何让XCode自动将dylib'target'复制到相对位置的应用程序包目标的bundle文件夹中?

3 个答案:

答案 0 :(得分:6)

最后。找到了一些official documentation。它可以完全在XCode中完成。

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

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

简单。自动的。

答案 1 :(得分:1)

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

应用程序正在寻找文件系统中的一个点,但它只在未在应用程序包中找到它之后执行此操作。您需要使用otool命令在编译后修改二进制文件(使用构建脚本)。

您会在之前提出的问题中找到答案: How Do I Create a Dynamic Library in Xcode

祝你好运。

答案 2 :(得分:0)

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

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系统内的dylibs。你不需要在项目中复制它们。

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

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

@executable_path/../Frameworks/nameOFTheDylib.dylib

(注意两点非常重要!)

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

Y终于这样做了:

a)改变路径:

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

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

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

(在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可以被写保护。

此时您应该更改所有dylib路径。您可以使用以下命令在某些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-你需要的dylib都是exampleFolder里面的所有dylib!就我而言,我得到了61个dylib。 (记得当我们开始时我放置了4个dylibs)

7-您需要做的最后一件事是在xCode中删除“Frameworks”文件夹。在此之后记住“建立阶段”并添加“复制文件”阶段:“编辑器”=&gt;“添加构建阶段”=&gt; “添加复制文件构建阶段”并在“复制文件”中逐步点击加载图标并添加您在“Framewroks”文件夹中找到的所有DYLIBS。您需要的目的地是框架。

就是这样,我或多或少地这样做了。