How to have CHECK_CXX_COMPILER_FLAG fail on illegal value?

1.7k views Asked by At

Our CMakeFile.txt contains the following for SunCC code paths. SunCC uses -xarch=XXX rather than GCC style -mXXX.

CHECK_CXX_COMPILER_FLAG("-xarch=sha" CRYPTOPP_IA32_SHA)

When we run CMake under Sun's compiler it results in:

-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test CRYPTOPP_IA32_SSSE3
-- Performing Test CRYPTOPP_IA32_SSSE3 - Success
-- Performing Test CRYPTOPP_IA32_SSE4
-- Performing Test CRYPTOPP_IA32_SSE4 - Success
-- Performing Test CRYPTOPP_IA32_CLMUL
-- Performing Test CRYPTOPP_IA32_CLMUL - Success
-- Performing Test CRYPTOPP_IA32_AES
-- Performing Test CRYPTOPP_IA32_AES - Success
-- Performing Test CRYPTOPP_IA32_SHA
-- Performing Test CRYPTOPP_IA32_SHA - Success
...

However, when we compile it results in:

$ make sha-simd.o shacal2-simd.o VERBOSE=1

make -f CMakeFiles/cryptopp-object.dir/build.make CMakeFiles/cryptopp-object.dir/sha-simd.cpp.o
Building CXX object CMakeFiles/cryptopp-object.dir/sha-simd.cpp.o
/opt/solarisstudio12.4/bin/CC -m32 -template=no%extdef -g -xO2 -DNDEBUG -xarch=sha -o CMakeFiles/cryptopp-object.dir/sha-simd.cpp.o -c /export/home/test/sha-simd.cpp
CC: Warning: illegal use of -xarch option, illegal value ignored: sha

make -f CMakeFiles/cryptopp-object.dir/build.make CMakeFiles/cryptopp-object.dir/shacal2-simd.cpp.o
Building CXX object CMakeFiles/cryptopp-object.dir/shacal2-simd.cpp.o
/opt/solarisstudio12.4/bin/CC -m32 -template=no%extdef -g -xO2 -DNDEBUG -xarch=sha -o CMakeFiles/cryptopp-object.dir/shacal2-simd.cpp.o -c /export/home/test/shacal2-simd.cpp
CC: Warning: illegal use of -xarch option, illegal value ignored: sha

Adding SunCC's -errwarn and -errwarn=%all does not help CMake to detect the failure.

The message could cause a lot of problems for users. It also violates our governance for clean compiles. We would like to clean it up and avoid any trouble.

How do we tell CMake to fail the CHECK_CXX_COMPILER_FLAG test on an illegal value?

2

There are 2 answers

2
jww On

The best we have been able to do is add a custom CheckCompilerOption. However, it has other problems because CMake does not supply accurate CXXFLAGS when CMakeLists.txt is executed. The problem surfaces during cross-compiles. Also see CMake Issue 18813.

function(CheckCompilerOption option variable)

    if (${CMAKE_CXX_COMPILER_ID} STREQUAL "SunPro")

        message(STATUS "Performing Test ${variable}")        
        execute_process(
            COMMAND sh -c "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${option} -E -xdumpmacros /dev/null 2>&1"
            COMMAND egrep -i -c "illegal value ignored"
            RESULT_VARIABLE COMMAND_RESULT
            OUTPUT_VARIABLE COMMAND_OUTPUT
            OUTPUT_STRIP_TRAILING_WHITESPACE)

            if (COMMAND_RESULT STREQUAL "1" AND COMMAND_OUTPUT STREQUAL "0")
                set(${variable} 1 PARENT_SCOPE)
                message(STATUS "Performing Test ${variable} - Success")
            else ()
                set(${variable} 0 PARENT_SCOPE)
                message(STATUS "Performing Test ${variable} - Failed")
            endif ()

    else()

        CHECK_CXX_COMPILER_FLAG(${option} ${variable})

    endif()

endfunction(CheckCompilerOption)

"${${variable}}" looks strange, but I believe its correct based on some existing code. The first version with the dereference was wrong. The CMake docs for function don't discuss it and don't offer an example, so we were flying blind again. It is mentioned in What's the CMake syntax to set and use variables? on Stack Overflow.

It can be called like expected:

CheckCompilerOption("-msse4.1 -maes" CRYPTOPP_IA32_AES)
CheckCompilerOption("-msse4.2 -msha" CRYPTOPP_IA32_SHA)
...

CheckCompilerOption("-march=armv7-a -mfloat-abi=hard -mfpu=neon" CRYPTOPP_ARMV7A_HARD)
CheckCompilerOption("-march=armv7-a -mfloat-abi=softfp -mfpu=neon" CRYPTOPP_ARMV7A_SOFTFP)
...

CheckCompilerOption("-march=armv8-a+crc" CRYPTOPP_ARMV8A_CRC)
CheckCompilerOption("-march=armv8-a+crypto" CRYPTOPP_ARMV8A_CRYPTO)
...

CheckCompilerOption("-xarch=aes" CRYPTOPP_SUNCC_AES)
CheckCompilerOption("-xarch=sha" CRYPTOPP_SUNCC_SHA)

If you need to go back further than CMake 3.0 (like to Ubuntu 10 or CentOS 5 with CMake 2.8), then abandon CHECK_CXX_COMPILER_FLAG and use the top part of the function for Clang, GCC, ICC, etc.

GCC's syntax for checking is an option is shown below. The command uses SSSE3 as an example.

$(CXX) -x c++ $(CXXFLAGS) -mssse3 -dM -E - </dev/null 2>&1 | egrep -i -c __SSSE3__
3
Tsyvarev On

I guess, when checks a compiler flag, CMake simply verifies result of the compilation command. As "Warning" message doesn't affect on result, CMake cannot detect that the flag is actually ignored.

You may manually test the flag with try_compile command, so you can check output for some patterns (e.g., for "Warning").

There is also CHECK_CXX_SOURCE_COMPILES macro, which already accepts pattern for match.

See also that question and my answer for it.