简体   繁体   English

iOS:如何基于 CocoaPods 依赖构建静态框架?

[英]iOS: How to build a static framework based on CocoaPods dependencies?

I am trying to build a framework that makes use of the geopackage-ios CocoaPods dependency.我正在尝试构建一个使用geopackage-ios CocoaPods 依赖项的框架。 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.在这种方法中,我将使用 Xcode 创建一个静态库,向其中添加 CocoaPods 依赖项并构建它。 The problem with this approach, however, is that the resulting framework will not have the CocoaPods dependencies embedded into it.然而,这种方法的问题是生成的框架不会嵌入 CocoaPods 依赖项。

  1. Create a new static library from Xcode ( File > New > Project… > iOS: Static Library ) named "MyLibrary" with language Swift.从 Xcode(文件 > 新建 > 项目... > iOS:静态库)创建一个名为“MyLibrary”的新静态库,语言为 Swift。
  2. Create a Podfile in the project root directory with the following content:在项目根目录下创建一个Podfile ,内容如下:
target 'MyLibrary' do
    pod 'geopackage-ios', '~> 7.2.1'
end
  1. Run pod install .运行pod install (This will install the geopackage-ios pod and 10 depending pods.) (这将安装geopackage-ios pod 和 10 个依赖的 pod。)
  2. Open the newly created MyLibrary.xcworkspace and add a BridgingHeader.h to the "MyLibrary" group having the following content:打开新创建的MyLibrary.xcworkspace并将BridgingHeader.h添加到具有以下内容的“MyLibrary”组:
#ifndef BridgingHeader_h
#define BridgingHeader_h

#import "geopackage-ios-Bridging-Header.h"

#endif
  1. Reference the bridging header by clicking on the "MyLibrary" project in the project navigator, selecting the "MyLibrary" target and, in the Build Settings , specifying MyLibrary/BridgingHeader.h as the "Objective-C Bridging Header".通过单击项目导航器中的“MyLibrary”项目,选择“MyLibrary”目标,并在Build Settings中将MyLibrary/BridgingHeader.h指定为“Objective-C Bridging Header”来引用桥接头。
  2. Modify MyLibrary.swift to use the GeoPackage dependency:修改MyLibrary.swift以使用 GeoPackage 依赖项:
public class MyLibrary {
    public init() {}
    
    public func test() {
        let manager = GPKGGeoPackageFactory.manager()!
        print("Manager:", manager)
    }
}
  1. Build the library for the iOS simulator by pressing Cmd + B .Cmd + B为 iOS 模拟器构建库。
  2. Optionally, create a static framework using a shell script like the one in this article (which will compile the library once for the simulator and once for physical devices and then combine the two results to a universal framework using the lipo command).或者,使用本文中的 shell 脚本创建一个静态框架(该脚本将为模拟器编译一次库,为物理设备编译一次库,然后使用lipo命令将这两个结果组合到一个通用框架)。

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:当我将静态库(连同MyLibrary.swiftmodule )或通用框架嵌入到应用程序中时,此应用程序的链接将失败:

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.我还可以将geopackage_ios.framework (位于“MyLibrary”的构建文件夹中)添加到应用程序(确保选择嵌入和签名嵌入选项),这将允许成功构建应用程序。 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.可以通过将所有 11 个 pod 框架添加到应用程序来解决此问题,但是,这是我试图避免的。

Second Approach: Using PodBuilder第二种方法:使用 PodBuilder

A second approach would be to use PodBuilder , which aims at automating this particular kind of build task.第二种方法是使用PodBuilder ,它旨在自动化这种特定类型的构建任务。 This approach, however, fails with a build error, the cause of which I can't quite make out.然而,这种方法因构建错误而失败,我无法完全确定其原因。

  1. Again, I would start out with a new Xcode project.同样,我将从一个新的 Xcode 项目开始。 This time, I'd create an iOS Swift app named "MyApp".这一次,我将创建一个名为“MyApp”的 iOS Swift 应用程序。
  2. I would create a Podfile with almost the same content as above:我会创建一个与上面内容几乎相同的Podfile
use_frameworks!
target 'MyApp' do
    pod 'geopackage-ios', '~> 7.2.1'
end
  1. Then, I'd run pod install .然后,我会运行pod install
  2. Next, I would install PodBuilder, create an empty Git repository (which PodBuilder requires for some reason), initialize PodBuilder, and start the build task:接下来,我将安装 PodBuilder,创建一个空的 Git 存储库(PodBuilder 出于某种原因需要它),初始化 PodBuilder,然后开始构建任务:
