如何使用CMake检测目标架构?

hec6srdp  于 2022-11-29  发布在  其他
关注(0)|答案(8)|浏览(318)

我已经做了很多研究,但无法找到这个问题的答案......我如何才能使用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和英特尔通用?

ki0zmccv

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

voj3qocg

voj3qocg2#

对于主机和目标系统相同的情况,我有一个解决方案。
首先,您需要调用“uname -m”以获取“machine hardware name"。然后,您需要切断尾随的“Carriage Return”以将实际值返回到提供的变量中。

EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE )

现在您可以打印变量${ARCHITECTURE}:

message( STATUS "Architecture: ${ARCHITECTURE}" )

或者做一些规范化的Map,例如“x86_64”,“amd 64”,......到例如“64 Bit”。32 Bit也是一样。有了这个,你可以执行依赖于体系结构的编译,比如:

if( ${ARCHITECTURE} STREQUAL "64Bit" )
    set( BLA_LIBRARY "/opt/lib/libBla.so" )
else()
    set( BLA_LIBRARY "/opt/lib32/libBla.so" )
endif()
sg24os4d

sg24os4d3#

安卓系统${ANDROID_ABI}

${ANDROID_ABI}变量是Android中的一种方法,它采用arm64-v8ax86_64等值。
它在官方NDK库示例中使用:https://github.com/googlesamples/android-ndk/blob/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/app/src/main/cpp/CMakeLists.txt#L25
我在以下网址对该示例作了进一步的评论:NDK:如何在不考虑体系结构的情况下包含预构建的共享库

dkqlctbz

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

SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR arm)

# specify the cross compiler
SET(ENV{TOOLCHAIN_ROOT} /home/user/toolchain/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin )
SET(CMAKE_C_COMPILER   $ENV{TOOLCHAIN_ROOT}/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN_ROOT}/arm-linux-gnueabihf-gcc)

# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
aij0ehis

aij0ehis5#

这个帖子是旧的,所以很抱歉,如果复活死者在这里,但我只是想我会分享我的解决方案。
我不想使用任何外部应用程序,不幸的是,我们使用的toolchain.cmake文件没有在另一个变量中设置arch,所以我通过查看CMAKE_C_FLAGSCMAKE_CXX_FLAGS变量来查找愚者的-march参数来检测它。如果没有,福尔斯CMAKE_HOST_SYSTEM_PROCESSOR
快速浏览一下Clang文档似乎表明这对那个不起作用,但它只需要第二个正则表达式步骤来匹配它的预期参数。

set(TARGET_ARCH_REGEX "^.*-march[= ]([^ ]+).*$")
string(REGEX MATCH "${TARGET_ARCH_REGEX}" TARGET_ARCH_MATCH ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS})
if (TARGET_ARCH_MATCH)
    string(REGEX REPLACE "${TARGET_ARCH_REGEX}" "\\1" TARGET_ARCH ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS})
else()
    set(TARGET_ARCH ${CMAKE_HOST_SYSTEM_PROCESSOR})
endif()
wljmcqd8

wljmcqd86#

现在,您不需要任何技巧来确定目标架构:针对每个目标的变量OSX_ARCHITECTURES已添加到cmake中,可用于您的目的:http://public.kitware.com/Bug/view.php?id=8725

2w3rbyxf

2w3rbyxf7#

您可以使用CMAKE_GENERATOR_PLATFORM变数。如果您要在win32下建置项目,您必须使用-A Win32来指定平台。然后平台会储存在CMAKE_GENERATOR_PLATFORM变数中。
сmake -A x64 ..cmake -A Win32 ..
如果不使用-A,变量将为空,这一点很重要

ffdz8vbo

ffdz8vbo8#

这是了解主机体系结构的一种经过充分测试的方法:

# Store in CMAKE_DEB_HOST_ARCH var the current build architecture
execute_process(COMMAND
  dpkg-architecture
    -qDEB_HOST_ARCH
  OUTPUT_VARIABLE
    CMAKE_DEB_HOST_ARCH
  OUTPUT_STRIP_TRAILING_WHITESPACE
)

并在以后需要时在CMakeLists中使用该信息

if(${CMAKE_DEB_HOST_ARCH} MATCHES "armhf")
  ...
elseif(${CMAKE_DEB_HOST_ARCH} MATCHES "i386")
  ...
else()
  ...
endif()

相关问题