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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...