Jak*_*les 41 architecture build-process qmake cmake
我已经做了很多研究并且无法找到答案...我怎样才能可靠地找到我正在编译的目标架构,使用CMake?基本上,相当于qmake中的QMAKE_TARGET.arch.
大多数消息来源似乎建议使用CMAKE_SYSTEM_PROCESSOR,但这是一个糟糕的解决方案,因为无论你是在编译i386,x86_64,ppc还是ppc64,它都会在OS X上返回i386.
同样,CMAKE_SIZEOF_VOID_P给出的指针大小的系统,而不是目标.
我知道有CMAKE_OSX_ARCHITECTURES,但如果没有设置,这可能是空的,在这种情况下,它似乎默认为系统能够做的任何事情.那么如何找到目标架构信息呢?
特别是对于OS X,我如何区分32,64和Intel Universal?
Jak*_*les 36
所以我为我的问题设计了一个相当有创意的解决方案......看来CMake没有任何功能来检测目标架构.
现在,我们知道我们可以很容易地做到这一点在C,因为相同的符号__i386__,__x86_64__这取决于你的环境等,将被定义.幸运的是,CMake有一个try_run函数,可以在配置阶段编译和运行任意C源代码文件.
然后我们可以编写一个使用一堆ifdef的小程序,并将架构名称作为字符串写入控制台.唯一的问题是这只有在主机和目标系统相同的情况下才有效...它在交叉编译期间无法工作,因为虽然您可以编译二进制文件,但您无法运行它来查看其输出.
事情变得有趣.我们可以通过故意编写一个破碎的C程序来利用C预处理器来获取必要的信息...我们使用基于ifdef将体系结构名称写入控制台的原始概念,但是我们只需要放置一个#错误预处理程序指令代替printf调用.
当CMake的try_run函数编译C文件时,编译将始终失败,但是我们在#error指令中放置的任何消息都将显示在编译器的错误输出中,try_run将返回给我们.
因此,我们所要做的就是使用一些CMake字符串命令从编译器的错误输出中解析体系结构名称,并且我们可以检索目标体系结构......即使在交叉编译时也是如此.
代码的OS X特定部分主要使用CMAKE_OSX_ARCHITECTURES来确定目标体系结构,但在未指定的情况下,它将使用与其他系统相同的代码并正确返回x86_64(对于编译器默认的现代系统)或i386 (适用于较旧的OS X系统,如Leopard).
我已经在Windows,OS X和Linux上使用Visual Studio 9和10生成器(x86,x86_64,ia64),Xcode,NMake,MSYS Makefiles和Unix Makefiles进行了测试和验证.每次都返回正确的结果.
注意:如果您故意执行诸如将-m32或-m64传递给编译器或其他可能影响目标体系结构的标志(有没有办法将所有环境设置传递给try_run?),此解决方案可能会失败; 这不是我测试过的东西.只要您使用生成器的默认设置并且所有目标都是针对相同的体系结构进行编译,您应该没问题.
我的解决方案的完整源代码可以在GitHub上找到:https://github.com/petroules/solar-cmake/blob/master/TargetArch.cmake
小智 17
我为主机和目标系统相同的情况提供了解决方案.
首先,您需要调用"uname -m"来获取" 机器硬件名称 ".之后,您需要切断尾随的" 回车符 "以将实际值恢复为提供的变量.
EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE )
Run Code Online (Sandbox Code Playgroud)
现在你可以打印出变量$ {ARCHITECTURE}:
message( STATUS "Architecture: ${ARCHITECTURE}" )
Run Code Online (Sandbox Code Playgroud)
或做一些Canonization来映射,例如"x86_64","amd64",...到例如"64Bit".32Bit也是如此.有了这个,您可以执行archtecture dependend Compilation,如:
if( ${ARCHITECTURE} STREQUAL "64Bit" )
set( BLA_LIBRARY "/opt/lib/libBla.so" )
else()
set( BLA_LIBRARY "/opt/lib32/libBla.so" )
endif()
Run Code Online (Sandbox Code Playgroud)
Cir*_*四事件 10
Android的 ${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:如何包含预建的共享库,无论架构如何
如果您的构建过程涉及多个目标,那么最好让CMake 知道要针对哪个ARCH /工具链。您可以按照说明进行操作 CMake交叉编译进行,鼓励您创建工具链CMake文件,该文件可让您选择使用的工具链/编译器。
我已经创建了一个用于为手臂处理器构建我的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。
这是我的toolchain-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)
Run Code Online (Sandbox Code Playgroud)