Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting up a Framework on macOS Command Line apps - Reason: image not found

I have been wrestling with this for weeks now. Why does the following macOS setup give an Alamofire linker error ?

Steps to recreate linker error:

  • Create new macOS Command Line app
  • Run pod init from Terminal Update
  • Create the following podfile:

    platform :osx, ’10.10’ target 'testMacOS' do use_frameworks! pod 'Alamofire', '~> 4.0' end

Run pod install. Open and Build workspace

Error: dyld: Library not loaded: @rpath/Alamofire.framework/Versions/A/Alamofire Reason: image not found

AT THIS POINT, this error made sense. You needed to go to the Target's / General / Linked Frameworks and Libraries. Then add Alamofire. Now Alamofire was inside the workspace's Framework directory.

Build and run. Same error. Why?

like image 678
rustyMagnet Avatar asked Dec 03 '22 14:12

rustyMagnet


2 Answers

You need to set @rpath manually, Pod install frameworks at "$(ProductDirectory)/$(FrameworkName)/$(FrameworkName).framework".

For example, your Alamofire framework is located at "$(ProductDirectory)/Alamofire/Alamofire.framework". Therefore, you need to add "@executable_path/Alamofire/" into your own target's Building Settings - Runpath Search Paths.

Furthermore, "Pods Project - Alamofire(Target)" also need to specify the swift runtime dynamic library position. In my environment, I need to add "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx" into "Building Settings - Runpath Search Paths".

But for convenient, you can have a look my pod post_install code.

post_install do |installer|
    files = Dir.glob("*.xcodeproj")
    proj_file = files[0]
    app_project = Xcodeproj::Project.open(proj_file)

    app_project.native_targets.each do |target|
        target.build_configurations.each do |config|
            config.build_settings['LD_RUNPATH_SEARCH_PATHS'] = '$(inherited) @executable_path/../Frameworks @loader_path/Frameworks'
            prefix = ' @executable_path/'

            # For each pod, add the framework path to LD_RUNPATH_SEARCH_PATHS
            installer.pods_project.targets.each do |pod_target|
                config.build_settings['LD_RUNPATH_SEARCH_PATHS'] = config.build_settings['LD_RUNPATH_SEARCH_PATHS'] + prefix + pod_target.name + '/'

                pod_target.build_configurations.each do |pod_config|
#if you want embed swift stdlib into every framework, uncommend 1,2 and commend 3,4
#1
#pod_config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'YES'
#2
#pod_config.build_settings['LD_RUNPATH_SEARCH_PATHS'] = '$(inherited) @executable_path/../Frameworks @loader_path/Frameworks'

#3
pod_config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'NO'
#4
pod_config.build_settings['LD_RUNPATH_SEARCH_PATHS'] = '$(inherited) /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/'
                end
            end
        end
    end

    app_project.save
end
like image 95
Chaorders Avatar answered Dec 21 '22 05:12

Chaorders


PROBLEM: with Xcode 8.1, I did not realize that macOS Command Line apps do not support Frameworks (dynamic libraries) in the same way as iOS or desktop macOS apps do with a bundle.

SOLUTION: I got around this by taking the source code off github and compiling it inside my workspace. That worked. Importing a static library also worked.

like image 23
rustyMagnet Avatar answered Dec 21 '22 05:12

rustyMagnet