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目录中。