iOS如何基于CocoaPods依赖构建可静态嵌入的静态框架
我正在尝试构建一个依赖geopackage-ios CocoaPods依赖的框架,目标是将该框架静态嵌入到一个或多个App中,无需宿主App额外配置依赖。
此前已有同类问题的讨论,但我未找到适配自身场景的解决方案,以下是我已尝试的三种实现路径及对应问题:
方案一:手动Xcode构建静态库
该方案思路是通过Xcode创建静态库,添加CocoaPods依赖后完成构建,但核心问题是产出的框架未内嵌CocoaPods依赖。
- 在Xcode中新建Swift语言的iOS静态库项目(操作路径:File > New > Project… > iOS: Static Library),命名为
MyLibrary。 - 在项目根目录创建
Podfile,内容如下:
target 'MyLibrary' do pod 'geopackage-ios', '~> 7.2.1' end
- 执行
pod install命令,该操作会安装geopackage-ios及其依赖的共10个关联pod。 - 打开生成的
MyLibrary.xcworkspace,在MyLibrary分组下新建BridgingHeader.h桥接头文件,内容如下:
#ifndef BridgingHeader_h #define BridgingHeader_h #import "geopackage-ios-Bridging-Header.h" #endif
- 在项目导航栏选中
MyLibrary项目,选择MyLibrary目标,在Build Settings配置页中将MyLibrary/BridgingHeader.h设置为"Objective-C Bridging Header"路径,完成桥接头文件关联。 - 修改
MyLibrary.swift文件,调用GeoPackage依赖能力,代码如下:
public class MyLibrary { public init() {} public func test() { let manager = GPKGGeoPackageFactory.manager()! print("Manager:", manager) } }
- 按下
Cmd + B,针对iOS模拟器编译该静态库。 - 参考公开的静态框架制作shell脚本流程:分别针对模拟器、真机编译库文件,再通过
lipo命令合并产物生成通用框架。
方案一遇到的问题
将静态库(搭配MyLibrary.swiftmodule)或通用框架嵌入App时,App会出现链接失败问题,报错信息如下:
Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_GPKGGeoPackageManager", referenced from: objc-class-ref in libMyLibrary.a(MyLibrary.o) "_OBJC_CLASS_$_GPKGGeoPackageFactory", referenced from: objc-class-ref in libMyLibrary.a(MyLibrary.o) ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
我也尝试将MyLibrary编译目录下的geopackage_ios.framework添加到App中,选择Embed & Sign嵌入选项,此时App可编译成功,但启动时会发生崩溃,报错信息如下:
dyld[79209]: Library not loaded: @rpath/ogc_api_features_json_ios.framework/ogc_api_features_json_ios Referenced from: /Users/admin1/Library/Developer/CoreSimulator/Devices/C3D61224-CFE8-45CC-951B-7B6AB54BC8B3/data/Containers/Bundle/Application/D41A82D6-4E69-4BB6-AC59-6BC28AE58795/TestApp.app/Frameworks/geopackage_ios.framework/geopackage_ios
如果将全部11个关联pod框架都添加到App中可以解决该问题,但这违背了我想要避免宿主App额外配置依赖的初衷。
方案二:使用PodBuilder预编译
第二种方案是使用PodBuilder工具,该工具专门用于自动化完成此类预编译构建任务,但实际使用时出现构建错误,暂未定位到根因。
- 新建Xcode项目,这次创建名为
MyApp的iOS Swift应用项目。 - 创建
Podfile,内容与之前基本一致:
use_frameworks! target 'MyApp' do pod 'geopackage-ios', '~> 7.2.1' end
- 执行
pod install。 - 安装PodBuilder,初始化空Git仓库(PodBuilder的强制要求),完成PodBuilder初始化后启动构建任务,执行命令如下:
sudo gem install pod-builder git init pod_builder init pod_builder build geopackage-ios
- 构建失败,
/tmp/pod_builder/pod_builder.err日志中记录的错误信息如下:
Undefined symbols for architecture arm64: "_PROJ_WEB_MERCATOR_MAX_LAT_RANGE", referenced from: +[GPKGTileBoundingBoxUtils toWebMercatorWithBoundingBox:] in GPKGTileBoundingBoxUtils.o +[GPKGTileBoundingBoxUtils boundDegreesBoundingBoxWithWebMercatorLimits:] in GPKGTileBoundingBoxUtils.o -[GPKGTileDao isXYZTiles] in GPKGTileDao.o -[GPKGTileGenerator adjustXYZBounds] in GPKGTileGenerator.o "_PROJ_UNDEFINED_CARTESIAN", referenced from: -[GPKGSpatialReferenceSystemDao createIfNeededWithSrs:andOrganization:andCoordsysId:] in GPKGSpatialReferenceSystemDao.o "_PROJ_AUTHORITY_NONE", referenced from: -[GPKGSpatialReferenceSystemDao createIfNeededWithSrs:andOrganization:andCoordsysId:] in GPKGSpatialReferenceSystemDao.o […]
- 初步判断是
geopackage-iospod自身的问题,可通过克隆自定义版本仓库修复:
cd .. git clone --branch 7.2.1 https://github.com/ngageoint/geopackage-ios.git
- 进入仓库目录安装依赖:
cd geopackage-ios pod install
- 手动拷贝
proj-ios源码文件:
cp -r Pods/proj-ios/proj-ios geopackage-ios
- 打开
geopackage-ios.xcodeproj,将proj-ios文件添加到项目内的geopackage-ios分组中完成引用。 - 修改CocoaPods配置,使用本地自定义版本的pod:
use_frameworks! target 'MyApp' do pod 'geopackage-ios', :path => '../geopackage-ios' end
- 回到MyApp目录,重新初始化PodBuilder:
cd ../MyApp pod_builder deintegrate pod deintegrate pod install pod_builder init
- 编辑
./PodBuilder/PodBuilder.json文件,配置允许PodBuilder使用本地开发pod:
{ …, "allow_building_development_pods": true, … }
- 重新执行构建命令:
pod_builder build geopackage-ios
方案二遇到的问题
本次构建出现了新的错误,报错信息如下:
The following build commands failed: CompileC /tmp/pod_builder/build/Pods.build/Release-iphoneos/sf-proj-ios.build/Objects-normal/arm64/SFPGeometryTransform.o /tmp/pod_builder/Pods/sf-proj-ios/sf-proj-ios/SFPGeometryTransform.m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target 'sf-proj-ios' from project 'Pods') (1 failure)
SFPGeometryTransform.m文件本身代码逻辑无明显问题。
方案三:使用cocoapods-rome插件
第三种方案是使用cocoapods-rome插件。
- 安装Rome插件:
sudo gem install cocoapods-rome
- 清理之前PodBuilder相关的配置:
pod_builder deintegrate pod deintegrate
- 修改
Podfile配置:
use_frameworks! platform :ios, '13.0' plugin 'cocoapods-rome', { :pre_compile => Proc.new { |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.0' end end installer.pods_project.save }, dsym: false, configuration: 'Release' } target 'MyApp' do pod 'geopackage-ios', :path => '../geopackage-ios' end
- 执行
pod install安装依赖。
方案三遇到的问题
该方案出现了与PodBuilder完全一致的构建错误。
编辑补充:经排查发现错误原因是
SFPGeometryTransform.m中导入的PROJProjectionTransform.h头文件无法找到,但我认为上述三种方案都不是最优实现路径,希望能得到排错建议,或是其他可行的实现思路。
内容的提问来源于stack exchange,提问作者goofy4224

