iOS app with framework crashed on device, dyld: Library not loaded, Xcode 6 Beta

后端 未结 30 3030
鱼传尺愫
鱼传尺愫 2020-11-22 10:08

This crash has been a blocking issue I used the following steps to reproduce the issue:

  • Create a Cocoa Touch Framework project
  • Add a swift file and a
30条回答
  •  攒了一身酷
    2020-11-22 10:39

    It is a runtime error that is caused by Dynamic Linker

    dyld: Library not loaded: @rpath/...
    ...
    Reason: image not found
    

    The error Library not loaded with @rpath indicates that Dynamic Linker cannot find the binary.

    1. Check if the dynamic framework was added to General -> Embedded Binaries

    2. 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

    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
    

    @executable_path

    @executable_path - relative to entry binary - Framework2 example
    use case: embed a Dynamic framework into an application

    //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 is an owner of this binary
    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

    @rpath is a compound concept that relies on outer(Application) and nested(Dynamic framework) parts:

    • Application:

      • Runpath Search Paths(LD_RUNPATH_SEARCH_PATHS) - defines a list of templates which be substituted with @rpath.
         @executable_path/../Frameworks
        
      • Review Build Phases -> Embed Frameworks -> Destination, Subpath to be shire where exactly the embed framework is located
    • Dynamic Framework:

      • Dynamic Library Install Name(LD_DYLIB_INSTALL_NAME) - point that @rpath is used together with local bundle path to a binary
        @rpath/Framework2.framework/subfolder1
        
    //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]

提交回复
热议问题