简体   繁体   English

将 RxSwift 链接到命令行工具的正确方法

[英]The right way to link RxSwift into a Command Line Tool

I'm trying to build RxSwift for a Command Line Tool but it seams to be far more difficult then with an iOS App.我正在尝试为命令行工具构建 RxSwift,但它比使用 iOS 应用程序要困难得多。

I created a new Command Line project and installed RxSwift with pod我创建了一个新的命令行项目并使用pod安装了 RxSwift

$ cat Podfile
# Podfile
use_frameworks!

target 'HelloRx' do
    pod 'RxSwift',    '~> 4.0'
end

$ pod --version
1.5.3

XCode 10.1代码 10.1

After opening the workspace (.xcworkspace) and without adding any code the project builds fine but crash on run:打开工作区 (.xcworkspace) 并且不添加任何代码后,项目构建良好但在运行时崩溃:

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. XCode 假设二进制文件可以在与二进制文件相关的Frameworks目录中找到框架。 Unfortunatelly if I look into the build directory there is no Frameworks dir, hence the error.不幸的是,如果我查看构建目录,则没有Frameworks目录,因此出现错误。

$ 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.为了使它更加混乱,所有框架都被复制到自己的Rx*目录中,而不是一个全局Frameworks目录中。

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 .现在是缺少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) (我是 XCode 和 Swift 的新手,所以也许我在做一些疯狂的事情)

One quick way could be to have all the pods frameworks as static libs.一种快速的方法是将所有 pod 框架都作为静态库。

  1. Select Pods project on the Project Navigator在 Project Navigator 上选择 Pods 项目
  2. Select the main Pods project above all the pods target在所有 pods 目标之上选择主 Pods 项目
  3. Go to Build Settings and change Mach-O Type to Static Library .转到 Build Settings 并将Mach-O Type更改为Static Library This will change all the pods to have Mach-O Type as Static Library .这会将所有 pod 更改为Mach-O Type作为Static Library (Each time you run pod install this will be changed back so you might have to do it again) (每次运行pod install都会改回来,所以你可能需要再做一次)
  4. Clean干净的

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 .如果您想使用动态框架,请遵循本教程: 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.通过使用第二种方法,您的输出将不仅仅是单个可执行文件,而且您还必须提供所有动态框架。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM