如何使用 CMake 检测目标架构? [英] How to detect target architecture using CMake?

查看:30
本文介绍了如何使用 CMake 检测目标架构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经做了很多研究,但无法找到答案……我如何使用 CMake 可靠地找到我正在编译的目标架构?基本上相当于 qmake 中的 QMAKE_TARGET.arch.

I've done a lot of research and been unable to find an answer to this... how can I reliably find the target architecture I'm compiling for, using CMake? Basically, the equivalent to QMAKE_TARGET.arch in qmake.

大多数消息来源似乎都建议使用 CMAKE_SYSTEM_PROCESSOR,但这是一个糟糕的解决方案,因为例如在 OS X 上,无论您是为 i386、x86_64、ppc 还是 ppc64 编译,它总是会返回 i386.

Most sources seem to suggest CMAKE_SYSTEM_PROCESSOR, but that's a bad solution because that will always return i386 on OS X for example, no matter whether you're compiling for i386, x86_64, ppc or ppc64.

同样,CMAKE_SIZEOF_VOID_P 给出了系统的指针大小,而不是目标.

Similarly, CMAKE_SIZEOF_VOID_P gives the pointer size of the system, not the target.

我知道有 CMAKE_OSX_ARCHITECTURES,但如果未设置,它可以为空,在这种情况下,它似乎默认为系统能够提供的任何内容.那么如何找到目标架构信息呢?

I understand there is CMAKE_OSX_ARCHITECTURES, but this can be empty if not set, in which case it seems to default to whatever the system is capable of. So how can I find the target architecture information?

特别是对于 OS X,我如何区分 32、64 和 Intel Universal?

And specifically for OS X, how can I differentiate between 32, 64, and Intel Universal?

推荐答案

所以我为我的问题设计了一个相当有创意的解决方案......看起来 CMake 没有任何检测目标架构的功能.

So I devised a rather creative solution to my problem... it appears that CMake has no functionality to detect the target architecture whatsoever.

现在,我们知道我们可以在 C 中轻松完成此操作,因为诸如 __i386____x86_64__ 等符号将根据您的环境进行定义.幸运的是,CMake 有一个 try_run 函数,可以在配置阶段编译和运行任意 C 源代码文件.

Now, we know we can easily do this in C because symbols like __i386__, __x86_64__, etc., will be defined depending on your environment. Fortunately CMake has a try_run function which will compile and run an arbitrary C source code file during the configure stage.

然后我们可以编写一个小程序,它使用一堆 ifdef 并将架构名称作为字符串写入控制台.唯一的问题是,这只适用于主机和目标系统相同的情况……它在交叉编译期间无法工作,因为虽然您可以编译二进制文件,但无法运行它以查看其输出.

We could then write a small program which uses a bunch of ifdefs and writes the architecture name to the console as a string. The only problem is that this only works if the host and target system are the same... it can't work during cross compilation because while you can compile the binary, you can't run it to see its output.

这里是事情变得有趣的地方.我们可以通过故意编写一个损坏的 C 程序来利用 C 预处理器来获取必要的信息……我们使用基于 ifdefs 将架构名称写入控制台的原始概念,但不是这样做,我们将简单地放置一个 #错误预处理器指令代替 printf 调用.

Here's where things get interesting. We can exploit the C preprocessor to get the necessary information by deliberately writing a broken C program... we use the original concept of writing the architecture name to the console based on ifdefs but instead of doing that, we'll simply place an #error preprocessor directive in place of a printf call.

当 CMake 的 try_run 函数编译 C 文件时,编译总是会失败,但是我们在 #error 指令中放置的任何消息都会显示在编译器的错误输出中,而 try_run 会返回给我们.

When CMake's try_run function compiles the C file, compilation will always fail, but whatever message we placed in the #error directive will show up in the compiler's error output, which try_run returns to us.

因此,我们所要做的就是使用一些 CMake 字符串命令从编译器的错误输出中解析架构名称,并且我们可以检索目标架构......即使在交叉编译时也是如此.

Therefore, all we have to do is parse the architecture name from the compiler's error output using some CMake string commands, and we can retrieve the target architecture... even when cross compiling.

代码的 OS X 特定部分主要使用 CMAKE_OSX_ARCHITECTURES 来确定目标架构,但在未指定的情况下,它将使用与其他系统相同的代码并正确返回 x86_64(对于现代系统,这是编译器的默认值)) 或 i386(适用于较旧的 OS X 系统,例如 Leopard).

The OS X specific part of the code mostly uses CMAKE_OSX_ARCHITECTURES to determine the target architecture, but in the case it's unspecified it will use the same code as other systems and correctly return x86_64 (for modern systems on which that is the compiler's default) or i386 (for older OS X systems such as Leopard).

我已经使用 Visual Studio 9 和 10 生成器(x86、x86_64、ia64)、Xcode、NMake、MSYS Makefiles 和 Unix Makefiles 在 Windows、OS X 和 Linux 上测试并验证了它的工作原理.每次都返回正确的结果.

I've tested and verified this works on Windows, OS X and Linux using Visual Studio 9 and 10 generators (x86, x86_64, ia64), Xcode, NMake, MSYS Makefiles and Unix Makefiles. The correct result is returned every time.

注意:如果您故意执行诸如将 -m32 或 -m64 传递给编译器或其他可能影响目标架构的标志(有没有办法传递所有环境设置到 try_run?);这不是我测试过的.只要您为生成器使用默认设置,并且所有目标都针对相同的架构进行编译,您应该没问题.

Notice: This solution can fail if you deliberately do things like pass -m32 or -m64 to your compiler, or other flags that may affect the target architecture (is there a way to pass all environment settings through to try_run?); this is not something I've tested. As long as you're using the default settings for your generator and all targets are being compiled for the same architecture you should be OK.

我的解决方案的完整源代码可以在 GitHub 上找到:https://github.com/petroules/solar-cmake/blob/master/TargetArch.cmake

The full source code for my solution can be found at GitHub: https://github.com/petroules/solar-cmake/blob/master/TargetArch.cmake

这篇关于如何使用 CMake 检测目标架构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