7

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
Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • To be clear, I want IA32 platform because this rule applies to {x86|x32|x64} for BSDs, Linux, Unix, Solaris, OS X and Windows. And we need something that works on CentOS 5 and Ubuntu 10 through OSes found today. – jww May 11 '17 at 20:03
  • Proper way to compare variable's value with a string: `if(ARCHITECTURE_ID STREQUAL "X86")`. – Tsyvarev May 11 '17 at 21:11
  • Thanks @Tsyvarev. It looks like `ARCHITECTURE_ID STREQUAL "X86"` does not match on an x86 or x64 machines. Neither does `ARCHITECTURE_ID STREQUAL "X64"` or `ARCHITECTURE_ID STREQUAL "x64"`. Any other ideas? – jww May 11 '17 at 21:27
  • What about just printing value of `ARCHITECTURE_ID` on those machines? Either via `message()` or via printing into a file with `execute_process()`. – Tsyvarev May 11 '17 at 21:38
  • Perhaps what you really want is to test for whatever platform functionality `rdrand.cpp` uses rather than going by architecture. You can use modules like [`CheckCSourceCompiles`](https://cmake.org/cmake/help/latest/module/CheckCSourceCompiles.html) or [`CheckCXXSymbolExists`](https://cmake.org/cmake/help/latest/module/CheckCXXSymbolExists.html) to do the test. Let me know if this would be a suitable alternative for you and I'll turn this comment into a detailed answer. – Craig Scott May 14 '17 at 05:59
  • Thanks @Craig. I'm not sure we are on the same page (but its due to my ignorance). We need a YES answer for X86, X32 and X64 platforms; and a NO otherwise. We have runtime checks in place for cpu features, so we always want to compile `rdrand.cpp` for X86, X32 and X64. I'm not sure how that equates to what Cmake considers platform functionality. – jww May 14 '17 at 07:25
  • I usually define (not determine) the architecture in the toolchain file. I have (at least) one toolchain file per architecture, this is very common across public projects like opencv. Is [this](https://cmake.org/Wiki/CMake_Cross_Compiling) relevant by the way? – Antonio May 15 '17 at 14:30
  • @Antonio - Thanks. I'm not sure what you mean. Cmake users install Cmake on their system, so everything should be available. Should we tell users to install something else? Or should we advise them to open a bug report against Cmake? (Right now its [our bug](https://github.com/weidai11/cryptopp/issues/419), but I would be happy to offload it to Cmake). Some of the back story: I help maintain the library, but I am not a Cmake user. The folks who originally wanted Cmake don't fix the bugs even though that was part of the agreement in adding it. – jww May 15 '17 at 17:50
  • @Antonio - When I said, *"Should we tell users to install something else?"*, I meant is Cmake like Boost? For Boost, installing just Boost is usually not enough. You have to install subcomponents, too, like `boost-threading` or `boost-system`. Is Cmake the same way? Do users have to install `cmake-os`, `cmake-platform` or `cmake-cpu` to get the information? – jww May 15 '17 at 18:30

1 Answers1

4
  • 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}
)    
Florian
  • 39,996
  • 9
  • 133
  • 149