It is a runtime error that is caused by Dynamic Linker
dyld: Library not loaded: @rpath/<some_path>
Referenced from: <some_path>
Reason: image not found
The error Library not loaded
with @rpath
indicates that Dynamic Linker
cannot find the binary.
Check if the dynamic framework was added to the front target General -> Frameworks, Libraries, and Embedded Content (Embedded Binaries)
. It is very simple to drag-and-drop a framework to project with Copy items if needed
[About] and miss to add the framework as implicit dependency in
Frameworks, Libraries, and Embedded Content
(or check in Add to targets
). In this case during compile time Xcode build it as success but when you run it you get runtime error
Check the @rpath
setup between consumer(application) and producer(dynamic framework):
- Dynamic framework:
Build Settings -> Dynamic Library Install Name
- Application:
Build Settings -> Runpath Search Paths
Build Phases -> Embed Frameworks -> Destination, Subpath
- Framework's
Mach-O file
[About] - Dynamic Library and Application's Frameworks, Libraries, and Embedded Content
[About] - Do Not Embed.
Dynamic linker
Dynamic Library Install Name(LD_DYLIB_INSTALL_NAME)
which is used by loadable bundle
(Dynamic framework
as a derivative) where dyld
come into play
Dynamic Library Install Name
- path to binary file(not .framework). Yes, they have the same name, but MyFramework.framework
is a packaged bundle
with MyFramework
binary file and resources inside.
This path to directory can be absolute or relative(e.g. @executable_path
, @loader_path
, @rpath
). Relative path is more preferable because it is changed together with an anchor that is useful when you distribute your bundle as a single directory
absolute path - Framework1 example
//Framework1 Dynamic Library Install Name
/some_path/Framework1.framework/subfolder1
Relative path
allows you to define a path in a dynamic way.
@executable_path
@executable_path - relative to executable binary which loads framework
use case: Dynamic framework
inside Application
(application binary path
is @executable_path) or more complex example with App Extension
[About] which is a part of Containing App
with Dynamic Framework
inside. There 2 @executable_path
for Application
target (application binary path is @executable_path) and for App Extension
target(App Extension binary path is @executable_path)) - Framework2 example
//Application bundle(`.app` package) absolute path
/some_path/Application.аpp
//Application binary absolute path
/some_path/Application.аpp/subfolder1
//Framework2 binary absolute path
/some_path/Application.аpp/Frameworks/Framework2.framework/subfolder1
//Framework2 @executable_path == Application binary absolute path <-
/some_path/Application.аpp/subfolder1
//Framework2 Dynamic Library Install Name
@executable_path/../Frameworks/Framework2.framework/subfolder1
//Framework2 binary resolved absolute path by dyld
/some_path/Application.аpp/subfolder1/../Frameworks/Framework2.framework/subfolder1
/some_path/Application.аpp/Frameworks/Framework2.framework/subfolder1
@loader_path
@loader_path - relative to bundle which causes framework to be loaded. If it is an application than it will be the same as @executable_path
use case: framework with embedded framework - Framework3_1 with Framework3_2 inside
//Framework3_1 binary absolute path
/some_path/Application.аpp/Frameworks/Framework3_1.framework/subfolder1
//Framework3_2 binary absolute path
/some_path/Application.аpp/Frameworks/Framework3_1.framework/Frameworks/Framework3_2.framework/subfolder1
//Framework3_1 @executable_path == Application binary absolute path <-
/some_path/Application.аpp/subfolder1
//Framework3_1 @loader_path == Framework3_1 @executable_path <-
/some_path/Application.аpp/subfolder1
//Framework3_2 @executable_path == Application binary absolute path <-
/some_path/Application.аpp/subfolder1
//Framework3_2 @loader_path == Framework3_1 binary absolute path <-
/some_path/Application.аpp/Frameworks/Framework3_1.framework/subfolder1
//Framework3_2 Dynamic Library Install Name
@loader_path/../Frameworks/Framework3_2.framework/subfolder1
//Framework3_2 binary resolved absolute path by dyld
/some_path/Application.аpp/Frameworks/Framework3_1.framework/subfolder1/../Frameworks/Framework3_2.framework/subfolder1
/some_path/Application.аpp/Frameworks/Framework3_1.framework/Frameworks/Framework3_2.framework/subfolder1
@rpath - Runpath Search Path
Framework2 example
Previously we had to setup a Framework to work with dyld. It is not convenient because the same Framework can not be used with a different configurations. Since this setup is made on Framework target side it is not possible to configure the same framework for different consumers(applications)
@rpath
is a compound concept that relies on outer(Application) and nested(Dynamic framework) parts:
Application:
Runpath Search Paths(LD_RUNPATH_SEARCH_PATHS)
- @rpath
- defines a list of templates which will be substituted with @rpath
. Consumer uses @rpath
word to point on this list
@executable_path/../Frameworks
Review Build Phases -> Embed Frameworks -> Destination, Subpath
to be sure where exactly the embed framework is located
Dynamic Framework:
//Application Runpath Search Paths
@executable_path/../Frameworks
//Framework2 Dynamic Library Install Name
@rpath/Framework2.framework/subfolder1
//Framework2 binary resolved absolute path by dyld
//Framework2 @rpath is replaced by each element of Application Runpath Search Paths
@executable_path/../Frameworks/Framework2.framework/subfolder1
/some_path/Application.аpp/Frameworks/Framework2.framework/subfolder1
*../
- go to the parent of the current directory
otool
- object file displaying tool
//-L print shared libraries used
//Application otool -L
@rpath/Framework2.framework/subfolder1/Framework2
//Framework2 otool -L
@rpath/Framework2.framework/subfolder1/Framework2
//-l print the load commands
//Application otool -l
LC_LOAD_DYLIB
@rpath/Framework2.framework/subfolder1/Framework2
LC_RPATH
@executable_path/../Frameworks
//Framework2 otool -l
LC_ID_DYLIB
@rpath/Framework2.framework/subfolder1/Framework2
install_name_tool
change dynamic shared library install names using -rpath
CocoaPods
uses use_frameworks!
[About] to regulate a Dynamic Linker
[Vocabulary]
[Java ClassLoader]
Link Binary with Libraries
and somehow Xcode knows to copy them into your app bundle, whereas for custom frameworks this simply doesn't happen. – fatuhoku