gpt4 book ai didi

ios - 如何修复我的构建:具有CocoaPods依赖项和2个目标(iOS和tvOS)的.framework文件

转载 作者:行者123 更新时间:2023-11-29 05:16:10 24 4
gpt4 key购买 nike

我有一个要求稍微复杂的项目,所以让我们从期望的目标开始:


该项目是用于与我们的后端服务(不是应用程序)接口的SDK。
项目必须输出可以包含在Xamarin应用程序中的.framework文件(我们所有内部应用程序都是使用Xamarin构建的)
该项目必须是带有.podspec文件的正确CocoaPod,以便第三方可以将SDK包含在自己的应用中(客户要求)
该项目依赖于三个第三方依赖关系,其中一个与另一个依赖关系的交付方式有所不同:


CocoaLumberjack和JSONModel在Podfile.podspec中作为依赖项列出时,将下载它们各自的项目并将它们作为子项目包含在您自己的工作空间中,以进行构建
当GoogleInterativeMediaAds作为Podfile.podspec中的依赖项列出时,它将下载.framework文件,并且是完全封闭源代码

该项目必须能够同时为iOS和tvOS构建(我们同时具有应用和客户端)


请注意,尽管JSONModel和CocoaLumberjack都宣称它们支持iOS和tvOS,但GoogleInteractiveMediaAds分别有CocoaPods(GoogleAds-IMA-iOS-SDK ~> 3.9GoogleAds-IMA-tvOS-SDK ~> 4.0

项目输出的任何.framework文件都必须包含嵌入的位码,并且必须是胖二进制文件
该项目有几个静态资产(PNG文件和XIB文件),需要作为.bundle包含在.framework


那么,现在:我已经完成了所有这些工作。这花费了很长时间,并且进行了大量实验,但是我有一个满足上述所有要求的项目。我的Podfile看起来像这样:

播客文件

use_frameworks!

def common()
pod 'CocoaLumberjack', '~> 3.5'
pod 'JSONModel', '~> 1.8'
end

target 'MyFramework-iOS' do
platform :ios, '9.0'
common()
pod 'GoogleAds-IMA-iOS-SDK', '~> 3.9'
end

target 'MyFramework-tvOS' do
platform :tvos, '9.1'
common()
pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.0'
end


我的 .podspec看起来像这样:

MyFramework.podspec

Pod::Spec.new do |spec|
spec.name = "MyFramework"
spec.version = "1.0.0"
spec.summary = "A framework for interfacing with our back-end"

spec.description = <<-DESC
A longer description
DESC

spec.homepage = "https://example.com/"
spec.license = "MIT"

spec.authors = {
"Steven Barnett" => "xxx@example.com"
}

spec.ios.deployment_target = "9.0"
spec.tvos.deployment_target = "9.1"

spec.source = { :git => "https://bitbucket.org/xxx/MyFramework.git", :tag => "#{spec.version}" }

spec.source_files = "Sources/Common/**/*.{h,m}", "Sources/MyFramework.h"
spec.ios.source_files = "Sources/iOS/**/*.{h,m}"
spec.tvos.source_files = "Sources/tvOS/**/*.{h,m}"

spec.ios.resource_bundles = {
"MyFramework" => ["Assets.xcassets", "Sources/iOS/**/*.{xib}"]
}
spec.tvos.resource_bundles = {
"MyFramework" => ["Assets.xcassets", "Sources/tvOS/**/*.{xib}"]
}

spec.frameworks = "Foundation", "UIKit", "AVKit"

spec.requires_arc = true

spec.dependency "CocoaLumberjack", "~> 3.5"
spec.dependency "JSONModel", "~> 1.8"
spec.ios.dependency "GoogleAds-IMA-iOS-SDK", "~> 3.9"
spec.tvos.dependency "GoogleAds-IMA-tvOS-SDK", "~> 4.0"
end


我的源代码分为三个文件夹:


./Sources/Common包含我们99%的代码,在iOS和tvOS中很常见
./Sources/iOS包含仅在iOS上可用的少数功能。具体来说,iOS在自定义视频播放器的布局方面提供了更大的灵活性,因此我们拥有自定义控件
./Sources/tvOS包含一些仅在tvOS上可用的功能。具体来说,是用于播放器控件的XIB和 .m文件的配对集合


在项目的“构建阶段”中,我添加了一个带有以下脚本的 Run Script阶段:

运行脚本

UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal

if [ "true" == ${ALREADYINVOKED:-false} ]; then
echo "RECURSION: Detected, stopping"
else
export ALREADYINVOKED="true"

# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"

# Step "0". Build our project twice
echo "Building for AppleTV Device (redundantly... sigh)"
xcodebuild -workspace "${PROJECT_DIR}/${PROJECT}.xcworkspace" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk appletvos ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" OBJROOT="${OBJROOT}/DependentBuilds" OTHER_CFLAGS="-fembed-bitcode"

echo "Building for AppleTV Simulator"
xcodebuild -workspace "${PROJECT_DIR}/${PROJECT}.xcworkspace" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk appletvsimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" OBJROOT="${OBJROOT}/DependentBuilds" OTHER_CFLAGS="-fembed-bitcode"

# Step 1. Copy the framework structure (from iphoneos build) to the universal folder
echo "Copying to output folder"
cp -R "${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}" "${UNIVERSAL_OUTPUTFOLDER}/"

# Step 2. Create universal binary file using lipo and place the combined executable in the copied framework directory
echo "Combining executables"
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-appletvsimulator/${EXECUTABLE_PATH}" "${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}"

# Step 3. Create universal binaries for embedded frameworks
for FRAMEWORK in $( find "${TARGET_BUILD_DIR}" -type d -name "*.framework" ); do
FRAMEWORK_PATH="${FRAMEWORK##$TARGET_BUILD_DIR}"
BINARY_NAME="${FRAMEWORK##*/}"
BINARY_NAME="${BINARY_NAME%.*}"
# I don't know how to do "if not" in Bash. Sue me.
if [[ $BINARY_NAME == Pods_* ]] || [[ $BINARY_NAME == $TARGET_NAME ]]; then
echo "Skipping framework: $FRAMEWORK_PATH"
else
echo "Creating fat binary for framework: $FRAMEWORK_PATH"
cp -r "${FRAMEWORK}" "${UNIVERSAL_OUTPUTFOLDER}/"
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${BINARY_NAME}.framework/${BINARY_NAME}" "${BUILD_DIR}/${CONFIGURATION}-appletvsimulator/${FRAMEWORK_PATH}/${BINARY_NAME}" "${TARGET_BUILD_DIR}/${FRAMEWORK_PATH}/${BINARY_NAME}"
fi
done

# Step 4. Manually copy some files to the output dir
cp -r "${SOURCE_ROOT}/Pods/GoogleAds-IMA-tvOS-SDK/GoogleInteractiveMediaAds.framework" "${UNIVERSAL_OUTPUTFOLDER}"
cp "${SOURCE_ROOT}/generate-xamarin-bindings.py" "${UNIVERSAL_OUTPUTFOLDER}"

# Step 5. Convenience step
open "${UNIVERSAL_OUTPUTFOLDER}"
fi


该脚本是我在网上找到的类似脚本的修改。它基本上执行以下操作:


为嵌入了位码的设备(ARM处理器)构建我的项目
用嵌入的位代码为模拟器(x86处理器)构建我的项目
使用lipo为我的项目创建一个胖二进制文件
反复使用lipo为我依赖的所有框架创建胖二进制文件
将我的框架和所有我依赖的框架复制到“通用”输出目录中


您可能还会注意到 generate-xamarin-bindings.py文件。就我的目的而言,这几乎可以忽略。它仅使用 Objective Sharpie来自动创建Xamarin绑定,然后使用JSONModel修复了一些已知的错误(定义为 @property (retain, nonatomic, nullable) NSString <Optional> *test;的变量将以 Optional test { get; set; }而不是 string test { get; set; }的形式引入绑定中)

除此之外,我不记得必须对所有脚本,构建设置和配置文件进行哪些其他配置和调整-但是如果出现任何问题,我可以查看代码并予以回答。

我有一个使用CocoaPods插入我的SDK的测试项目,如下所示:

例子/ tvOS / Podfile

use_frameworks!
platform :tvos, '9.1'

target 'MyFramework Example tvOS App' do
pod 'MyFramework', :path => '../../'
end


这个测试项目构建完美,我可以在模拟器或真实设备上运行它。几周前,我还能够将测试项目部署到Apple Store(TestFlight),但是从那时起,我进行了一些更改(包括从标准构建转换为胖二进制文件),因此我不确定仍然有效(我将对此进行测试)

此外,当我们进行性能分析并创建Xamarin绑定时,我们可以将所有四个框架( MyFramework.frameworkCocoaLumberjack.frameworkJSONModel.frameworkGoogleInteractiveMediaAds.framework)嵌入到我们的Xamarin应用程序中,它们将在两个模拟器和真实设备上。

我们遇到的问题是当我们试图将这些基于Xamarin的应用程序之一推到Apple Store(TestFlight)时。我们收到了11个错误:


错误ITMS-90166:“缺少代码签名权利。在捆绑包'com.xxx.MyFramework'中找不到可执行文件'Payload / InternalApp.app / Frameworks / MyFramework-tvOS.framework / MyFramework.bundle / MyFramework'的权利。”
错误ITMS-90668:“可执行文件无效。可执行文件'InternalApp.app/Frameworks/MyFramework-tvOS.framework/MyFramework-tvOS”包含不完整的位代码。要编译具有完整位代码的二进制文件,请打开Xcode并在“产品”菜单中选择“存档”。 ”
错误ITMS-90668:“可执行文件无效。可执行文件'InternalApp.app/Frameworks/CocoaLumberjack.framework/CocoaLumberjack'包含不完整的位代码。要编译具有完整位代码的二进制文件,请打开Xcode并在“产品”菜单中选择“存档”。
错误ITMS-90668:“可执行的捆绑包无效。可执行文件'InternalApp.app/Frameworks/JSONModel.framework/JSONModel'包含不完整的位代码。要编译具有完整位代码的二进制文件,请打开Xcode并在“产品”菜单中选择“存档”。
错误ITMS-90635:“无效的Mach-O格式。捆绑软件“ InternalApp.app/Frameworks/CocoaLumberjack.framework”中的Mach-O与主捆绑软件中的Mach-O不一致。主捆绑软件Mach-O包含“ arm64(位代码),而嵌套捆绑包Mach-O包含arm64(机器代码)。请验证平台的所有目标的ENABLE_BITCODE构建设置值是否一致。”
错误ITMS-90635:“无效的Mach-O格式。捆绑软件“ InternalApp.app/Frameworks/MyFramework-tvOS.framework”中的Mach-O与主捆绑软件中的Mach-O不一致。主捆绑软件Mach- “ O包含arm64(位代码),而嵌套包Mach-O包含arm64(机器代码)。请验证平台的所有目标的ENABLE_BITCODE构建设置值是否一致。”
错误ITMS-90635:“无效的Mach-O格式。捆绑软件“ InternalApp.app/Frameworks/JSONModel.framework”中的Mach-O与主捆绑软件中的Mach-O不一致。主捆绑软件Mach-O包含“ arm64(位代码),而嵌套捆绑包Mach-O包含arm64(机器代码)。请验证平台的所有目标的ENABLE_BITCODE构建设置值是否一致。”
错误ITMS-90171:“无效的捆绑包结构-不允许二进制文件'InternalApp.app/Frameworks/MyFramework-tvOS.framework/MyFramework.bundle/MyFramework”。您的应用程序不能包含独立的可执行文件或库,有效的CFBundleExecutable受支持的捆绑包。有关tvOS应用捆绑包结构的信息,请参考 https://developer.apple.com/go/?id=bundle-structure捆绑包编程指南。”
错误ITMS-90209:“无效的段对齐。'InternalApp.app/ Frameworks / MyFramework-tvOS.framework / MyFramework-tvOS'上的应用程序二进制文件没有正确的段对齐。尝试使用最新的Xcode版本重建应用程序。”
错误ITMS-90209:“无效的段对齐。位于'InternalApp.app/Frameworks/CocoaLumberjack.framework/CocoaLumberjack'的应用程序二进制文件没有正确的段对齐。尝试使用最新的Xcode版本重建应用程序。
错误ITMS-90209:“无效的段对齐。'InternalApp.app/ Frameworks / JSONModel.framework / JSONModel'上的应用程序二进制文件没有正确的段对齐。尝试使用最新的Xcode版本重建应用。”


因此,我开始尝试手动跟踪构建过程,以找出问题出在哪里或出了什么问题。我已经在使用最新的Xcode,并且我们都尝试了 Product > ArchiveProduct > Build For > Profiling,所以我认为ITMS-90668或ITMS-90209的建议解决方案并不准确。

在手动查看构建过程时,我注意到一些奇怪的事情:


当我构建应用程序的tvOS版本时,在 ~/Library/Developer/Xcode/DerivedData/MyFramework-xxxxxx/Build/Products(此后称为 ${BUILD_ROOT})中,正在构建依赖项的iOS和tvOS版本:


${BUILD_ROOT}/Release-appletvos/JSONModel-iOS.framework
${BUILD_ROOT}/Release-appletvos/JSONModel-tvOS.framework
${BUILD_ROOT}/Release-appletvsimulator/JSONModel-iOS.framework
${BUILD_ROOT}/Release-appletvsimulator/JSONModel-tvOS.framework
等(与CocoaLumberjack相同)

果然,如果我查看 ${BUILD_ROOT}/Release-universal/MyFramework-tvOS.framework/MyFramework.bundle的内容,里面会有一个名为 MyFramework的可执行文件。我不知道是谁,什么来创建此可执行文件,它来自何处或为什么将其包含在我的捆绑软件中。在任何构建阶段都没有引用它,但这似乎是ITMS-90171的原因
GoogleInteractiveMediaAds框架是唯一一个未启用位码的框架,这使我怀疑将位图提交到商店不是必需的,因为它也是唯一不会引发任何错误的框架(尽管之前被告知您需要包含位码)


我想做的事情听起来并不那么困难。我只是在创建一个库(如CocoaLumberjack),该库可以在iOS或tvOS(如CocoaLumberjack)上运行,但具有依赖项(与CocoaLumberjack不同),可以作为 .framework文件而不是CocoaPod(不确定CocoaLumberjack是否有这个?)。但是我找不到我遇到的问题的任何答案,也找不到某些奇怪的构建行为的解释。

特别:


为什么可执行文件显示在我的 .bundle中?
当我尝试构建我的tvOS版本时,为什么要构建依赖框架的iOS版本?
我需要位码吗?还是应该禁用它?


更新资料


Google Interactive Media Ads框架确实具有位码,只是没有 __LLVM
从我的 .bundle中删除​​二进制文件将ITMS-90171替换为一个新错误(我忘记了ITMS-X代码),该错误有关Info.plist引用的CFBundleExecutable不存在。删除此二进制文件也可以处理ITMS-90166
通过转到资源包的目标并选择“ Info”,我可以删除“ Executable file”键以删除输出Info.plist中的这一行,但是它并不能解决最初创建的可执行文件。当手动删除二进制文件时,它DID可以防止新错误


因此,通过修改Info.plist并删除该可执行文件(现在手动进行,因为我不知道它是由什么生成的),这11个错误中的2个消失了,剩下3个错误的3个实例(共9个):


可可伐木工人(ITMS-90668,ITMS-90635和ITMS-90209)
JSONModel(ITMS-90668,ITMS-90635和ITMS-90209)
MyFramework(ITMS-90668,ITMS-90635和ITMS-90209)


更新2


在我的xcodebuild命令中添加 BITCODE_GENERATION_MODE=bitcode标志似乎可以改善情况。我的输出二进制文件从1.2 MB增至3.4 MB(大概包含“完整”位码)。但是,发生了一些奇怪的事情。代替了ITMS-90668的三个实例,针对单个框架的所有三个错误(ITMS-90668,ITMS-90635和ITMS-90209)都消失了:JSONModel


我现在看到6个错误(CocoaLumberjack和MyFramework各自抛出3个错误)。但是我无法理解如何或为什么修复了JSONModel,而其他问题没有解决

另一个附录:当我添加了位码生成模式标志时,我开始在捆绑包中收到可执行文件的链接器错误(该链接不应该存在,并且我仍然不知道它是由什么创建的)。我注意到 OTHER_CFLAGS被传递给clang的每个调用,而不仅仅是相关的调用,所以我删除了 OTHER_CFLAGS="-fembed-bitcode",这解决了链接器错误

最后一个附录:我注意到,当我不使用运行脚本来生成胖二进制文件时,只会构建依赖项的 *-tvOS版本。我的运行脚本正在构建 *-iOS版本。这似乎对我从Apple Store看到的错误没有影响,但是它减慢了我的构建速度,创建了额外的文件,并发出了有关隐式依赖性检测找到两个候选对象的警告。我不知道该如何解决。

更新3

我已经解决了我的问题之一!

因此,出现在我的软件包中的奇怪二进制文件是由于 VERSIONING_SYSTEM构建设置默认为 apple-generic造成的。苹果通用版本控制系统创建一个名为 <ProjectName>_vers.c的源文件,对其进行编译,然后将该文件与某些库链接(我猜是系统库吗?)

当我使用 OTHER_CFLAGS="-fembed-bitcode"时,正是此文件引起了链接器错误,因为此二进制文件设置了不兼容的 -bundle。通过将版本控制系统设置为 None,我可以带回该标志而没有任何链接程序错误!

我刚刚编译并尝试再次推送到Apple Store,这次一切正常!

摘要


要修复ITMS-90166和ITMS-90171,我必须将任何资源捆绑包目标的 Versioning System设置为 None
修复此问题之后,必须确保资源束的info.plist不包含 Executable File键(如果存在,请删除它)
要修复ITMS-90668,ITMS-90635和ITMS-90209,我必须将标志 BITCODE_GENERATION_MODE=bitcodeENABLE_BITCODE=YES添加到我的 xcodebuild命令中(以及现有的 OTHER_CFLAGS="-fembed-bitcode"


经历了所有这些之后,我的构建系统仍然有一个奇怪的怪癖,但是它只会引发警告(而不是错误),我可以在短期内忍受它。这是事实,它在我运行xcodebuild时正在构建依赖关系的iOS版本,而不仅仅是构建tvOS版本。

最佳答案

我不知道这个问题/答案对偶然发现它的其他人有多大用处,因为我有大量的问题和非常具体的设置。但我想继续发布,确实为我的问题找到了解决方案。

首先,我需要设置ENABLE_BITCODE=YESBITCODE_GENERATION_MODE=bitcode标志。但是,设置这两个标志会阻止我的代码因链接器错误而生成。造成此错误的原因是我的资源捆绑目标使用的是Apple通用版本控制-资源捆绑不支持

通过将Versioning System构建设置设置为“无”,它修复了所有问题

关于ios - 如何修复我的构建:具有CocoaPods依赖项和2个目标(iOS和tvOS)的.framework文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59164395/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com