Release 2.2.1: universal macOS DMG and arch install fix.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
// mklipo merges two Mach-O binaries into one macOS universal (fat) binary.
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
fatMagic = 0xCAFEBABE
|
||||
cpuTypeX86_64 = 0x01000007
|
||||
cpuTypeARM64 = 0x0100000c
|
||||
fatArchSize = 20
|
||||
)
|
||||
|
||||
type slice struct {
|
||||
cpu, sub uint32
|
||||
data []byte
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 4 {
|
||||
fmt.Fprintln(os.Stderr, "usage: mklipo <amd64-bin> <arm64-bin> <out>")
|
||||
os.Exit(2)
|
||||
}
|
||||
amd, err := os.ReadFile(os.Args[1])
|
||||
if err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
arm, err := os.ReadFile(os.Args[2])
|
||||
if err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
if err := writeFat(os.Args[3], []slice{
|
||||
{cpuTypeX86_64, 3, amd},
|
||||
{cpuTypeARM64, 0, arm},
|
||||
}); err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func writeFat(path string, parts []slice) error {
|
||||
const align uint32 = 0x4000
|
||||
hdr := 8 + fatArchSize*len(parts)
|
||||
offsets := make([]uint32, len(parts))
|
||||
cur := uint32(hdr)
|
||||
for i, p := range parts {
|
||||
pad := (align - (cur % align)) % align
|
||||
cur += pad
|
||||
offsets[i] = cur
|
||||
cur += uint32(len(p.data))
|
||||
}
|
||||
|
||||
out, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
if err := binary.Write(out, binary.BigEndian, uint32(fatMagic)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, uint32(len(parts))); err != nil {
|
||||
return err
|
||||
}
|
||||
for i, p := range parts {
|
||||
if err := binary.Write(out, binary.BigEndian, p.cpu); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, p.sub); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, offsets[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, uint32(len(p.data))); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, align); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cur = uint32(hdr)
|
||||
for _, p := range parts {
|
||||
pad := (align - (cur % align)) % align
|
||||
if pad > 0 {
|
||||
if _, err := out.Write(make([]byte, pad)); err != nil {
|
||||
return err
|
||||
}
|
||||
cur += pad
|
||||
}
|
||||
if _, err := out.Write(p.data); err != nil {
|
||||
return err
|
||||
}
|
||||
cur += uint32(len(p.data))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fatal(err error) {
|
||||
fmt.Fprintln(os.Stderr, "mklipo:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
Reference in New Issue
Block a user