我正在拧一个需要执行一些(控制台)应用程序的Cocoa应用程序,这些应用程序针对32位和64位进行了优化。因此,我想检测运行应用程序的CPU架构,以便启动正确的控制台应用程序。
简而言之:如何检测应用程序是否在64位操作系统上运行?
编辑:我知道Mach-O胖二进制文件,这不是我的问题。我需要知道这一点,所以我可以启动另一个非捆绑(控制台)应用程序。一个针对x86进行了优化,一个针对x64进行了优化。
答案 0 :(得分:10)
有一种超级简单的方法。编译可执行文件的两个版本,一个用于32位,一个用于64位,并将它们与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'哦!我没有意识到你需要运行时检查...通过sysctl -A
的输出,两个变量看起来可能有用。尝试解析sysctl hw.optional.x86_64
和sysctl hw.cpu64bit_capable
的输出。我没有32位Mac来测试这个,但是在Core2Duo Mac上的Snow Leopard中这两个都设置为1。
答案 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;
}
答案 2 :(得分:3)
您无需手动检测即可实现此效果。一个Mach-O可执行文件可以包含32位和64位英特尔机器的二进制文件,内核自动运行最合适的文件。如果您正在使用XCode,那么项目检查器中有一个设置,您可以在一个通用二进制文件中设置要包含的体系结构(ppc,i386,x86_64)。
另外,请记住,在OS X上,运行64位内核(使用Snow Leopard)并能够运行64位用户登陆应用程序是两个正交的概念。如果你有一台64位cpu的机器,即使内核以32位模式运行(使用Leopard或Snow Leopard),你也可以在64位模式下运行用户域程序,只要所有的库都可以。你链接的是64位。因此,检查操作系统是否具有64位功能并没有用。
答案 3 :(得分:3)
通常,您不需要能够在运行时检查您是64位还是32位。如果您的主机应用程序(我称之为启动64位或32位工具的应用程序)是胖二进制文件,则编译时检查就足够了。因为它将被编译两次(一次用于胖二进制文件的32位部分,一次用于64位部分),而正确的一次将由系统启动,您将在正确的启动代码中编译写......像
#if __LP64__
NSString *vExecutablePath = [[NSBundle mainBundle] pathForResource: @"tool64" ofType: @""];
#else
NSString *vExecutablePath = [[NSBundle mainBundle] pathForResource: @"tool32" ofType: @""];
#endif
[NSTask launchedTaskWithLaunchPath: vExecutableName ...];
如果用户以某种方式在64位Mac上以32位显式启动您的应用程序,请相信他们知道他们正在做什么。无论如何,这是一个边缘案例,为什么要为权力用户打破错误的完美感。如果您发现只有64位的错误,如果您可以告诉用户解决方法是以32位方式启动,您甚至可能会感到高兴。
如果您的应用程序本身只有32位(例如带有命令行帮助程序的Carbon GUI),您只需要进行真正的运行时检查。在这种情况下,host_processor_info或sysctl或类似的可能是你唯一的路由,如果出于某些奇怪的原因你不能只是将两个可执行文件合并在一起。
答案 4 :(得分:2)
如果您使用的是Snow Leopard,请使用NSRunningApplication的executableArchitecture。
否则,我会做以下事情:
-(BOOL) is64Bit
{
#if __LP64__
return YES;
#else
return NO;
#endif
}
答案 5 :(得分:1)
以编程方式获取具有CPU体系结构名称的字符串:
#include <sys/types.h>
#include <sys/sysctl.h>
// 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);
在shell脚本中执行相同的操作:
set name=`sysctl -n hw.machine`
答案 6 :(得分:0)
检查操作系统版本的标准方法(以及它的雪豹,64位操作系统)是否详细here。