4

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?

rustyMagnet
  • 3,479
  • 1
  • 31
  • 41

3 Answers3

12

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
Chaorders
  • 123
  • 1
  • 6
3

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.

Lukas Würzburger
  • 6,543
  • 7
  • 41
  • 75
rustyMagnet
  • 3,479
  • 1
  • 31
  • 41
2

Commandline tools do indeed "support" Frameworks, but not in the way Application bundles do. You need to put the referenced frameworks in the @rpath which in practice is ~/Library/Frameworks/ or /Library/Frameworks/

Joe Daniels
  • 1,646
  • 1
  • 11
  • 9