Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine platforms like ARM, MIPS and IA32?

Something is sideways in our CmakeFileList.txt file. Its trying to build an IA32 component on an ARM platform. I'm trying to fix the issue.

The file in question was filtered-out from the GLOB, which is named rdrand.cpp:

list(REMOVE_ITEM cryptopp_SOURCES
        ...
        ${CMAKE_CURRENT_SOURCE_DIR}/rdrand.cpp
        ...
        ${cryptopp_SOURCES_TEST}
        )
set(cryptopp_SOURCES

Now I am trying to add rdrand,cpp back in for IA32 platforms. According to Building c++ project on Windows with CMake, Clang and Ninja (not a good fit, but it has useful information) and CMakePlatformId.h.in, it looks like I need a predicate using ARCHITECTURE_ID and "X86", "X32", "X64" or "x64" (not a dup, the x is lowercase instead of uppercase).

Here's my attempt to create the predicate:

# http://github.com/weidai11/cryptopp/issues/419
if (${ARCHITECTURE_ID} == "X86" OR ${ARCHITECTURE_ID} == "X32" OR ${ARCHITECTURE_ID} == "X64" )
    list(APPEND cryptopp_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/rdrand.cpp)
endif()

The results below are from a BeagleBoard with Cmake 3.5.2. Neither ==, =,STREQUAL seems to work:

CMake Error at CMakeLists.txt:310 (if):
  if given arguments:

    "==" "X86" "OR" "==" "X32" "OR" "==" "X64"

  Unknown arguments specified

And:

$ cmake .
CMake Error at CMakeLists.txt:310 (if):
  if given arguments:

    "STREQUAL" "X86" "OR" "STREQUAL" "X32" "OR" "STREQUAL" "X64"

  Unknown arguments specified

My attempts to search for how to use ARCHITECTURE_ID are nearly useless. I can't find an example or the docs on Cmake's site. Adding quotes around "${ARCHITECTURE_ID}" did not help; nor did removing the braces to denote a variable ARCHITECTURE_ID.

I also tried to use CMAKE_SYSTEM_PROCESSOR and other related defines, but Cmake mostly returns "unknown" for them. Its not very helpful to say the least.

How do I use ARCHITECTURE_ID to identify IA32 platforms? Or, is there something else I should be using in this instance?

Thanks in advance.


Here's what we do in our GNUmakefile. Make is not a build system, so we have to do the heavy lifting:

IS_X86 := $(shell uname -m | $(EGREP) -v "x86_64" | $(EGREP) -i -c "i.86|x86|i86")
IS_X64 := $(shell uname -m | $(EGREP) -i -c "(_64|d64)")
...

# Need RDRAND for X86/X64/X32
ifeq ($(IS_X86)$(IS_X32)$(IS_X64),000)
  SRCS := $(filter-out rdrand.cpp, $(SRCS))
endif
like image 349
jww Avatar asked May 11 '17 18:05

jww


1 Answers

  • I don't think a variable named ARCHITECTURE_ID does exist in CMake to query. That's probably the reason why you can't find any hints in CMake's documentation. It's only used in CMakePlatformId.h to fill MSVC specific internal variable like MSVC_CXX_ARCHITECTURE_ID.

    /* For windows compilers MSVC and Intel we can determine
       the architecture of the compiler being used.  This is because
       the compilers do not have flags that can change the architecture,
       but rather depend on which compiler is being used
    */
    
  • What you are actually looking for is the cmake_host_system_information()command. The problem there is, that it does not export all the information it actually has. I'm thinking that to be a missing feature and probably will make a pull request for CMake's source Git over the next days to extend its functionality, but that won't help you for the near future.

    If you have CMake's source code on the system(s) in question you could run one of the tests

     $ cmsysTestscxx testSystemInformation
    

    to see what system information CMake actually has.

    𝓝𝓸𝓽𝓮: Querying the host system won't help when cross-compiling or e.g. compiling for 32 Bit on a 64 Bit machine (that could also be a possible flaw in your GNUMakefile example).

  • To answer your question about the if statement, this can simply be solved by an Regular Expression:

    cmake_minimum_required(VERSION 2.4)
    
    project(TestArchitectureId)
    
    if (ARCHITECTURE_ID MATCHES "^(X86|X32|X64|x64)$" )
        message(STATUS "Hello ${CMAKE_MATCH_1}")
    endif()
    

Otherwise isn't this somewhat related to Detect 32-bit x86 processor in CMakeList.txt?

Alternatives

CMake itself uses

if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "ia64")

or

if(NOT CMAKE_GENERATOR MATCHES "IA64")

or - even this may be going the extra mile - call try_compile() with rdrand.cpp:

# Choose a configuration for our compiler tests
if (NOT CMAKE_CONFIGURATION_TYPES AND 
    NOT CMAKE_NO_BUILD_TYPE)
    set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}")
else()
    set(CMAKE_TRY_COMPILE_CONFIGURATION RelWithDebInfo)
endif()
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

string(TOUPPER "${CMAKE_TRY_COMPILE_CONFIGURATION}" cryptopp_TRY_COMPILE_CONFIGURATION) 
set(CMAKE_REQUIRED_FLAGS "${CMAKE_CXX_FLAGS}" "${CMAKE_CXX_FLAGS_${cryptopp_TRY_COMPILE_CONFIGURATION}}") 
get_directory_property(CMAKE_REQUIRED_INCLUDES INCLUDE_DIRECTORIES)
get_directory_property(CMAKE_REQUIRED_DEFINITIONS COMPILE_DEFINITIONS)
if (CMAKE_REQUIRED_DEFINITIONS)
    string(REPLACE ";" ";-D" CMAKE_REQUIRED_DEFINITIONS "-D${CMAKE_REQUIRED_DEFINITIONS}")
endif()

try_compile(
    cryptopp_RDRAND_WORKS 
    ${CMAKE_CURRENT_BINARY_DIR}
    SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/rdrand.cpp
    CMAKE_FLAGS 
        -DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS}
        -DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}
    COMPILE_DEFINITIONS 
        ${CMAKE_REQUIRED_DEFINITIONS}
)    
like image 180
Florian Avatar answered Oct 02 '22 00:10

Florian