我已经做了很多研究,但无法找到这个问题的答案......我如何才能使用CMake可靠地找到我正在编译的目标架构?基本上,相当于qmake中的QMAKE_TARGET.arch。
大多数源代码似乎都建议使用CMAKE_SYSTEM_PROCESSOR,但这是一个糟糕的解决方案,因为它在OS X上总是返回i386,例如,无论您是针对i386、x86_64、ppc还是ppc64进行编译。
类似地,CMAKE_SIZEOF_VOID_P给出 system 的指针大小,而不是目标的指针大小。
我知道有CMAKE_OSX_ARCHITECTURES,但如果没有设置,它可能是空的,在这种情况下,它似乎默认为系统所能提供的任何功能。那么,我如何才能找到目标架构信息呢?
特别是对于OS X,我如何区分32、64和英特尔通用?
8条答案
按热度按时间ki0zmccv1#
所以我设计了一个相当有创意的解决方案来解决我的问题...看起来CMake没有任何功能来检测目标架构。
现在,我们知道我们可以很容易地在C中实现这一点,因为像
__i386__
,__x86_64__
等符号将根据您的环境进行定义。幸运的是,CMake有一个try_run函数,它将在配置阶段编译并运行任意的C源代码文件。然后我们可以编写一个小程序,使用一堆ifdef,并将架构名称作为字符串写入控制台。唯一的问题是,这只在主机和目标系统相同的情况下有效...它在交叉编译时不能工作,因为虽然你可以编译二进制文件,但你不能运行它来查看它的输出。
有趣的是,我们可以利用C预处理器来获取必要的信息,方法是故意编写一个不完整的C程序......我们使用了最初的概念,即基于ifdef将架构名称写入控制台,但我们没有这样做,而是简单地用#error预处理器指令代替printf调用。
当CMake的try_run函数编译C文件时,编译总是会失败,但是我们在#error指令中放置的任何消息都会在编译器的错误输出中显示出来,try_run会返回给我们。
因此,我们所要做的就是使用一些CMake字符串命令从编译器的错误输出中解析架构名称,并且我们可以检索目标架构......即使在交叉编译时。
特定于OS X的代码部分主要使用CMAKE_OSX_ARCHITECTURES来确定目标体系结构,但在未指定的情况下,它将使用与其他系统相同的代码,并正确返回x86_64(对于现代系统,这是编译器的默认值)或i386(对于较旧的OS X系统,如Leopard)。
我已经使用Visual Studio 9和10生成器(x86,x86_64,ia 64),Xcode,NMake,MSYS Makefile和Unix Makefile在Windows,OS X和Linux上测试和验证了它的工作原理。
**注意:**如果您故意将-m32或-m64传递给编译器,或者传递其他可能影响目标体系结构的标志(是否有办法将所有环境设置传递给try_run?),则此解决方案可能会失败;这不是我测试过的东西。只要你使用你的生成器的默认设置,并且所有的目标都是为同一个体系结构编译的,你应该没问题。
我的解决方案的完整源代码可以在GitHub上找到:https://github.com/petroules/solar-cmake/blob/master/TargetArch.cmake
voj3qocg2#
对于主机和目标系统相同的情况,我有一个解决方案。
首先,您需要调用“uname -m”以获取“machine hardware name"。然后,您需要切断尾随的“Carriage Return”以将实际值返回到提供的变量中。
现在您可以打印变量${ARCHITECTURE}:
或者做一些规范化的Map,例如“x86_64”,“amd 64”,......到例如“64 Bit”。32 Bit也是一样。有了这个,你可以执行依赖于体系结构的编译,比如:
sg24os4d3#
安卓系统
${ANDROID_ABI}
${ANDROID_ABI}
变量是Android中的一种方法,它采用arm64-v8a
、x86_64
等值。它在官方NDK库示例中使用:https://github.com/googlesamples/android-ndk/blob/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/app/src/main/cpp/CMakeLists.txt#L25
我在以下网址对该示例作了进一步的评论:NDK:如何在不考虑体系结构的情况下包含预构建的共享库
dkqlctbz4#
如果您的构建过程涉及多个目标,最好让CMake知道它构建的ARCH/工具链。您可以遵循CMake交叉编译的instructions,这鼓励您创建一个工具链CMake文件,它允许您选择正在使用的工具链/编译器。
我已经创建了一个用于为arm处理器构建C++ Linux应用程序的脚本,并将其命名为
toolchain-arm.cmake
。它包括
set(CMAKE_SYSTEM_PROCESSOR arm)
。然后我执行CMake,如下所示:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE={my toolchain cmake path}/toolchain-arm.cmake {my source path}
在我的项目的CMakeList.txt中,我可以以任何方式引用CMAKE_SYSTEM_PROCESSOR。
当为X86构建时,我没有包括对-DCMAKE_TOOLCHAIN_FILE的引用,从而使CMAKE_SYSTEM_PROCESSOR保持未定义状态,或者至少没有定义为
arm
。这是我的工具链臂。cmake
aij0ehis5#
这个帖子是旧的,所以很抱歉,如果复活死者在这里,但我只是想我会分享我的解决方案。
我不想使用任何外部应用程序,不幸的是,我们使用的toolchain.cmake文件没有在另一个变量中设置arch,所以我通过查看
CMAKE_C_FLAGS
和CMAKE_CXX_FLAGS
变量来查找愚者的-march
参数来检测它。如果没有,福尔斯CMAKE_HOST_SYSTEM_PROCESSOR
。快速浏览一下Clang文档似乎表明这对那个不起作用,但它只需要第二个正则表达式步骤来匹配它的预期参数。
wljmcqd86#
现在,您不需要任何技巧来确定目标架构:针对每个目标的变量OSX_ARCHITECTURES已添加到cmake中,可用于您的目的:http://public.kitware.com/Bug/view.php?id=8725
2w3rbyxf7#
您可以使用CMAKE_GENERATOR_PLATFORM变数。如果您要在win32下建置项目,您必须使用-A Win32来指定平台。然后平台会储存在CMAKE_GENERATOR_PLATFORM变数中。
сmake -A x64 ..
或cmake -A Win32 ..
如果不使用-A,变量将为空,这一点很重要
ffdz8vbo8#
这是了解主机体系结构的一种经过充分测试的方法:
并在以后需要时在CMakeLists中使用该信息