sudo gem install pod-builder
git init
pod_builder init
pod_builder build geopackage-ios
  1. The build will fail, however, with errors like these written to /tmp/pod_builder/pod_builder.err :但是,构建将失败,并将以下错误写入/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
  […]
  1. This seems to be a problem with the geopackage-ios pod itself, which can be fixed by cloning our own version of the repo …这似乎是geopackage-ios pod 本身的问题,可以通过克隆我们自己的 repo 版本来解决……
cd ..
git clone --branch 7.2.1 https://github.com/ngageoint/geopackage-ios.git
  1. …, installing the pods … …,安装吊舱…
cd geopackage-ios
pod install
  1. … manually copying the proj-ios source files … … 手动复制proj-ios源文件 …
cp -r Pods/proj-ios/proj-ios geopackage-ios
  1. …, and opening the geopackage-ios.xcodeproj to reference the proj-ios files in the geopackage-ios group inside that project. ...,并打开geopackage-ios.xcodeproj以引用该项目内geopackage-ios组中的proj-ios文件。

  2. Then telling CocoaPods to use our local version of the pod …然后告诉 CocoaPods 使用我们本地版本的 pod……

use_frameworks!
target 'MyApp' do
    pod 'geopackage-ios', :path => '../geopackage-ios'
end
  1. …, reinitializing PodBuilder … …,重新初始化 PodBuilder …
cd ../MyApp
pod_builder deintegrate
pod deintegrate
pod install
pod_builder init
  1. … and allowing PodBuilder to use local pods by editing the ./PodBuilder/PodBuilder.json file: ... 并允许 PodBuilder 通过编辑./PodBuilder/PodBuilder.json文件来使用本地 pod:
{
  …,
  "allow_building_development_pods": true,
  …
}
  1. Then, one can try to rebuild:然后,可以尝试重建:
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.然而, SFPGeometryTransform.m文件看起来不错。

The full build log is available here .完整的构建日志可在此处获得。

Third Approach: Using Rome第三种方法:使用罗马

The third approach would be to use cocoapods-rome .第三种方法是使用cocoapods-rome

  1. To use it, one would install Rome …要使用它,需要安装 Rome……
sudo gem install cocoapods-rome
  1. …, get rid of the PodBuilder stuff … …,摆脱 PodBuilder 的东西…
pod_builder deintegrate
pod deintegrate
  1. …, quickly adjust the Podfile : ...,快速调整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
  1. … and install the pods: …并安装吊舱:
pod install

This, however, will fail with the exact same error as PodBuilder.但是,这将失败,并出现与 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.) (编辑:似乎找不到导入到SFPGeometryTransform.mPROJProjectionTransform.h文件。无论如何,我认为这些方法并不方便。因此,非常感谢任何帮助。)

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 ).通过简单地将pod 安装中的所有聚合源文件输入到一个新的静态库中,然后使用lipo命令从中生成一个胖二进制文件或从中创建一个 Xcode 框架来解决该问题(如此所述)。 The compiled framework could then be used to create another framework built on top of it.然后可以使用编译的框架来创建另一个构建在它之上的框架。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何修复我的构建:带有 CocoaPods 依赖项和 2 个目标(iOS 和 tvOS)的 .framework 文件 - How to fix my build: .framework file with CocoaPods dependencies and 2 targets (iOS and tvOS) iOS - 如何在使用 cocoapods 的开发过程中管理框架的依赖关系? - iOS - How to manage dependencies of a framework during it's development using cocoapods? 如何使用弱链接 CocoaPods 库构建 iOS 框架 - How to build an iOS framework with weak-linked CocoaPods libraries 如何在Xcode 6中构建静态ios框架? - How to build static ios framework in xcode 6? 如何从iOS中的静态库构建框架? - How to build Framework from Static library in iOS? iOS - 使用其他框架依赖项构建静态框架 - iOS - Building a static framework with other framework dependencies 如何使用Cocoapods基于两个静态库制作动态框架(Swift) - How to make a dynamic framework(Swift) based on two static libraries using Cocoapods unity build iOS framework add failed due to a CocoaPods 安装失败 - Unity build iOS framework addition failed due to a CocoaPods installation failure 具有 CocoaPods 依赖项的 Cocoa Touch 框架 - Cocoa Touch Framework with CocoaPods dependencies 框架目标,App目标和cocoaPods一起工作,如何维护依赖项 - Framework target, App target and cocoaPods working together, how to maintain dependencies
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM