iOS M1 晶元 編譯爬坑

来源:https://www.cnblogs.com/lesten/archive/2022/05/20/16293735.html
-Advertisement-
Play Games

今天我們來認識一位接觸 OpenHarmony 不到一年,便帶領團隊成功開發出一款“啟航 KP“智能開發套件的開發者——軟通動力資深項目經理許北林。 ...


主要是兩個錯誤,引起混淆。導致爬了挺久的坑。

1、 In xxxx/proj.ios_mac/xxxx.framework/xxxx(xxxx.a-arm64-master.o), building for iOS Simulator, but linking in object file built for iOS, for architecture arm64.
或者
ld: warning: ignoring file YoupPth/Build/Products/Debug-iphonesimulator/xxxx/xxxx.framework/xxxx, 
building for iOS Simulator-x86_64 but attempting to link with file built for iOS Simulator-arm64
Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_xxxx", referenced from:
      objc-class-ref in xxxx.o
ld: symbol(s) not found for architecture x86_64
    
    
2、 In xxxx/proj.ios_mac/xxxx.xcodeproj The linked framework 'Pods_xxx_iOS.framework' is missing one or more architectures required by this target: x86_64.

看起來好像是差不多,都是由於 項目中的依賴庫 提供的指令集 不完整導致的。

第一個 是說  xxxx.framework  指令集為 iOS 真機 這個庫, 不能 鏈接 為 iOS 模擬器 的 目標文件。 實際上這個問題 應該是一個相容問題,只出現在 M1 晶元的 Mac 上。 因為 M1 晶元的 Mac 本身就是 arm64 架構,它的模擬器也是 arm64 架構的。

首先有一點要明確:

我們在 intel 機型上 創建一個靜態庫文件,編譯後會生成兩個版本。一個是模擬器版, x86_64 架構(如果M1 機型上創建 那麼是 arm64 架構),一個是真機版, arm64 架構。

如果 intel 機型上 生成的靜態庫 需要 給 intel 機型上的 其他工程引入,一般操作是通過 lipo 工具合併成一個 模擬器和真機 通用的 靜態庫,以方便瀏覽器或者真機調試。

鏈接真機的時候 會把真機的指令 鏈接進 目標文件,鏈接模擬器 就把模擬器的指令鏈接進 目標文件

當鏈接的時候: 針對 一般第三方庫, 以前普遍提供的是 包含真機 arm64 指令集 和 模擬器 x86_64 指令集的 通用版本。

在 intel 機型上也就是你的Mac 打包機器為 intel 晶元,  為真機鏈接 arm64 架構 指令,為模擬器鏈接 x86_64 架構 指令沒有什麼問題。

但是 你的Mac 打包機器為 M1 晶元的時候,   為真機鏈接 arm64 架構指令,為模擬器 還是鏈接 x86_64 指令就會有問題。因為 此時 M1 機型 的模擬器架構是 arm64! 只能跑 arm64 指令。

這時候 Xcode 就會報以上類型的錯誤,而不會去為 模擬器 鏈接 該依賴庫 真機的 arm64 指令!!!

驗證很簡單,你在 M1 機型上編譯 真機的 靜態庫  鏈接到 模擬器 的可執行文件  依然不行。即使他們 都是在 arm64 架構下。

那麼如何解決這個問題? 有以下兩種方式。

1、使用 Rosetta 模式 運行Xcode, 重新編譯。

2005年, 蘋果從PowerPC 晶元切換到 因特爾,Rosetta 最初是為 PowerPC 應用轉換到 x86 上,能讓大多數 PowerPC 應用在 x86 Mac 上運行,但是會損失部分性能。 

Rosetta 模式 會使 Xcode 能夠 在鏈接 x86靜態庫 前 將其轉換為 arm64 指令。

通過 Rosetta 模式運行 Xcode, Xcode 是以 x86架構的方式運行(正常是 Apple 也就是 arm64), 靜態庫是 x86 的也能正常鏈接跑。  

在 M1 的 Mac 機型,模擬器 正常是以 arm64 運行的,模擬器 啟動 app 也是以 arm64 的方式運行。

而PC 上 Rosetta 模式啟動 Xcode 讓 App 鏈接 x86(也就是當前Xcode 運行模式)的庫,即使依賴庫既有 arm64 也有 x86 指令集。如果 依賴庫本身只有 arm64 指令集,那麼會報 未定義 符號,無法鏈接。

註意:Rosetta 的方式 雖然 足以支持大多數主流生產力應用程式,但無法相容那些需要與操作系統、硬體或圖形硬體進行直接交互的軟體。

 

2、編譯鏈接 app 工程的時候  排除 arm64 架構。 具體 在 Build Settings 里 設置 Excluded Architectures 選項,在 Debug 模式下 添加 arm64 。真機不會出現這個問題,所以 Release 不需要。

所以先 檢查工程以及子工程 編譯設置 排除 arm64 架構的編譯產物。 但是如果需要 編譯依賴庫文件 提供給第三方 使用 那麼你的生成產物又不能排除 arm64.  你可能就需要針對不同 的架構打不同的版本。下麵有更好的解決辦法。

檢查 Build Settings 裡面的 Excluded Architectures 添加  arm64。  clean 重編。 

最終跑起來  會發現  排除了 arm64 指令集後 模擬器也是以 x86 的方式啟動 App 了。 

查看 活動監視器 裡面  進程的 種類 就可以清晰的知道。 

模擬器與 模擬器啟動的 App 運行指令集不同,通過 XPC 方式進行通信,理論上沒有啥問題,但是 XPC 通信 相對同步時間比較長, 對於 時間敏感的邏輯可能會出問題。

比如 滑動手勢 或者 列表的慣性滾動。 

 

對於通過 cocoapods 維護依賴庫的方式來說, 如果手動更改後,重新  pod update 會導致又要重新修改,所以excluded Architectures  需要寫進 Podfile

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = "arm64"
    end
  end
end

 

為瞭解決 M1 晶元機型 封裝庫文件的問題, 2019年 的 WWDC 大會  Apple 提供了 XCFrameworks 的方式,這就可以理解成 新的 xcodebuild 命令替換以前  lipo 命令,將不同指令集 的庫文件合併成 通用二進位文件。

只不過 XCFrameworks 還可以包含其他第三方的庫。 這裡就不展開說 XCFrameworks 了。

 

第二個 是說 鏈接 Pods_xxxx_iOS.framework 這個framework 中 缺失了 x86_64 架構 的某個庫。

所以檢查 編譯 生成 Pods_xxxx_iOS.framework 的 所有依賴庫的工程 或者 prebuilt 的庫,是否存在 x86_64 架構。

1、針對子工程,如果 Xcode 13, 檢查工程的 User-Defined 裡面的  VALID_ARCHS 值 是否存在  x86_64,沒有則需要添加。 如果是 Xcode 12 則在  Architectures 裡面檢查 是否存在 x86_64。其他架構也是同樣

2、針對 預編譯庫, 可以使用 lipo 工具查看包含一些什麼 指令集。是否缺失 x86_64。   例如:lipo -i xxx.a

主要是 Xcode12 預設不再對 x86_64 架構 進行支持了,打通用包的時候  需要手動添加。

 

lipo 工具 可以對  庫文件的架構進行修改

nm 工具 用來現實一個 程式包的符號表

strip 用來刪除一個 程式包里的符號表

ar 工具 可以獲取 庫文件 鏈接前的  .o 文件  

libtool -static -o  xxx.a  *.o   又可以合併 *.o 文件 為 xxx.a。 或者 直接用 ld。

 

參考:

https://juejin.cn/post/7037037120158269448


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • awk linux命令_sed AWK 是一種處理文本文件的語言,是一個強大的文本分析工具。 之所以叫 AWK 是因為其取了三位創始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字元。 學習具體使用前,先來看下 aw ...
  • 本文例子參考《STM32單片機開發實例——基於Proteus虛擬模擬與HAL/LL庫》 源代碼:https://github.com/LanLinnet/STM33F103R6 項目要求 單片機每隔1s以“YYYY-MM-DD HH:MM:SS”的格式自動向串口輸出日期和時間信息(“ASCII格式” ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 一,VMware配置。 因為要裝kali,所以要用到Debian。 這裡的處理器配置要根據自己的電腦硬體決定。 查找電腦處理器信息: 控制面板——設備管理器——處理器 這裡也是看著給,有條件的多給點,沒有就預設。 如果有人真的要問,最低推薦不就可 ...
  • Issue 升級 PostgreSQL 9.1 的一個集群,由於該集群用到了 PostGIS,在升級 PostgreSQL 時也需要升級一下 PostGIS。PostGIS 相關軟體安裝好後,在 PostgreSQL 11 中創建 postgis extension 時失敗,如下: alvindb= ...
  • 一、概述 Hue是一個開源的Apache Hadoop UI系統,最早是由Cloudera Desktop演化而來,由Cloudera貢獻給開源社區,它是基於Python Web框架Django實現的。通過使用Hue我們可以在瀏覽器端的Web控制臺上與Hadoop集群進行交互來分析處理數據,例如操作 ...
  • 一、安裝mysql8.0 ##下載mysql安裝包 http://mirrors.sohu.com/mysql/MySQL-8.0/ wget http://mirrors.sohu.com/mysql/MySQL-8.0/mysql-community-client-8.0.18-1.el7.x8 ...
  • 分享嘉賓:王懷遠 阿裡雲 表格存儲架構師 編輯整理:李瑤 DataFun 出品平臺:DataFunTalk 導讀: 大家好,我是王懷遠,我2015年加入阿裡雲,一直從事表格存儲的研發和架構相關工作,目前擔任表格存儲的架構師。我在存儲和資料庫領域有一些研發和架構方面的經驗。 本次分享的主題是一站式物聯 ...
  • 一、概述 Impala 直接針對存儲在 HDFS、HBase或 Amazon Simple Storage Service (S3)中的 Apache Hadoop 數據提供快速的互動式 SQL 查詢。Impala是一個基於Hive、分散式、大規模並行處理(MPP:Massively Paralle ...
一周排行
    -Advertisement-
    Play Games
  • 什麼是工廠模式 工廠模式是最常用的設計模式之一,屬於創建型模式。 有點: 解耦,可以把對象的創建和過程分開 減少代碼量,易於維護 什麼時候用? 當一個抽象類有多個實現的時候,需要多次實例化的時候,就要考慮使用工廠模式。 比如:登錄的抽象類ILoginBusiness,它有2個實現,一個用用戶名密碼登 ...
  • 這次iNeuOS升級主要升級圖形渲染引擎和增加豐富的圖元信息,可以很快的方案應用。總共增加41個通用和行業領域的圖元應用,增加2154個圖元信息,現在iNeuOS視圖建模功能模塊總共包括5894個行業圖元信息。現在完全支持製作高保真的工藝流程和大屏展示效果。 ...
  • 效果圖先附上: 首先 這是我是參考 教程:使用 SignalR 2 和 MVC 5 實時聊天 | Microsoft Docs 先附上教程: 在“添加新項 - SignalRChat”中,選擇 InstalledVisual> C#>WebSignalR>,然後選擇 SignalR Hub 類 (v ...
  • 一、前言 項目中之前涉及到胎兒心率圖曲線的繪製,最近項目中還需要添加心電曲線和血樣曲線的繪製功能。今天就來分享一下心電曲線的繪製方式; 二、正文 1、胎兒心率曲線的繪製是通過DrawingVisual來實現的,這裡的心電曲線我也是採用差不多相同的方式來實現的,只是兩者曲線的數據有所區別。心電圖的數據 ...
  • 安裝 Redis # 首先安裝依賴gcc, 後面需要使用make編譯redis yum install gcc -y # 進入 /usr/local/src 目錄, 把源碼下載到這裡 cd /usr/local/src # 下載 redis 7.0.2 的源碼,github被牆,可以使用國內的地址 ...
  • Redis 的定義? 百度百科: Redis(Remote Dictionary Server ),即遠程字典服務,是一個開源的使用ANSI C語言編寫、支持網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。 中文官網: Redis是一個開源(BSD許可),記憶體存 ...
  • 事情的起因是收到了一位網友的請求,他的java課設需要設計實現迷宮相關的程式——如標題概括。 我這邊不方便透露相關信息,就只把任務要求寫出來。 演示視頻指路👉: 基於JavaFX圖形界面的迷宮程式演示_嗶哩嗶哩_bilibili 完整代碼鏈接🔎: 網盤:https://pan.baidu.com ...
  • Python中的字典 Python中的字典是另一種可變容器模型,且可存儲任意類型對象。鍵值使用冒號分割,你可以看成是一串json。 常用方法 獲取字典中的值 dict[key] 如果key不存在會報錯,建議使用dict.get(key),不存在返回None 修改和新建字典值 dict[key]=va ...
  • 迎面走來了你的面試官,身穿格子衫,挺著啤酒肚,髮際線嚴重後移的中年男子。 手拿泡著枸杞的保溫杯,胳膊夾著MacBook,MacBook上還貼著公司標語:“加班使我快樂”。 面試官: 看你簡歷上用過MySQL,問你幾個簡單的問題吧。什麼是聚簇索引和非聚簇索引? 這個問題難不住我啊。來之前我看一下一燈M ...
  • tunm二進位協議在python上的實現 tunm是一種對標JSON的二進位協議, 支持JSON的所有類型的動態組合 支持的數據類型 基本支持的類型 "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "varint", "float", "s ...