Flutter是如何轉換成iOS應用程序包的?

本文翻譯自:Flutter’s iOS Application Bundle

本文檔描述了Flutter的構建系統如何將您的Flutter項目(及其資產)轉換爲iOS應用程序包。我但願能描述清楚一些構建步驟,並解釋生成相應產物的目的(PS:這裏的產物我以爲能夠理解爲構建時生成的一些中間文件或者最終生成的可執行文件等),這樣您就能夠將相同的過程集成到你本身的構建環境中。ios

關於工做流程的注意事項:在構建要發佈的應用程序時,您可能會使用Flutter工具,這會使構建過程容易一些。可是,一些開發人員可能會發現這個過程不是可配置的,或者不適合他們自定義的構建持續集成(CI)配置。c++

若是您有自定義的Xcode構建或Gradle設置,那麼Flutter工具添加的全部「魔法」功能都是可選的,您能夠配置構建方式以適應您本身的工做流程。git

本文檔中的全部信息均適用於準備發佈到App Store的iOS應用程序包。也就是說項目構建的是Flutter的發佈模式。Debug或者Prifile的編譯方式使用了不一樣的運行時和打包模式,以便於支持熱重載(Hot Reload)和監控(observatory)。github

Flutter應用程序將用戶界面渲染爲原生視圖樹(圖層)中的單個視圖。以下 json

iOS

應用程序包

使用flutter build ios --release 命令(或者使用Flutter IDE如Android Studio)建立的應用程序與典型的iOS應用程序包很是類似,後者包含了應用程序可執行文件及其引用的框架和資源。緩存

Flutter生成的Runner.app包結構:bash

Runner.app
├── AppFrameworkInfo.plist
├── Assets.car
├── Base.lproj
│   ├── LaunchScreen.storyboardc
│   └── Main.storyboardc
├── Debug.xcconfig
├── Frameworks
│   ├── App.framework            # See 「App framework bundle」
│   │   ├── App
│   │   ├── Info.plist
│   └── Flutter.framework        # See 「Flutter framework bundle」
│       ├── Flutter
│       ├── Info.plist
│       └── icudtl.dat
├── Info.plist
├── Runner
└── flutter_assets
├── AssetManifest.json
├── FontManifest.json
├── LICENSE
├── fonts
└── packages
└── cupertino_icons
└── assets
└── CupertinoIcons.ttf
複製代碼

編譯應用程序

在編譯應用程序的發佈版本(而不是Profile或debug版本)時,須要來自構建程序和主機的產品。(有關構建機器人(構建引擎的一部分,使用GN和Ninja)的更多信息,請參見《爲Flutter引擎作貢獻》。)微信

當您安裝SDK時,Flutter工具將緩存在您的機器上。您能夠在你的Flutter SDK副本中的bin/cache目錄中看到它們。若是您決定將此過程的任何步驟集成到您本身的構建系統中,那麼該文件夾包含處理Flutter所需的全部版本化工具。網絡

如下部分描述了Flutter的iOS應用程序包特有的一些文件。架構

Flutter 引擎框架包

Flutter.framework 文件夾是被打包成iOS框架的包,包含

  • Flutter 引擎 包含核心庫(例如,圖形、文件和網絡I/O、可訪問性支持、插件架構)、DartVM和Skia渲染引擎。
  • Flutter引擎引用的資源文件集(assets) 目前這只是ICU的數據。

構建機器人生成Flutter引擎框架包,而後Flutter工具下載並緩存到您的機器上。

AOT框架包

App.framework 包含用戶編寫的全部Dart應用程序代碼的AOT快照以及 armv7aarch64 格式的Flutter框架和插件的Dart代碼。

在版本構建過程當中,編譯器對Dart代碼執行精簡,所以只有實際使用的代碼纔會出如今bundle中。設備上緩存的gen_snapshot工具生成建立App.framework包所需的組件。

AOT 快照

AOT快照包含了由Dart向設備相關編譯而成的靜態碼。gen_snapshot 生成的快照庫包含四個主要符號。這些符號能夠由nm命令解包,如:

