I am trying to build a framework that makes use of the geopackage-ios
CocoaPods dependency. I would then like to statically embed this framework into one or more apps.
Similar questions have been asked before, but I couldn't find a solution to my problem. Here's what I've been trying so far:
First Approach: Building Manually
In this approach, I would create a static library using Xcode, add the CocoaPods dependencies to it and build it. The problem with this approach, however, is that the resulting framework will not have the CocoaPods dependencies embedded into it.
Podfile
in the project root directory with the following content:target 'MyLibrary' do
pod 'geopackage-ios', '~> 7.2.1'
end
pod install
. (This will install the geopackage-ios
pod and 10 depending pods.)MyLibrary.xcworkspace
and add a BridgingHeader.h
to the "MyLibrary" group having the following content:#ifndef BridgingHeader_h
#define BridgingHeader_h
#import "geopackage-ios-Bridging-Header.h"
#endif
MyLibrary/BridgingHeader.h
as the "Objective-C Bridging Header".MyLibrary.swift
to use the GeoPackage dependency:public class MyLibrary {
public init() {}
public func test() {
let manager = GPKGGeoPackageFactory.manager()!
print("Manager:", manager)
}
}
Cmd + B
.lipo
command).When I embed either the static library (along with the MyLibrary.swiftmodule
) or the universal framework into an app, linking will fail for this 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)
I could also add the geopackage_ios.framework
(found in the build folder of "MyLibrary") to the app (making sure to choose the Embed & Sign embedding option), which will allow the app to be built successfully. Then, however, the app will crash upon launch:
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
One might be able to fix this by adding all eleven pod frameworks to the app, which, however, is what I'm trying to avoid.
Second Approach: Using PodBuilder
A second approach would be to use PodBuilder
, which aims at automating this particular kind of build task. This approach, however, fails with a build error, the cause of which I can't quite make out.
Podfile
with almost the same content as above:use_frameworks!
target 'MyApp' do
pod 'geopackage-ios', '~> 7.2.1'
end
pod install
.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-ios
pod itself, which can be fixed by cloning our own version of the repo …cd ..
git clone --branch 7.2.1 https://github.com/ngageoint/geopackage-ios.git
cd geopackage-ios
pod install
proj-ios
source files …cp -r Pods/proj-ios/proj-ios geopackage-ios
…, and opening the geopackage-ios.xcodeproj
to reference the proj-ios
files in the geopackage-ios
group inside that project.
Then telling CocoaPods to use our local version of the pod …
use_frameworks!
target 'MyApp' do
pod 'geopackage-ios', :path => '../geopackage-ios'
end
cd ../MyApp
pod_builder deintegrate
pod deintegrate
pod install
pod_builder init
./PodBuilder/PodBuilder.json
file:{
…,
"allow_building_development_pods": true,
…
}
pod_builder build geopackage-ios
This time, the build will fail with a different error:
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)
The SFPGeometryTransform.m
file, however, looks fine.
The full build log is available here.
Third Approach: Using Rome
The third approach would be to use cocoapods-rome
.
sudo gem install cocoapods-rome
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
This, however, will fail with the exact same error as PodBuilder.
Can anyone give me some advice on any of these approaches? Or does anyone perhaps have a whole different idea on how to build such a framework?
(EDIT: It seems like the PROJProjectionTransform.h
file imported to SFPGeometryTransform.m
cannot be found. Anyway, I don't think these approaches are expedient. So any help is highly appreciated.)
Solved the problem by simply feeding all the aggregated source files from the pod installation into a new static library, then using either the lipo command to make a fat binary out of it or creating an Xcode framework from it (as described here). The compiled framework could then be used to create another framework built on top of it.