kil*_*anc 7 xcode cocoa objective-c sbjson
我正在处理XCode的奇怪行为:
dyld: Library not loaded: /Library/Frameworks/SBJson.framework/Versions/A/SBJson
Run Code Online (Sandbox Code Playgroud)
基本上它忽略了实际的my Runpath Search Path(LD_RUNPATH_SEARCH_PATHS)配置@loader_path/../Frameworks.
我暂时无法加载任何嵌入式框架:/
otool 说
otool -L /Users/kilian/Library/Developer/Xcode/DerivedData/r-ghohkslxtxgpnuepmblogfjtuefx/Build/Products/Debug/r.app/Contents/MacOS/r
/Users/kilian/Library/Developer/Xcode/DerivedData/r-ghohkslxtxgpnuepmblogfjtuefx/Build/Products/Debug/r.app/Contents/MacOS/r:
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 19.0.0)
/Library/Frameworks/SBJson.framework/Versions/A/SBJson (compatibility version 1.0.0, current version 37.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 945.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1186.0.0)
Run Code Online (Sandbox Code Playgroud)
PS如果您想知道我是否将副本添加到框架构建阶段,答案是肯定的.
BJ *_*mer 19
问题是,在构建时SBJSON.framework,安装名称未配置为使用@rpath.因此,当您的应用程序加载动态库时,它会查找/Library/Frameworks而不是应用程序的运行路径告诉它的位置.
要修复它,您需要更改SBJSON.framework目标上的构建设置.将动态库安装名称设置更改为@rpath/${EXECUTABLE_PATH}.然后再次构建,链接新建的框架,你很高兴.
框架的核心是动态库.这意味着库中包含的代码不会嵌入到您的应用程序中,而是在运行时从SBJSON.framework包中提取.为此,您的应用需要知道在哪里查找动态库.
这种方式的工作方式是,当您链接到框架时,链接器实际上并没有将整个库嵌入到您的应用程序中.相反,它只是添加了一个小部分,告诉应用程序在运行时在哪里找到库.当然,这意味着编译器必须知道库在运行时的位置.它通过查看动态库的"安装名称"来查找信息.
动态库的"安装名称"基本上只是库预期的路径.从历史上看,大多数动态库和框架都是在系统范围内共享的.比如像Foundation.framework和CoreData.framework,例如,住/System/Library/Frameworks,和所有的应用程序可以合理地期望在那里找到他们.因此,在CoreData.framework构建时,其安装名称设置为/System/Library/Frameworks/....当Xcode将您的应用与Core Data链接时,它会查看框架的安装名称,并告诉它在应用程序启动时加载到该路径的框架中.
这一切都很好,但是当你需要在你的应用程序中嵌入一个框架时,它并没有帮助你.您不知道应用程序在运行时在系统中的位置.用户可以从中运行它/Applications,但也可以从中运行它~/Downloads.您无法提供单个路径作为安装名称,该名称始终在运行时始终正确指向框架.
要处理此问题,您可以将框架的安装名称设置为@loader_path/../Frameworks.当动态加载程序看到时@loader_path,它会将其替换为当前加载的应用程序的路径.使用此安装名称将允许框架安装在Frameworks任何应用程序的文件夹中.
然而,事情仍然不完美.该框架仍在决定应该放置的位置.例如,如果另一个应用程序想要将框架放在Libraries文件夹中,那就不幸了.该框架负责放置它的位置,而不是应用程序.这是依赖树的反转,并不理想.该应用程序应该能够加载从哪里框架它要藏匿它,不管是什么其他框架做.
因此,在OS X 10.5 @rpath中引入了.如果dylib或框架的安装名称以...开头@rpath,则加载器将转向并询问应用程序它的"Runpath搜索路径"是什么,并替换它们.这允许应用程序指定其框架将存在的位置.通过使用@rpath,框架将决策委托给应用程序.应用程序可以根据需要使用@loader_path,也可以根据需要指定绝对路径.它甚至可以指定一整套应用程序将使用的共享文件夹.
所以,关于你的问题.您正确设置应用程序的运行路径搜索路径@loader_path/../Frameworks.但是,框架的安装名称未使用@rpath; 事实上,它仍然使用硬编码路径/Library/Frameworks/....由于框架的安装名称不使用@rpath,因此甚至不会查看应用程序的运行路径.它只是尝试从/Library文件夹中链接SBJSON .由于它不在那里,你的应用程序甚至在启动之前就崩溃了.
您需要更改要使用的SBJSON框架的安装名称@rpath.将动态库安装名称设置为@rpath/${EXECUTABLE_PATH}.(${EXECUTABLE_PATH}是包含框架的文件夹中内部动态库的相对路径.)
一旦你用新的安装名称构建了框架,你应该能够链接到新的框架,确保它被复制到app bundle的Frameworks/文件夹中,你很高兴!
PS如果不是很清楚的话,Mike Ash对@rpath朋友们做了很好的评论.你可以在这里找到它.