$ nm -gU Runner.app/Frameworks/App.framework/App
Runner.app/Frameworks/App.framework/App (for architecture armv7):
003c6f60 S _kDartIsolateSnapshotData
00007000 T _kDartIsolateSnapshotInstructions
003c16a0 S _kDartVmSnapshotData
00004000 T _kDartVmSnapshotInstructions
Runner.app/Frameworks/App.framework/App (for architecture arm64):
00000000004041a0 S _kDartIsolateSnapshotData
0000000000009000 T _kDartIsolateSnapshotInstructions
00000000003fc740 S _kDartVmSnapshotData
0000000000005000 T _kDartVmSnapshotInstructions
複製代碼

其目的以下:

  • Dart VM快照(kDartVmSnapshotData): 表示孤立體之間共享的Dart堆的初始狀態。這有助於更快地啓動Dart isolates,但不包含任何特定於分離的信息。但不包含任何特定isolates的信息。

  • Dart VM指令(kDartVmSnapshotInstructions): 包含VM中全部Dart隔離器之間共享的通用例程的AOT指令。這個快照一般很是小,而且主要包含存根。

  • 隔離快照(kDartIsolateSnapshotData): 表示Dart堆的初始狀態,幷包含特定於隔離的信息。

  • 分離指令(kDartIsolateSnapshotInstructions): 包含Dart分離器執行的AOT代碼。

調用gen_snapshot很簡單。您將其指向Dart源代碼,它將爲這四個符號中的每個輸出一點東西。而後,Xcode將這些符號打包成一個iOS framework,就像用C、c++、Objective-C或Swift編寫的框架同樣。瞭解更多關於如何在Flutter engine 中配置快照和引擎請查看: Flutter engine wiki

除了大量的代碼以外,Flutter工具還確保應用程序(及其插件)引用的資產最終位於應用程序包中。它經過閱讀項目的pubspec.yaml文件中列出的資產來實現這一點。

關於安卓

構建Android APK包(使用`flutter build apk - release 命令或IDE)的過程會生成如下文件結構:

$ Runner.apk.unzipped
├── AndroidManifest.xml
├── assets
│   ├── flutter_assets
│   │   ├── fonts
│   │   │   └── MaterialIcons-Regular.ttf
│   │   └── packages
│   │       └── cupertino_icons
│   │           └── assets
│   │               └── CupertinoIcons.ttf
│   ├── icudtl.dat
│   ├── isolate_snapshot_data
│   ├── isolate_snapshot_instr
│   ├── vm_snapshot_data
│   └── vm_snapshot_instr
├── classes.dex
├── lib
│   └── armeabi-v7a
│       └── libflutter.so
├── output.json
├── res
└── resources.arsc
複製代碼

它與iOS發佈包基本相同,除了:

  • Flutter引擎被打包爲ELF庫(libflutter.so)。
  • 上一節中詳細介紹的4個符號如今只是assets目錄中的二進制blob。

第二點可能有點出乎意料,須要解釋一下:構建發行版APK並不須要下載NDK。這是由於,在機器上沒有NDK時,Flutter工具會將blob添加爲資產。在Android上,Flutter引擎能夠將頁面標記爲可執行文件。所以,當它檢測到AOT資產被打包爲二進制blob時,它將這些blob映射到內存中,並將相應的頁面標記爲可執行文件。若是您能夠訪問機器上的NDK,那麼您能夠指定它的位置,並使用這些符號生成一個動態庫。在這種狀況下,Flutter引擎使用動態庫中的4個符號。

總結

構建iOS應用程序包的關鍵在於:

  • 您能夠在原生視圖層次結構的任何位置放置Flutter視圖。Flutter呈現的全部內容都將被合成到這個視圖中。

  • Dart代碼被編譯成原生機器碼,並像其餘c++ /Objective/Swift庫同樣打包成庫或框架包。這意味着全部崩潰報告和符號化工具對Dart AOT代碼的工做方式是相同的。

  • 您能夠將Flutter集成到您本身的定製構建系統中,而不依賴於開發機器上的Flutter工具(儘管使用它會使您的工做更輕鬆)。全部這些工具均可以在Flutter SDK的bin/cache目錄中找到。


筆者和朋友作了淘寶優惠券公衆號,購物領券省錢,幫忙關注一下。

微信公衆號
相關文章
相關標籤/搜索