From 813eca64160509465c0e557aa98c9b0f828e47a9 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Tue, 3 Jan 2012 19:54:43 +0100 Subject: CheckSymbolExists: force the compiler to keep the referenced symbol Otherwise the compiler may optimize out the reference to the symbol as the previous version was not really using this. This leads to symbols that are only in a header but not in the given libraries to be reported as present. This came up on the first try to fix bug 11333 as "gcc -O3" would optimize out the reference to pthread_create() so the correct library the symbol is in was not detected. The new test code was suggested by Brad King. --- Modules/CheckSymbolExists.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index 183b2bb..515319d 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -60,7 +60,7 @@ MACRO(_CHECK_SYMBOL_EXISTS SOURCEFILE SYMBOL FILES VARIABLE) "${CMAKE_CONFIGURABLE_FILE_CONTENT}#include <${FILE}>\n") ENDFOREACH(FILE) SET(CMAKE_CONFIGURABLE_FILE_CONTENT - "${CMAKE_CONFIGURABLE_FILE_CONTENT}\nvoid cmakeRequireSymbol(int dummy,...){(void)dummy;}\nint main()\n{\n#ifndef ${SYMBOL}\n cmakeRequireSymbol(0,&${SYMBOL});\n#endif\n return 0;\n}\n") + "${CMAKE_CONFIGURABLE_FILE_CONTENT}\nint main(int argc, char** argv)\n{\n (void)argv;\n#ifndef ${SYMBOL}\n return ((int*)(&${SYMBOL}))[argc];\n#else\n (void)argc;\n return 0;\n#endif\n}\n") CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" "${SOURCEFILE}" @ONLY IMMEDIATE) -- cgit v0.12 From 8e1f376782be078407f926c042f07c789e073856 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 2 Jan 2012 23:04:42 +0100 Subject: add a test for Check{,CXX}SymbolExists Now that we think that CheckSymbolExists really works for all cases it is time to prove that. If this code fails too many other things will break. --- Tests/CMakeOnly/CMakeLists.txt | 4 ++ .../CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt | 62 ++++++++++++++++++++++ Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt | 51 ++++++++++++++++++ Tests/CMakeOnly/CheckSymbolExists/cm_cse.h | 6 +++ 4 files changed, 123 insertions(+) create mode 100644 Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt create mode 100644 Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt create mode 100644 Tests/CMakeOnly/CheckSymbolExists/cm_cse.h diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt index d32e7be..ec883ef 100644 --- a/Tests/CMakeOnly/CMakeLists.txt +++ b/Tests/CMakeOnly/CMakeLists.txt @@ -7,3 +7,7 @@ macro(add_CMakeOnly_test test) -P ${CMAKE_CURRENT_BINARY_DIR}/Test.cmake ) endmacro() + +add_CMakeOnly_test(CheckSymbolExists) + +add_CMakeOnly_test(CheckCXXSymbolExists) diff --git a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt new file mode 100644 index 0000000..1c978c1 --- /dev/null +++ b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt @@ -0,0 +1,62 @@ +# This test will verify if CheckCXXSymbolExists only report symbols available +# for linking that really are. You can find some documentation on this in +# bug 11333 where we found out that gcc would optimize out the actual +# reference to the symbol, so symbols that are in fact _not_ available in the +# given libraries (but seen in header) were reported as present. +# +# If you change this test do not forget to change the CheckSymbolExists +# test, too. + +PROJECT(CheckCXXSymbolExists CXX) + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) + +SET(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/../CheckSymbolExists") + +INCLUDE(CheckCXXSymbolExists) + +foreach(_config_type Release RelWithDebInfo MinSizeRel Debug) + set(CMAKE_TRY_COMPILE_CONFIGURATION ${_config_type}) + unset(CSE_RESULT_${_config_type} CACHE) + MESSAGE(STATUS "Testing configuration ${_config_type}") + check_cxx_symbol_exists(non_existent_function_for_symbol_test "cm_cse.h" CSE_RESULT_${_config_type}) + + IF (CSE_RESULT_${_config_type}) + MESSAGE(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol as existing in configuration ${_config_type}") + ENDIF (CSE_RESULT_${_config_type}) +endforeach() + +set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE}) +unset(CSE_RESULT_ERRNO_CERRNO CACHE) + +MESSAGE(STATUS "Checking ") + +check_cxx_symbol_exists(errno "cerrno" CSE_RESULT_ERRNO_CERRNO) + +IF (NOT CSE_RESULT_ERRNO_CERRNO) + unset(CSE_RESULT_ERRNO_ERRNOH CACHE) + + MESSAGE(STATUS "Checking ") + + check_cxx_symbol_exists(errno "errno.h" CSE_RESULT_ERRNO_ERRNOH) + + IF (NOT CSE_RESULT_ERRNO_ERRNOH) + MESSAGE(SEND_ERROR "CheckCXXSymbolExists did not find errno in and ") + ELSE (NOT CSE_RESULT_ERRNO_ERRNOH) + MESSAGE(STATUS "errno found in ") + ENDIF (NOT CSE_RESULT_ERRNO_ERRNOH) +ELSE (NOT CSE_RESULT_ERRNO_CERRNO) + MESSAGE(STATUS "errno found in ") +ENDIF (NOT CSE_RESULT_ERRNO_CERRNO) + +IF (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") + unset(CSE_RESULT_O3 CACHE) + MESSAGE(STATUS "Testing with optimization -O3") + + check_cxx_symbol_exists(non_existent_function_for_symbol_test "cm_cse.h" CSE_RESULT_O3) + + IF (CSE_RESULT_O3) + MESSAGE(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol as existing with optimization -O3") + ENDIF (CSE_RESULT_O3) +ENDIF (CMAKE_COMPILER_IS_GNUCXX) diff --git a/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt new file mode 100644 index 0000000..7c969d3 --- /dev/null +++ b/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt @@ -0,0 +1,51 @@ +# This test will verify if CheckSymbolExists only report symbols available +# for linking that really are. You can find some documentation on this in +# bug 11333 where we found out that gcc would optimize out the actual +# reference to the symbol, so symbols that are in fact _not_ available in the +# given libraries (but seen in header) were reported as present. +# +# If you change this test do not forget to change the CheckCXXSymbolExists +# test, too. + +PROJECT(CheckSymbolExists C) + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) + +SET(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}") + +INCLUDE(CheckSymbolExists) + +foreach(_config_type Release RelWithDebInfo MinSizeRel Debug) + set(CMAKE_TRY_COMPILE_CONFIGURATION ${_config_type}) + unset(CSE_RESULT_${_config_type} CACHE) + MESSAGE(STATUS "Testing configuration ${_config_type}") + + check_symbol_exists(non_existent_function_for_symbol_test "cm_cse.h" CSE_RESULT_${_config_type}) + + IF (CSE_RESULT_${_config_type}) + MESSAGE(SEND_ERROR "CheckSymbolExists reported a nonexistent symbol as existing in configuration ${_config_type}") + ENDIF (CSE_RESULT_${_config_type}) +endforeach() + +set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE}) +unset(CSE_RESULT_ERRNO CACHE) + +check_symbol_exists(errno "errno.h" CSE_RESULT_ERRNO) + +IF (NOT CSE_RESULT_ERRNO) + MESSAGE(SEND_ERROR "CheckSymbolExists did not find errno in ") +ELSE (NOT CSE_RESULT_ERRNO) + MESSAGE(STATUS "errno found as expected") +ENDIF (NOT CSE_RESULT_ERRNO) + +IF (CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") + unset(CSE_RESULT_O3 CACHE) + MESSAGE(STATUS "Testing with optimization -O3") + + check_symbol_exists(non_existent_function_for_symbol_test "cm_cse.h" CSE_RESULT_O3) + + IF (CSE_RESULT_O3) + MESSAGE(SEND_ERROR "CheckSymbolExists reported a nonexistent symbol as existing with optimization -O3") + ENDIF (CSE_RESULT_O3) +ENDIF (CMAKE_COMPILER_IS_GNUCC) diff --git a/Tests/CMakeOnly/CheckSymbolExists/cm_cse.h b/Tests/CMakeOnly/CheckSymbolExists/cm_cse.h new file mode 100644 index 0000000..4f41c76 --- /dev/null +++ b/Tests/CMakeOnly/CheckSymbolExists/cm_cse.h @@ -0,0 +1,6 @@ +#ifndef _CSE_DUMMY_H +#define _CSE_DUMMY_H + +int non_existent_function_for_symbol_test(); + +#endif -- cgit v0.12