如何将动态Swift框架添加到命令行工具
让我们逐步介绍如何尝试向命令行工具中添加动态框架,并讨论每步操作中出了什么问题。
步骤1:将其添加到“链接的框架和库”部分
这是您运行应用程序时发生的情况:
dyld:库未加载:@ rpath / libswiftAppKit.dylib
引用自:/Users/seanberry/Library/Developer/Xcode/DerivedData/TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv/Build/Products/Debug/ThirdParty.framework/Versions/A/ThirdParty
原因:找不到图片
ThirdParty.framework
尝试在@rpath
目录中找到libswiftAppKit.dylib
(它是Swift标准库的一部分)。
我们可以看到ThirdParty.framework
如何通过运行来定义@rpath
$ oTool -l ThirdParty.framework / Versions / Current / ThirdParty
加载命令27
指令LC_RPATH
cmdsize 48
路径@executable_path /../ Frameworks(偏移量12)
加载命令28
指令LC_RPATH
cmdsize 40
路径@ loader_path / Frameworks(偏移量12)
好吧,开枪。 这些与我们的命令行工具无关。 我们没有任何名为/ Frameworks或../Frameworks的文件夹。 为什么要在其中寻找Swift标准库?
因为它是为iOS和Mac应用程序构建的。 这是Mac应用程序中的目录结构:
那解释了path @executable_path/../Frameworks
对于iOS,应用程序内部的目录结构为:
这说明了path @loader_path/Frameworks (offset 12)
但是,谦虚的命令行工具开发人员呢? Swift标准库在我们的可执行文件中静态链接,但是我们的第三方框架找不到它们。 不幸的是,它们并没有存储在每台Mac上的标准位置。 开发人员可以访问埋在Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx
(但请不要要求用户安装Xcode)。
那么我们该怎么办? 我见过的标准做法是为您的项目创建一个自定义框架,将所有依赖项导入其中,然后也复制快速的标准库。
步骤2:创建自定义框架并复制标准Swift库
完善! 现在,让我们继续运行命令行工具…
objc [2335]:类别_TtC8Dispatch16DispatchWorkItem在/Users/seanberry/Library/Developer/Xcode/DerivedData/TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv/Build/Products/Debug/FirstParty.framework/Diss/10pWys/libs/libs/libs中和/ Users / seanberry / Library / Developer / Xcode / DerivedData / TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv / Build / Products / Debug / TestCommandLineTool(0x1005c7698)。 将使用两者之一。 哪一个未定义。
以20种不同方式重复上述错误
您的应用程序现在可以看到两个不同的Swift标准库副本:在可执行文件中静态链接的副本和在/ Frameworks文件夹中的静态链接。
从这里有两种解决方案。
步骤3(选项A):改用Mac应用并提取可执行文件
我调查了著名的命令行工具Carthage和SwiftLint,以了解它们如何处理此问题。 原来他们没有设置为命令行工具! 他们是Mac应用! 为什么? 因为Mac应用程序不是静态链接标准库。 他们通过添加一个从应用程序包中提取可执行文件的运行阶段,将自己部署为命令行工具。
#!/ bin / bash
##从其应用程序包中提取迦太基CLI工具。 打算运行
#作为Xcode运行脚本构建阶段的一部分。
cp -v“ $ {BUILT_PRODUCTS_DIR} / $ {EXECUTABLE_PATH}”“” $ {BUILT_PRODUCTS_DIR} / $ {EXECUTABLE_NAME}“
您可以继续这样做,没问题。 但是我找到了解决此问题的另一种方法。
步骤3(选项B):禁用静态链接
将它们添加到用户定义的构建设置中:
SWIFT_FORCE_DYNAMIC_LINK_STDLIB是
SWIFT_FORCE_STATIC_LINK_STDLIB否
这将强制您的可执行文件动态链接所有库。 通过将框架目录添加到“ Runpath搜索路径”,确保告诉Xcode在哪里找到它们。
@executable_path/FirstParty.framework/Versions/Current/Frameworks
祝您使用命令行工具好运!
肖恩试图让Xcode在 Livefront 上编译