我正在尝试在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文件夹中?
答案 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。您需要的目的地是框架。
就是这样,我或多或少地这样做了。