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
  • 前言 本文將以 C# 語言來實現一個簡單的布隆過濾器,為簡化說明,設計得很簡單,僅供學習使用。 感謝@時總百忙之中的指導。 布隆過濾器簡介 布隆過濾器(Bloom filter)是一種特殊的 Hash Table,能夠以較小的存儲空間較快地判斷出數據是否存在。常用於允許一定誤判率的數據過濾及防止緩存 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • 「簡單有價值的事情長期堅持做」 這是成功最簡單,但也最難學的秘訣。不經過訓練,人很難意識到時間複利的威力。 仙劍奇俠傳的「十里坡劍神」和金庸群俠傳的「十級野球拳」,就是簡單的事情持之以恆反覆做,最後就有巨大的威力 唐家三少成為網文收入第一,最重要的一步是十四年從未斷日更 這樣的案例很多,一開始可能成 ...
  • 迎面走來了你的面試官,身穿格子衫,挺著啤酒肚,髮際線嚴重後移的中年男子。 手拿泡著枸杞的保溫杯,胳膊夾著MacBook,MacBook上還貼著公司標語:“我愛加班”。 面試開始,直入正題。 面試官: 看你簡歷上面寫著精通MySQL,我先問你事務的特性是什麼? 老生常談,這個還有誰不會背的嗎? 我: ...
  • 基礎知識 python是一門腳本語言,它是解釋執行的。 python使用縮進做為語法,而且python2環境下同一個py文件中不能同時存在tab和空格縮進,否則會出錯,建議在IDE中顯示縮進符。 python在聲明變數時不寫數據類型,可以type(xx)來獲取欄位的類型,然後可以int(),list ...
  • 為什麼要多線程下載 俗話說要以終為始,那麼我們首先要明確多線程下載的目標是什麼,不外乎是為了更快的下載文件。那麼問題來了,多線程下載文件相比於單線程是不是更快? 對於這個問題可以看下圖。 橫坐標是線程數,縱坐標是使用對應線程數下載對應文件時花費的時間,藍橙綠代表下載文件的大小,每個線程下載對應文件2 ...
  • 詳細講解python爬蟲代碼,爬微博搜索結果的博文數據。 爬取欄位: 頁碼、微博id、微博bid、微博作者、發佈時間、微博內容、轉發數、評論數、點贊數。 爬蟲技術: 1、requests 發送請求 2、datetime 時間格式轉換 3、jsonpath 快速解析json數據 4、re 正則表達式提... ...
  • 背景: 一般我們可以用HashMap做本地緩存,但是HashMap功能比較弱,不支持Key過期,不支持數據範圍查找等。故在此實現了一個簡易的本地緩存,取名叫fastmap。 功能: 1.支持數據過期 2.支持等值查找 3.支持範圍查找 4.支持key排序 實現思路: 1.等值查找採用HashMap2 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • 本章是系列文章的第八章,用著色演算法進行寄存器的分配過程。 本文中的所有內容來自學習DCC888的學習筆記或者自己理解的整理,如需轉載請註明出處。周榮華@燧原科技 寄存器分配 寄存器分配是為程式處理的值找到存儲位置的問題 這些值可以存放到寄存器,也可以存放在記憶體中 寄存器更快,但數量有限 記憶體很多,但 ...