3


2

Objective C(Mac OS X)でCPUアーキテクチャ(32ビット/ 64ビット)ランタイムを検出する

現在、32ビットと64ビットに最適化された(コンソール)アプリケーションを実行する必要があるhttp://en.wikipedia.org/wiki/Cocoa_%28API%29[Cocoa]アプリケーションを作成しています。 このため、アプリケーションが実行されているCPUアーキテクチャを検出して、適切なコンソールアプリケーションを起動できるようにします。

要するに、アプリケーションが64ビットOSで実行されているかどうかをどのようにして検出するのでしょうか?

編集:http://en.wikipedia.org/wiki/Mach-O[Mach-O] fatバイナリについて知っていますが、それは私の質問ではありませんでした。 別の非バンドル(コンソール)アプリケーションを起動できるように、これを知る必要があります。 1つはhttp://en.wikipedia.org/wiki/X86[x86]用に最適化され、もう1つはhttp://en.wikipedia.org/wiki/X86-64[x64]用に最適化されています。

7 Answer


10


とても簡単な方法があります。 32ビット用と64ビット用の2つのバージョンの実行可能ファイルをコンパイルし、それらをlipoと組み合わせます。 そうすれば、正しいバージョンが常に実行されます。

gcc -lobjc somefile.m -o somefile -m32 -march=i686
gcc -lobjc somefile.m -o somefile2 -m64 -march=x86_64
lipo -create -arch i686 somefile -arch x86_64 somefile2 -output somefileUniversal

編集:または、最初に `gcc -arch i686 -arch x86_64`を使用してユニバーサルバイナリをコンパイルします

OPのコメントに応えて:

if(sizeof(int*) == 4)
    //system is 32-bit
else if(sizeof(int*) == 8)
    //system is 64-bit

編集:D’oh! ランタイムチェックが必要だとは知らなかった…​ sysctl -A`の出力を見ると、2つの変数が潜在的に有用に見えます。 `sysctl hw.optional.x86_64`および sysctl hw.cpu64bit_capable`の出力を解析してみてください。 これをテストするための32ビットMacはありませんが、Core2Duo MacのSnow Leopardではこれらの両方が1に設定されています。


7


次の定数のいずれかを返す `[[NSRunningApplication currentApplication] executableArchitecture]`を使用します。

  • NSBundleExecutableArchitectureI386

  • NSBundleExecutableArchitectureX86_64

  • 「NSBundleExecutableArchitecturePPC」

  • NSBundleExecutableArchitecturePPC64

例えば:

switch ([[NSRunningApplication currentApplication] executableArchitecture]) {
  case NSBundleExecutableArchitectureI386:
    // TODO: i386
    break;

  case NSBundleExecutableArchitectureX86_64:
    // TODO: x86_64
    break;

  case NSBundleExecutableArchitecturePPC:
    // TODO: ppc
    break;

  case NSBundleExecutableArchitecturePPC64:
    // TODO: ppc64
    break;

  default:
    // TODO: unknown arch
    break;
}


3


その効果を達成するために手動で検出する必要はありません。 1つのMach-O実行可能ファイルには、32ビットと64ビットのIntelマシンの両方のバイナリを含めることができ、カーネルは最も適切なものを自動的に実行します。 XCodeを使用している場合、プロジェクトインスペクターには、単一のユニバーサルバイナリに含めるアーキテクチャ(ppc、i386、x86_64)を設定できる設定があります。

また、OS Xでは、64ビットカーネル(Snow Leopardを使用)を実行し、64ビットユーザーランドアプリを実行できることは、2つの直交する概念であることを忘れないでください。 64ビットCPUを搭載したマシンを使用している場合、すべてのライブラリがあれば、カーネルが32ビットモード(LeopardまたはSnow Leopardを使用)で実行されている場合でも、64ビットモードでユーザーランドプログラムを実行できます。リンク先は64ビットで利用可能です。 そのため、OSが64ビットに対応しているかどうかを確認することはそれほど役に立ちません。


3


通常、実行時に64ビットか32ビットかを確認できる必要はありません。 ホストアプリケーション(64ビットまたは32ビットツールを起動するアプリ)がファットバイナリである場合、コンパイル時のチェックで十分です。 それは、(一度64ビットの部分について、ファットバイナリの32ビットの部分に一回)を2回コンパイルされます、そして右の1は、システムによって起動されます、あなただけのことで右の起動コードにコンパイルしますので、執筆。 like

#if __LP64__
    NSString    *vExecutablePath = [[NSBundle mainBundle] pathForResource: @"tool64" ofType: @""];
#else
    NSString    *vExecutablePath = [[NSBundle mainBundle] pathForResource: @"tool32" ofType: @""];
#endif
[NSTask launchedTaskWithLaunchPath: vExecutableName ...];

ユーザーが何らかの方法で64ビットMacで32ビットでアプリを明示的に起動した場合、彼らが何をしているかを知っていると信頼してください。 それはとにかくエッジケースであり、なぜパワーユーザーのために間違った完璧な感覚から物事を壊すのですか? 回避策が32ビットとして起動されることをユーザーに伝えることができれば、64ビットのみのバグを発見した場合でも、あなたは自分自身を幸せにすることができます。

アプリ自体が32ビットしかない場合にのみ、実際のランタイムチェックが必要です(例: コマンドラインヘルパーを備えたCarbon GUI)。 その場合、何らかの奇妙な理由で2つの実行可能ファイルを一緒にリポできない場合、host_processor_infoまたはsysctlなどがおそらく唯一のルートです。


2


Snow Leopardを使用している場合は、NSRunningApplicationのexecutableArchitectureを使用してください。

そうでなければ、私は次のことをします:

-(BOOL) is64Bit
{
#if __LP64__
  return YES;
#else
  return NO;
#endif
}


1


CPUアーキテクチャ名の文字列をプログラムで取得するには:

#include
#include

// Determine the machine name, e.g. "x86_64".
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0); // Get size of data to be returned.
char *name = malloc(size);
sysctlbyname("hw.machine", name, &size, NULL, 0);

// Do stuff...

free(name);

シェルスクリプトで同じことを行うには:

set name=`sysctl -n hw.machine`


0


OSバージョン(およびそのユキヒョウ、64ビットOSかどうか)をチェックする標準的な方法は、http://www.cocoadev.com/index.pl?DeterminingOSVersion [こちら]で詳しく説明されています。