登录
  • 人们都希望被别人需要 却往往事与愿违
  • 我的管理风格既不是美国的个人主义, 也不是日本的共识主义, 而是独特的达尔文主义(适者生存)!@比尔.盖茨

在Linux下使用lipo创建 universal macOS binary

编程 Benny小土豆 3062次浏览 2400字 0个评论
文章目录[显示]
这篇文章在 2022年09月16日23:20:04 更新了哦~

macOS的应用程序可以同时包含多种架构,最常见的是包含arm64和amd64这两种。操作系统会自动选择执行最合适的架构,避免使用rosetta 2.

在Linux下使用lipo创建 universal macOS binary

创建universal binary

在macOS中,自带一个工具 lipo,可以用来合并、提取、显示这种universal binary的信息。

比如我想创建一个universal binary,可以这样做

# lipo -create -output universal amd64 arm64
# file universal
universal: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64Mach-O 64-bit executable x86_64] [arm64]
universal (for architecture x86_64): Mach-O 64-bit executable x86_64
universal (for architecture arm64): Mach-O 64-bit executable arm64

可以把某个架构的binary提取出来,-extract

# lipo -extract x86_64 -output amd universal
# file amd
amd: Mach-O universal binary with 1 architecture: [x86_64:Mach-O 64-bit executable x86_64Mach-O 64-bit executable x86_64]
amd (for architecture x86_64): Mach-O 64-bit executable x86_64

也可以用来显示binary的一些信息

> $ lipo -detailed_info universal
Fat header in: universal
fat_magic 0xcafebabe
nfat_arch 2
architecture x86_64
    cputype CPU_TYPE_X86_64
    cpusubtype CPU_SUBTYPE_X86_64_ALL
    capabilities 0x0
    offset 4096
    size 1181264
    align 2^12 (4096)
architecture arm64
    cputype CPU_TYPE_ARM64
    cpusubtype CPU_SUBTYPE_ARM64_ALL
    capabilities 0x0
    offset 1196032
    size 1190706
    align 2^14 (16384)

Linux下创建universal binary替代品

可惜Linux上竟然没有对应的lipo。对于那些用Go写的应用程序,天生就支持交叉编译,那为了在release发布一个universal binary,还得自己合并,或者GitHub Actions跑一个macOS?也不是不行,就是太麻烦啦!

但是不怕,universal binary的技术细节是公开的,并且Apple开源了lipo对应的代码,可以看cctools. 非常幸运的是还有一个人给port到了Linux,https://github.com/tpoechtrager/cctools-port

那么为了在Linux下创建这样的universal binary,要么就去读技术细节,参考官方的C语言实践,自己用其他语言写一个;要么就直接用现成的cctools-port,编译一个lipo,直接用即可。

Linux-lipo

我比较菜,大概读不懂那些难度很高的文档,还得看十六进制,因此我选择直接用官方的代码。

于是我就做了一个docker image,只要传递过来参数,就可以创建universal binary

比如我写了这样的简单的Go代码,打印出运行时的架构

package main

import "runtime"

func main() {
	// print architecture info
	println("Architecture:", runtime.GOARCH)
}

然后编译两个不同架构的binary

GOOS=darwin GOARCH=amd64 go build -o amd64 .
GOOS=darwin GOARCH=arm64 go build -o arm64 .

> $ file amd64 arm64
amd64: Mach-O 64-bit executable x86_64
arm64: Mach-O 64-bit executable arm64

然后就可以这样创建出来universal binary

docker run --rm -v $(pwd):/app/ bennythink/lipo-linux -create -output universal amd64 arm64

或者extract啊什么的都行的。只要你想,甚至可以把这个docker image里的lipo提取出来用,问题不大。

 

也许可以……

如果你的Mac的存储空间严重不足,也许可以考虑把那些fat binary给瘦身一下。毕竟两个架构,体积翻倍。framework之类的也可以瘦身,就看能不能找到。比如说word的话……可以考虑瘦身一下这个文件,80M变40M🤣

Microsoft Word.app/Contents/MacOS/Microsoft Word

效果还是有的,70%左右吧😂
在Linux下使用lipo创建 universal macOS binary

参考资料

A deep dive on macOS universal binaries

https://www.jviotti.com/2021/07/23/a-deep-dive-on-macos-universal-binaries.html

Building a Universal macOS Binary

https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary

 


文章版权归原作者所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明原作者和本文原始地址:
https://dmesg.app/linux-lipo.html
喜欢 (13)
分享:-)
关于作者:
If you have any further questions, feel free to contact me in English or Chinese.
发表我的评论(代码和日志请使用Pastebin或Gist)
取消评论

                     

去你妹的实名制!

  • 昵称 (必填)
  • 邮箱 (必填,不要邮件提醒可以随便写)
  • 网址 (选填)