I'm trying to build RxSwift for a Command Line Tool but it seams to be far more difficult then with an iOS App.
I created a new Command Line project and installed RxSwift with pod
$ cat Podfile
# Podfile
use_frameworks!
target 'HelloRx' do
pod 'RxSwift', '~> 4.0'
end
$ pod --version
1.5.3
XCode 10.1
After opening the workspace (.xcworkspace) and without adding any code the project builds fine but crash on run:
dyld: Library not loaded: @rpath/RxAtomic.framework/Versions/A/RxAtomic
Referenced from: /Users/luke/Library/Developer/Xcode/DerivedData/HelloRx-ftbkqquhoytidfesyxazbaovndbu/Build/Products/Debug/HelloRx
Reason: image not found
Dynamic dependencies are not visible to the binary.
$ otool -l HelloRx | grep -A 2 RPATH | grep path
path @executable_path/../Frameworks (offset 12)
path @loader_path/Frameworks (offset 12)
path @executable_path/../Frameworks (offset 12)
path @loader_path/Frameworks (offset 12)
XCode assumed that the binary can find frameworks in Frameworks
directory relative to the binary. Unfortunatelly if I look into the build directory there is no Frameworks
dir, hence the error.
$ ls
HelloRx Pods_HelloRx.framework RxCocoa
HelloRx.swiftmodule RxAtomic RxSwift
$ ls ..
Debug
To make it more confusing all frameworks were copied into own Rx*
dir rather then one global Frameworks
dir.
I can fix that by adding more paths into "Build Settings" >> "Runpath Search Paths".
'@executable_path/RxAtomic'
'@executable_path/RxSwift'
I does the trick but binary still crashes.
dyld: Library not loaded: @rpath/libswiftAppKit.dylib
Referenced from: /Users/luke/Library/Developer/Xcode/DerivedData/HelloRx-ftbkqquhoytidfesyxazbaovndbu/Build/Products/Debug/RxSwift/RxSwift.framework/Versions/A/RxSwift
Reason: image not found
Now it's the RxSwift which is missing libswiftAppKit.dylib
.
This can be "fixed" by adding another Runpath path.
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx'
This finally stop crashes but my application throws lots of warnings:
objc[64025]: Class _TtCE6AppKitVSo17NSAnimationEffectP33_9E6F1C1DB126EBCC5B18B8BAC8A387CC26_CompletionHandlerDelegate is implemented in both /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftAppKit.dylib (0x101360b98) and /Users/luke/Library/Developer/Xcode/DerivedData/HelloRx-ftbkqquhoytidfesyxazbaovndbu/Build/Products/Debug/HelloRx (0x10059a250). One of the two will be used. Which one is undefined.
objc[64025]: Class _TtC8Dispatch16DispatchWorkItem is implemented in both /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftDispatch.dylib (0x101a7c6d0) and /Users/luke/Library/Developer/Xcode/DerivedData/HelloRx-ftbkqquhoytidfesyxazbaovndbu/Build/Products/Debug/HelloRx (0x10059bd28). One of the two will be used. Which one is undefined.
objc[64025]: Class _TtC10FoundationP33_45BFD3D387700B862E3A7353B97EF7ED20_CharacterSetStorage is implemented in both /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftFoundation.dylib (0x101c34f00) and /Users/luke/Library/Developer/Xcode/DerivedData/HelloRx-ftbkqquhoytidfesyxazbaovndbu/Build/Products/Debug/HelloRx (0x10059d5e8). One of the two will be used. Which one is undefined.
objc[64025]: Class _TtC10Foundation12_DataStorage is implemented in both /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftFoundation.dylib (0x101c34fa8) and /Users/luke/Library/Developer/Xcode/DerivedData/HelloRx-ftbkqquhoytidfesyxazbaovndbu/Build/Products/Debug/HelloRx (0x10059d690). One of the two will be used. Which one is undefined.
...
I can live with warnings but it's clearly not the right solution. That makes me think, what's the right way to solve this problem?
(I'm new to XCode and Swift so perhaps I'm doing something crazy)
One quick way could be to have all the pods frameworks as static libs.
Mach-O Type
to Static Library
. This will change all the pods to have Mach-O Type
as Static Library
. (Each time you run pod install
this will be changed back so you might have to do it again)The advantage of this method is that your output will be a single executable.
If you want to use dynamic frameworks follow this tutorial: https://medium.com/livefront/how-to-add-a-dynamic-swift-framework-to-a-command-line-tool-bab6426d6c31. By using this second method your output will not be just a single executable, but you will have to provide all the dynamic frameworks as well.