【问题标题】:Build Cocoa Touch Framework with CocoaPod dependencies, don't embed使用 CocoaPod 依赖构建 Cocoa Touch 框架,不要嵌入
【发布时间】:2019-08-09 07:49:23
【问题描述】:

我有一个内置在 CocoaTouch 框架 中的 SDK。 该 SDK 使用 CocoaPods,因为它依赖于其他一些库。我使用此构建脚本构建框架:

# 1
# Set bash script to exit immediately if any commands fail.
set -e
# 2
# Setup some constants for use later on.
FRAMEWORK_NAME="MyFrameworkName"
OUTPUT_DIR="${SRCROOT}/framework/build"
# 3
# If remnants from a previous build exist, delete them.
if [ -d "${OUTPUT_DIR}" ]; then
rm -rf "${OUTPUT_DIR}"
fi
# 4
# Build the framework for device and for simulator (using
# all needed architectures).
xcodebuild -workspace "${FRAMEWORK_NAME}.xcworkspace" -scheme "${FRAMEWORK_NAME}" -configuration Release -arch arm64 -arch armv7 -arch armv7s only_active_arch=no defines_module=yes -sdk "iphoneos" -derivedDataPath "${OUTPUT_DIR}"
xcodebuild -workspace "${FRAMEWORK_NAME}.xcworkspace" -scheme "${FRAMEWORK_NAME}" -configuration Release -arch x86_64 -arch i386 only_active_arch=no defines_module=yes -sdk "iphonesimulator" -derivedDataPath "${OUTPUT_DIR}"
# 5
# Remove .framework file if exists from previous run.
if [ -d "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework" ]; then
rm -rf "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework"
fi
# 6
# Copy the device version of framework.
cp -r "${OUTPUT_DIR}/Build/Products/Release-iphoneos/${FRAMEWORK_NAME}.framework" "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework"
# 7
# Replace the framework executable within the framework with
# a new version created by merging the device and simulator
# frameworks' executables with lipo.
lipo -create -output "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${OUTPUT_DIR}/Build/Products/Release-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${OUTPUT_DIR}/Build/Products/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"
# 8
# Copy the Swift module mappings for the simulator into the
# framework. The device mappings already exist from step 6.
cp -r "${OUTPUT_DIR}/Build/Products/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule/" "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule"

这一切都很好,使用框架也不是问题。但由于此框架是使用其他依赖项构建的,例如 Alamofire 和 Firebase,因此在 MyFrameworkName.framework 中有此痕迹。

当我运行一个使用我的框架和 CocoaPods 将所需依赖项添加到项目中的应用程序时,我收到以下错误:

objc[7299]:APPMBDynamicFilterResultTimestamp 类在 /private/var/containers/Bundle/Application/9966CA12-11F5-42FE-91FF-BB7A91C07571/MyProject.app/Frameworks/MyFrameworkName.framework/MyFrameworkName (0x101b34158) 和/var/containers/Bundle/Application/9966CA12-11F5-42FE-91FF-BB7A91C07571/MyProject.app/MyProject (0x1007416e8)。将使用两者之一。哪一个是未定义的。

我将如何构建具有依赖项的框架(否则它当然不会构建),但不将任何依赖项包含在框架中?

谢谢

【问题讨论】:

  • 您是否考虑过使用Carthage 来构建您的框架?您可以将依赖项设置为 Cartfile 并根据需要添加它们
  • 不幸的是 CocoaPods 是必需品,否则我早就换了。

标签: ios swift xcode


【解决方案1】:

问题在于您在 SDK 中使用了 cocoapods 依赖项。正如您所提到的,一切正常,直到主机应用程序具有相同的依赖项。不幸的是,没有简单的方法来解决这个问题,因为相同依赖项的符号被链接到 SDK 和应用程序中。不过,您可以考虑几种方法。

  1. 如果您愿意通过 cocoapods 发布您的 SDK,那么您可以在您的 podspec 中指定依赖项。但是,在这种情况下,SDK 应该由 cocoapods 构建。例如podspec example
  2. 另一种方法是在您的 SDK 中添加一个抽象层。您应该使用Bridge pattern 来处理您的抽象。

希望对你有帮助。

【讨论】:

  • 感谢您的回答。您对第 1 点的确切含义是什么?我们计划通过 CocoaPods 提供我们的 SDK,但仅限于那些我们允许访问包含 .framework 文件的私有 repo 的人。 the SDK should be built by CocoaPods 是什么意思?没有嵌入它就没有办法构建它。如果我使用.framework,它显然是在依赖于 Foundation/UIKit/etc 时构建的。但这不会产生冲突。如果可能,我将如何实现这样的目标?
  • 我会尽量详细说明。当应用程序将 SDK 与依赖项集成时,具有相同版本的依赖项非常重要。此外,在某些情况下,它们应该使用相同的构建工具链构建。为此,您可以在应用程序构建阶段延迟构建您的 SDK。一种选择是使用 Cocoapods。在示例 podspec 中有从源代码构建 SDK 的说明。因此,在集成过程中,Cocoapods 将确保 SDK 和 App 都依赖相同的依赖项并将它们链接在一起。 Foundation/UIKit/etc 是系统框架。
  • 您的意思是在构建使用它的应用程序时,该框架将构建在用户的机器上?在这种情况下,保持源关闭/私有很重要。但我理解正确吗?
  • 是的,没错。在这种情况下,框架将在构建应用程序时构建在用户的机器上。顺便说一句,当您将 Cocoapods 与您的 SDK 集成时,您使用框架吗?
猜你喜欢
  • 2015-01-22
  • 2023-03-31
  • 2015-08-26
  • 2019-01-05
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
  • 2019-02-14
  • 2014-12-14
相关资源
最近更新 更多