Universal Binaryの調査

2012/05/13

Mac OS Xの必要システム条件

10.7 Lion 2011/7/20 Intel Core 2 Duo、Core i3、Core i5、Core i7、またはXeonプロセッサを搭載したMac
10.6 Snow Leopard 2009/8/28 Intelプロセッサを搭載したMac
10.5 Leopard 2007/10/26 Intelプロセッサを搭載したMac、PowerPC G5、PowerPC G4(867MHz以上)
10.4 Tiger 2005/4/29 PowerPC G3/G4/G5 プロセッサ

OS Xが出てから10.4まではサポートCPUは変わっていなかった (I/O関係でサポート対象が変わっていたようだが)と思うがIntel Macが登場 した10.4以降はバージョンアップのたびに変化してきた。 次の変化は32ビットしかサポートしていない、または完全な64ビットが サポートできないIntelプロセッサがサポート外になるのだろうが、当分先の事で あろう。

10.5でも64Bitのアプリの構築および実行が出来たようだが、システム付属の アプリはすべて32Bitだったのではないだろうか。10.5ではシステム側の64Bit の準備をおこなって、10.6ではアプリをすべて64Bitにするという順序立ては さすがAppleと思う。おばかなシステム屋はすべて一緒にやって失敗する。

Xcode 3.2.5のgcc 4.2でビルドしたバイナリーのfileコマンドで確認した内容。 この場合このアプリの動作環境は10.4以降のG4以降の機種になるのではないかと 思われる。

Zebra: Mach-O universal binary with 3 architectures
Zebra (for architecture x86_64):        Mach-O 64-bit executable x86_64
Zebra (for architecture i386):  Mach-O executable i386
Zebra (for architecture ppc7400):       Mach-O executable ppc

このバイナリのアプリケーションを10.4 G3のマシンで起動すると クラッシュする。 CrashReporterのログには"incompatible cpu-subtype"と出ている。 10.4をリリースしていた時にはG4以上のバイナリーは想定外で、gcc 4.2を 提供するときにはその事を忘れていたかgcc4.0を同梱しているので対応する 必要はないと考えたのだと思われる。 同じ環境でi386だけのバイナリを実行すると以下のダイアログが出る。

i386only

Xcode 3.2.5のgcc 4.0でビルドしたバイナリーの中身。この場合は64bitのサポートが なくなるが10.4のG3のサポートが出来る。

ppctest: Mach-O universal binary with 2 architectures
ppctest (for architecture i386):     Mach-O executable i386
ppctest (for architecture ppc):      Mach-O executable ppc

lipoコマンドを使って、gcc 4.0でビルドした内容を抜き出して、gcc 4.2でビルド したIntel系のバイナリと引っ付けると10.4のG3以降の環境で動作できるアプリに なる。以下が簡単に実行するためのスクリプトです。

#!/bin/sh

APP="Zebra"
CONT="Contents/MacOS"

lipo -create ${APP}.app/${CONT}/${APP} ${APP}32.app/${CONT}/${APP}32 -output ${APP}

mv ${APP} ${APP}.app/${CONT}/${APP}

ppc64を指定してもgcc 4.2/4.0とも64BitのPowerPCのコードは生成されない。 これはppc64なコードをRossetaがエミュレートできないためかもしれない。 おそらくppcの生成もそれほど遠くないうちに出来なくなるのではないかと思われる。 最近のAppleは何の予告もなくサポートを打ち切る事があるので、十分に注意が 必要だと思われる。(iOS 3.xのSDKが3.2.5で突然なくなって困りました)

NSApplicationDelegateを使った場合には10.6以降の環境でしか動かなくなると 思われる。

Xcode 3.2.5のSDKのサポートは10.4からだが作り方によっては10.3(もしくはそれ以前) でも動きそうな感じがあるが全く試していない。

元祖Airの10.6はカーネルは32bitで動いていて、ユーザランド(アプリ)は64ビット で動いているようだ。これはシステムプロファイラのソフトウエアの項目で 「64ビットカーネルと機能拡張」で確認できる。 この環境で64ビットのバイナリを含むユニバーサルバイナリの 32ビットコードを実行するにはアプリの「情報をみる」で「32ビットモードで開く」 にチェックを入れて実行する。

PPCコードを実行するRossetaは10.6からオプションでのインストールになっている。

システムに含まれるkextをfileコマンドで確認すると以下のような感じになっている。 64ビットのカーネルであがっている場合は64ビットのバイナリを含まないkextは利用 できないのではないかと思われるが確認環境がないため未確認。

msdosfs: Mach-O universal binary with 2 architectures
msdosfs (for architecture x86_64):      Mach-O 64-bit kext bundle x86_64
msdosfs (for architecture i386):        Mach-O object i386

iPhoneのアプリをビルドしたところは以下のような感じ。

Pigeon: Mach-O universal binary with 2 architectures
Pigeon (for architecture armv6):        Mach-O executable arm
Pigeon (for architecture armv7):        Mach-O executable arm

必要以上には複雑にはなっていないようにも思うが、十分複雑だ。。。

以下のページが大変参考になりました。

Universal Binary【前編】
Universal Binary【後編】
やっぱりスゴい! Snow Leopardの「64bit対応」