1. Xcode Build For ios Simulator arm64
前言
將一個老項目由Xcode11升級到Xcode12的時候,在用模擬器編譯的時候,報了一個錯誤,具體如下:
「ld: building for iOS Simulator, but linking in dylib built for iOS, file '/Users/xxxx/Work/Git/xxx/Framework/GoogleCast/GoogleCast.framework/GoogleCast' for architecture arm64」
我使用模擬器編譯的,遇到arm64的錯誤,一開始還是一頭霧水啊。於是Google和網路就上了,經過一番查找,基本定位到問題了。
原因
下面翻譯一位外國同仁的解釋:
Xcode 12實際上是Apple Silicon的墊腳石,但有了這個平台,我們將得到基於arm64的macOS,模擬器也將運行在arm64架構上,而不是目前基於Intel的x86_64架構。
Xcode通常依賴於「Run Destination」來構建它的庫/應用程序,所以當一個模擬器被選擇為「Run Destination」時,它將為可用的模擬器架構構建應用程序,當一個設備被選擇為「Run Destination」時,它將為設備支持的架構構建(arm*)。
xcodebuild,在Xcode 12+ build系統中,arm64是支持Apple Silicon的有效架構。因此,當一個模擬器被選擇為運行目標時,它可能會嘗試針對基於arm64的模擬器編譯/鏈接你的庫/應用程序。所以它在<architecture>-<os>-<sdk>-<destination>格式中給clang(++)發送了一些-target標志,如arm64-apple-ios13.0-simulator,clang試圖構建/鏈接基於arm64的模擬器,但最終在基於Intel的mac上失敗。
但xcodebuild只在發布版本中嘗試這個。因為「Build Active Architecture Only (ONLY_ACTIVE_ARCH)」構建設置通常被設置為「No」,僅用於「發布」配置。這意味著xcodebuild將嘗試為選定的運行目標構建所有庫/應用的架構變體。對於模擬器運行目標,它現在將包括x86_64和arm64,因為arm64在Xcode 12+中也是一個支持Apple Silicon的模擬器架構。
了解原因後,剩下來就是如何解決了。
解決方法
首先看一下Xcode11和Xcode12在Architecture配置這一塊的區別:
Xcode11:
Xcode11中有Valid Architectures的配置項。
Xcode12:
在Xcode12中,在Architecture配置組中,用Excluded Architectures代替了Valid Architectures,那麼Valid Architectures跑到哪裡去了,在User-Defined配置組裡面。
我們的目的是能在Xcode12的模擬器上順利編譯,那麼可按照下面的步驟修改:
1. 將Build Active Architecture Only配置的debug值改為Yes。如下圖。
2. 如果在Xcode11中有Valid Architectures的配置項,那麼請在Xcode12的User-Defined配置組裡面刪除Valid Architectures的配置項,同時在Target上面的Project裡面的User-Defined配置組裡面同樣刪除Valid Architectures的配置項,如何刪除,選中,敲擊鍵盤的delete就可以了。
3. 將Validate Workspace配置項修改一次,一定要變成黑粗體,默認值是NO,改成Yes就可以,或者再改回NO,反正得折騰一次。見下圖。(之前有一篇文章升級Xcode12.3報錯提到過這個配置,可參考一下。)
4. 配置完前三步基本就能編譯通過了,如果還是報錯,請嘗試在Excluded Architectures的debug模式下添加arm64,如下圖:
經過這幾步,基本就能順利編譯通過了,不過別忘了再用真機編譯試試哦,別再影響了真機測試。
結束語
個人感覺這個是Xcode12的一個坑了,不過如果所有的項目裡面都採用XCFramework,估計這個問題就能屏蔽掉了。
原文鏈接:https://blog.csdn.net/guoyongming925/article/details/114628455
2. PVE內核在ARM64下安裝及編譯
以下命令在linux root下進行
1.apt-getinstall gnupg2 wget –y
2.加入Proxmox 軟逗山早件包源
wget -qO -http://download.proxmox.com/debian/proxmox-ve-release-6.x.gpg | sudo apt-key add echo "deb http://download.proxmox.com/debian/pve buster pve-no-subscription " | sudotee /etc/apt/sources.list.d/buster-pvetest.list
3.apt-getupdate
4.安裝編譯環境
apt-get install build-essentialasciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzipzlib1g-dev libc6-dev subversion flex uglifyjs p7zip p7zip-full msmtp libssl-devtexinfo libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automakelibtool autopoint device-tree-compiler screen
apt-get install python3-dev python3-sphinx lintian bc bison libdw-devlibiberty-dev libnuma-dev libslang2-dev lz4 rsync libpve-common-perl dh-make docbook5-xml
若山雀是出現libncurses5-dev安裝依賴錯誤,用aptitude安裝即可解決
5. Git pve內核源碼
git clonegit://git.proxmox.com/git/pve-kernel.git
6. 修改Makefile文件
23行內容 KERNEL_ARCH=x86和之後 修改成如下圖所示:
7. 在pve-kernel/debian/rules.d文件目錄下生成文件arm64.mk,內容如下
KERNEL_BUILD_ARCH = arm64
KERNEL_HEADER_ARCH = $(KERNEL_BUILD_ARCH)
KERNEL_BUILD_IMAGE = Image
KERNEL_IMAGE_PATH =arch/$(KERNEL_BUILD_ARCH)/boot/${KERNEL_BUILD_IMAGE}
KERNEL_INSTALL_FILE = vmlinuz
8. 修改pve-kernel/debian/rules文件,將rysnc中的tools修改成source,修改結果如下圖所示
9. Make all
10.最終編譯成功後會生唯橡成四個文件包,使用dpkg -i命令安裝四個deb包,即可完成pve內核的安裝。
linux-tools-{KERNEL_VER}_arm64.deb
linux-tools-5.0-dbgsym_{KERNEL_VER}_arm64.deb
pve-headers-{KERNEL_VER}_arm64.deb
pve-kernel-{KERNEL_VER}_arm64.deb
3. 下軟體是下arm64還是x64
x64
第一、cpu配套內存訪問速度,這方面x86速度肯定更快。32位C編譯器編譯C函數時候調用使用內存棧傳遞褲磨世參數,因為內存訪問速度已經夠快,再加上cpu高速緩存,運行速度能再上一個台階。而ARM的ram是和CPU在一起的,更多考慮了功耗等問題。ram訪問速度更慢,但作為補償C程序函數的調用約定是在32位模式中用4個寄存器傳遞前4個32位參數數據,在64位模式中用8個寄存器傳遞前8個64位參數數據
第二、寄存器數量,這方面arm寄存器比x86寄存器更多,這對C程序的編譯會更友好一些
第三、關於GPU,arm晶元都是和GPU一起的,為的是減少功耗,x86要看規格和廠商,比如筆記本晶元大多帶集成GPU,而台式機可能就沒有
第四、其他類似simd指令功能使用很不一樣,相對來說arm規范很多游李,而x86的simd會更糟糕,x86的simd是16位元組對齊,而arm的simd是4位元組對齊。再比如:x86的simd整數乘法會增長數據長度,至少sse2指令集是如此的胡肢,而arm的乘法根據不同指令自己選擇。
4. M1 設備的 Xcode 編譯問題深究
在Apple發布M1晶元之前,一直使用Intel的晶元,沒有出現什麼問題。發布M1晶元後,由於兩者架構的不同(M1是arm64架構,Intel是x86_64的架構),導致很多軟體運行出現了問題。我們在M1機型中使用Xcode編譯模擬器時,可能會碰到如下報錯:
或
這些報錯,都是是由於項目中存在.a或.framework靜態庫導致的。以前,我們創建靜態庫時,會分別打包出一份針對真機(arm64)和模擬器的(x86_64),然後將這兩份合並成一個包後引入項目中進行使用。在Intel機型上,真機上使用arm64指令,模擬器(x86_64)中使用x86_64指令,所以不存在問題。但是在M1機型上,模擬器是以arm64運行的,顯然再以x86_64運行就會出現問題。
對於這類架構報錯問題,網上的資料一般會告訴你兩個解決方案:
以Rosetta模式運行Xcode。
修改Build Settings -> Excluded Architectures選項,添加Any iOS Simulator SDK選項,並設置值為arm64。圖示如下:
這兩種方案都能解決編譯問題,但是也都存在問題。
以Rosetta模式運行是M1機器上x86軟體無法運行的解決方案,它會將x86指令轉譯成ARM指令運行,這種轉譯顯然是存在性能損耗的,損耗大概在20%~30%,不到萬不得已,不推薦使用這種方案。
Excluded Architectures方案說明
修改Excluded Architectures選項也有它的問題。字面意思是排除架構的意思,我們設置在模擬器中排除arm64就能解決模擬器無法編譯arm64的問題。
這樣的設置能生效會讓人有點費解,我們知道,在intel機型上,模擬器本來就是以x86方式運行的,排除arm64毫無影響。但是在M1機型上,模擬器是以arm64方式運行的,排除了arm64反而能跑,這不是把我的智商摁在地上摩擦么?,但是蘋果就是這樣乾的,當在M1機型上,排除了模擬器的arm64架構後,模擬器還是會以arm64的方式運行,但是模擬器中的app是以x86的方式運行的,對蘋果的這個騷操作我們不得不服。圖示如下:
有時候在Excluded Architectures選項中排除了模擬器的arm64指令,依然無法編譯通過,那麼一般是項目設置和cocoapods的設置不一致導致,設置為一致後一般可以解決問題。可以通過在Podfile中添加如下內容來解決:
通過上述內容,我們知道了問題的由來,它是由於項目中存在.a或.framework,它們提供的指令集不完整導致的。Apple對於這類問題,也提供了解決方案,請由我細細道來。
以Xcode13為例,在我們創建靜態庫時,選擇真機編譯出來的包只包含arm64指令,選擇模擬器編譯出來的會同時包含arm64和x86_64指令。我看一些網上的教程,教別人將模擬器部分的arm64移除,其實大可不必。因為要支持M1機器正常跑模擬器,模擬器必須同時包含arm64和x86_64指令。
2019年的WWDC,apple提供了一種新的框架封裝格式XCFramework。簡單理解就是以前使用lipo合並不同指令集的包,現在則使用新的指令合並成XCFramework格式
打包成framework,格式如下:
打包成XCFramework後,格式如下:
從上述可以看出,XCFramework就是把兩個不同指令集的framework放入了同一個文件夾(.xcframework),並生成了一個配置文件Info.plist。這樣生成的XCFramework就可以完美的解決M1機器無法編譯模擬器的問題。
XCFramework的創建指令也很簡單:
以現在的情況,很多第三方框架,並沒有使用XCFramework,而項目中只要有一個框架沒有支持模擬器的arm64指令,那麼在M1機器上,模擬器只能以Rosetta模式運行應用,對這一塊的普遍支持估計要等M1普及以後了。
蘋果換芯,成了開發者們的噩夢?
armv6、armv7、armv7s、armv8、armv64及其i386、x86_64區別
細說iOS靜態庫和動態庫
關於Xcode11的XCFrameworks框架
5. 如何使用QEMU來編譯打包armhf/arm64的snap包
首先,你需要設置QEMU和ARM二進制以及asdebootstrap支持: sudo apt-get install debootstrap qemu-user-static qemu-system git \gcc-arm-linux-gnueabihf binfmt-support 現在,創建文件系統本身(這是為2GB圖片)和它掛載在/mnt目錄中。