把 C/Object-C/C++ 程式包成 Swift Package

zonble
4 min readFeb 7, 2020

--

最近花了一點時間,把一些之前用 C/Objective-C 語言寫好的公司內部 CocoaPods,轉換成 Swift package。 — 在 Xcode 11 推出之後,其實就可以把 C/Objective-C/C++ 寫成的程式打包成 Swift package,不過最近才比較有時間做這些事情。

這些內部使用的 CocoaPods Spec 原本可以用在開發 iOS/macOS 等蘋果平台上的 GUI 應用程式,在打包成 Swift Package 之後,最立即的好處是,我要用 Swift 寫一些 command line 的內部工具的時候,也可以直接使用我以前寫好的 C/Objective-C 程式。而打包成 Swift package 之後,其實還是可以跟 CocoaPods 相容,除了用 SPM 之外,你還是可以使用 CocoaPods 安裝。

限制

把 C/Objective-C/C++ 程式打包成 Swift package 的限制如下:

  1. 在 C/Objetive-C/C++ 的 target 中,不可以混用 Swfit 語言。
  2. 就跟 SPM 原本的限制一樣,你只能夠打包程式,不能夠同時夾帶一些相關的其他檔案,像是圖片…等等。

如果你原本寫好了一個 CocoaPods library,但是是底下幾種狀況,就會讓你無法同時打包成 Swift package:

  1. 你的 CocoaPods spec 中,使用了其他還沒有轉換成 Swift package 的相依套件。
  2. 你的 CocoaPods spec 中有 subspec。CocoaPods 的 subspec 像是「你要不要把某些檔案放進某個 target 裡頭」,而 SPM 的設計是一個 package 裡頭可以有多個 target,基本的想法就不太一樣,而你想把 CocoaPods subspec 變成多個 target 的架構的時候,要怎麼參照其他的 subspecies/target 就會是個問題,而如果你就是改成多個 target,那麼你手上的這個 library 就無法與 CocoaPods 相容了。

流程

把 CocoaPods 打包成 Swift package 的流程大概是:

  1. 先到專案所在的目錄,在終端機下輸入swift package init。這個指令會幫你建立 Package.swift 檔案以及相關的目錄結構。
  2. 搬移檔案。比方說,你有一個叫做 KKBOXOpenAPI 的 Pod spec,在原本的目錄結構中,CocoaPods 預設會幫你把程式放在 ./KKBOXOpenAPI/Classes/ 底下,你就得把檔案搬到 ./Sources/KKBOXOpenAPI 底下。
  3. 注意 public headers。在 Swift 當中我們是透過 access control 決定外部可以呼叫哪些 API,但是使用 C/Objective-C/C++ 開發的 framework ,主要倚賴我們在 public headers 裡頭寫了什麼。在使用 C/Objective-C/C++ 開發 Swift package 的時候,我們需要把想暴露在外的 header 放進 include 目錄裡頭(像是./Sources/KKBOXOpenAP/include ),而在 include 目錄中,如果有一個跟整個 package 同名的 header(像是 ./Sources/KKBOXOpenAP/include/KKBOXOpenAPI.h ),這個檔案會被視作 umbrella header。
  4. 試試看能不能夠編譯。如果這個專案支援 macOS,那就直接在終端機中輸入 swift build 看看。如果是只支援 iOS/tvOS 等平台,就用 Xcode 11 ,直接把這個目錄當做 Swift package 打開,然後看看能不能夠編譯,Xcode 11 可以直接開啟目錄,你不需要用 swift package generate-xcodeproj 指令產生 Xcode 專案。
  5. 回去改你的 Podspec,把 s.source_files 這邊的設定換掉,然後用 pod lib lint 指令檢查改過的 Podspec 有沒有問題。

由於 public header 必須放在一個分別的 include 目錄中,所以打包完之後,這個目錄結構會讓人覺得有點不舒服。

--

--

zonble
zonble

Written by zonble

XDDDD - eXtreme Due Date Driven Development

No responses yet