diff options
author | Alexander Neundorf <neundorf@kde.org> | 2009-03-19 00:55:45 +0000 |
---|---|---|
committer | Alexander Neundorf <neundorf@kde.org> | 2009-03-19 00:55:45 +0000 |
commit | 3e31cecffb401508cd893032be8b77889c721b83 (patch) | |
tree | 4209b1b0332eedca8ff6a9470fcc1bd0e79a4d7e | |
parent | b6b707c5d1cbb53bc3207e12cc57392feb150fa2 (diff) | |
download | extra-cmake-modules-3e31cecffb401508cd893032be8b77889c721b83.tar.gz extra-cmake-modules-3e31cecffb401508cd893032be8b77889c721b83.tar.bz2 |
-add modified versions of CheckCXXSourceRuns/Compiles.cmake, which can handle imported library targets
(see http://lists.kde.org/?t=123686453500002&r=1&w=2 )
Alex
svn path=/trunk/KDE/kdelibs/; revision=941177
-rw-r--r-- | modules/CMakeLists.txt | 2 | ||||
-rw-r--r-- | modules/CheckCXXSourceCompiles.cmake | 68 | ||||
-rw-r--r-- | modules/CheckCXXSourceRuns.cmake | 81 | ||||
-rw-r--r-- | modules/HandleImportedTargetsInCMakeRequiredLibraries.cmake | 81 |
4 files changed, 231 insertions, 1 deletions
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 675659c4..70df69b2 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,4 +1,4 @@ -# install the cmake files +## install the cmake files file(GLOB cmakeFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.cmake") diff --git a/modules/CheckCXXSourceCompiles.cmake b/modules/CheckCXXSourceCompiles.cmake new file mode 100644 index 00000000..ba7f185c --- /dev/null +++ b/modules/CheckCXXSourceCompiles.cmake @@ -0,0 +1,68 @@ +# - Check if the source code provided in the SOURCE argument compiles. +# CHECK_CXX_SOURCE_COMPILES(SOURCE VAR) +# - macro which checks if the source code compiles +# SOURCE - source code to try to compile +# VAR - variable to store whether the source code compiled +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link + +GET_FILENAME_COMPONENT(_CHECK_CXX_SOURCE_COMPILES_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +INCLUDE(${_CHECK_CXX_SOURCE_COMPILES_DIR}/HandleImportedTargetsInCMakeRequiredLibraries.cmake) + + +MACRO(CHECK_CXX_SOURCE_COMPILES SOURCE VAR) + IF("${VAR}" MATCHES "^${VAR}$") + SET(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") + IF(CMAKE_REQUIRED_LIBRARIES) + # this one translates potentially used imported library targets to their files on disk + HANDLE_IMPORTED_TARGETS_IN_CMAKE_REQUIRED_LIBRARIES(_CHECK_CXX_SOURCE_COMPILES_CMAKE_REQUIRED_LIBRARES) + + SET(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES + "-DLINK_LIBRARIES:STRING=${_CHECK_CXX_SOURCE_COMPILES_CMAKE_REQUIRED_LIBRARES}") +# "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") + ELSE(CMAKE_REQUIRED_LIBRARIES) + SET(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES) + ENDIF(CMAKE_REQUIRED_LIBRARIES) + IF(CMAKE_REQUIRED_INCLUDES) + SET(CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + ELSE(CMAKE_REQUIRED_INCLUDES) + SET(CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES) + ENDIF(CMAKE_REQUIRED_INCLUDES) + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx" + "${SOURCE}\n") + + MESSAGE(STATUS "Performing Test ${VAR}") + TRY_COMPILE(${VAR} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + "${CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES}" + "${CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES}" + OUTPUT_VARIABLE OUTPUT) + IF(${VAR}) + SET(${VAR} 1 CACHE INTERNAL "Test ${VAR}") + MESSAGE(STATUS "Performing Test ${VAR} - Success") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Performing C++ SOURCE FILE Test ${VAR} succeded with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + ELSE(${VAR}) + MESSAGE(STATUS "Performing Test ${VAR} - Failed") + SET(${VAR} "" CACHE INTERNAL "Test ${VAR}") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Performing C++ SOURCE FILE Test ${VAR} failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + ENDIF(${VAR}) + ENDIF("${VAR}" MATCHES "^${VAR}$") +ENDMACRO(CHECK_CXX_SOURCE_COMPILES) + diff --git a/modules/CheckCXXSourceRuns.cmake b/modules/CheckCXXSourceRuns.cmake new file mode 100644 index 00000000..c18d8b37 --- /dev/null +++ b/modules/CheckCXXSourceRuns.cmake @@ -0,0 +1,81 @@ +# - Check if the C++ source code provided in the SOURCE argument compiles and runs. +# CHECK_CXX_SOURCE_RUNS(SOURCE VAR) +# +# SOURCE - source code to try to compile +# VAR - variable to store the result, 1 for success, empty for failure +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link + +GET_FILENAME_COMPONENT(_CHECK_CXX_SOURCE_RUNS_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +INCLUDE(${_CHECK_CXX_SOURCE_RUNS_DIR}/HandleImportedTargetsInCMakeRequiredLibraries.cmake) + +MACRO(CHECK_CXX_SOURCE_RUNS SOURCE VAR) + IF("${VAR}" MATCHES "^${VAR}$") + SET(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") + IF(CMAKE_REQUIRED_LIBRARIES) + # this one translates potentially used imported library targets to their files on disk + HANDLE_IMPORTED_TARGETS_IN_CMAKE_REQUIRED_LIBRARIES(_CHECK_CXX_SOURCE_RUNS_CMAKE_REQUIRED_LIBRARES) + + SET(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES + "-DLINK_LIBRARIES:STRING=${_CHECK_CXX_SOURCE_RUNS_CMAKE_REQUIRED_LIBRARES}") +# "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") + ELSE(CMAKE_REQUIRED_LIBRARIES) + SET(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES) + ENDIF(CMAKE_REQUIRED_LIBRARIES) + IF(CMAKE_REQUIRED_INCLUDES) + SET(CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + ELSE(CMAKE_REQUIRED_INCLUDES) + SET(CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES) + ENDIF(CMAKE_REQUIRED_INCLUDES) + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx" + "${SOURCE}\n") + + MESSAGE(STATUS "Performing Test ${VAR}") + TRY_RUN(${VAR}_EXITCODE ${VAR}_COMPILED + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} + "${CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES}" + "${CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES}" + COMPILE_OUTPUT_VARIABLE OUTPUT) + + # if it did not compile make the return value fail code of 1 + IF(NOT ${VAR}_COMPILED) + SET(${VAR}_EXITCODE 1) + ENDIF(NOT ${VAR}_COMPILED) + # if the return value was 0 then it worked + IF("${${VAR}_EXITCODE}" EQUAL 0) + SET(${VAR} 1 CACHE INTERNAL "Test ${VAR}") + MESSAGE(STATUS "Performing Test ${VAR} - Success") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Performing C++ SOURCE FILE Test ${VAR} succeded with the following output:\n" + "${OUTPUT}\n" + "Return value: ${${VAR}}\n" + "Source file was:\n${SOURCE}\n") + ELSE("${${VAR}_EXITCODE}" EQUAL 0) + IF(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN") + SET(${VAR} "${${VAR}_EXITCODE}") + ELSE(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN") + SET(${VAR} "" CACHE INTERNAL "Test ${VAR}") + ENDIF(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN") + + MESSAGE(STATUS "Performing Test ${VAR} - Failed") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Performing C++ SOURCE FILE Test ${VAR} failed with the following output:\n" + "${OUTPUT}\n" + "Return value: ${${VAR}_EXITCODE}\n" + "Source file was:\n${SOURCE}\n") + ENDIF("${${VAR}_EXITCODE}" EQUAL 0) + ENDIF("${VAR}" MATCHES "^${VAR}$") +ENDMACRO(CHECK_CXX_SOURCE_RUNS) + diff --git a/modules/HandleImportedTargetsInCMakeRequiredLibraries.cmake b/modules/HandleImportedTargetsInCMakeRequiredLibraries.cmake new file mode 100644 index 00000000..28564ab6 --- /dev/null +++ b/modules/HandleImportedTargetsInCMakeRequiredLibraries.cmake @@ -0,0 +1,81 @@ + +# This is a helper function used by CheckCXXSourceRuns.cmake and +# CheckCXXSourceCompiles.cmake. Actually it should be used by all macros which +# use TRY_COMPILE() or TRY_RUN(). +# It takes the CMAKE_REQUIRED_LIBRARY variable and searches it for imported +# (library) targets. Since the project created by TRY_COMPILE() (and TRY_RUN()) +# does not know about these imported targets, this macro here replaces these +# imported targets with the actual library files on disk and it also +# adds the libraries from the link interface of these imported targets. +# E.g the imported target KDE4__kdeui is replaced on my system with /opt/kdelibs/lib/libkdeui.so +# and the link interface libraries, which includes e.g. /opt/kdelibs/lib/libkdecore.so. +# This way imported targets work also when used with CHECK_CXX_SOURCE_COMPILES/RUNS(). + +# Copyright (c) 2009, Alexander Neundorf, <neundorf@kde.org> +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +FUNCTION(HANDLE_IMPORTED_TARGETS_IN_CMAKE_REQUIRED_LIBRARIES _RESULT) +# handle imported library targets + SET(_CCSR_IMP_TARGETS_MAP) + SET(_CCSR_REQ_LIBS ${CMAKE_REQUIRED_LIBRARIES}) + SET(_CHECK_FOR_IMPORTED_TARGETS TRUE) + SET(_CCSR_LOOP_COUNTER 0) + WHILE(_CHECK_FOR_IMPORTED_TARGETS) + MATH(EXPR _CCSR_LOOP_COUNTER "${_CCSR_LOOP_COUNTER} + 1 ") + SET(_CCSR_NEW_REQ_LIBS ) + SET(_CHECK_FOR_IMPORTED_TARGETS FALSE) + FOREACH(_CURRENT_LIB ${_CCSR_REQ_LIBS}) + GET_TARGET_PROPERTY(_importedConfigs ${_CURRENT_LIB} IMPORTED_CONFIGURATIONS) + IF (_importedConfigs) + # Ok, so this is an imported target. + # First we get the imported configurations. + # Then we get the location of the actual library on disk of the first configuration. + # then we'll get its link interface libraries property, + # iterate through it and replace all imported targets we find there + # with there actual location. + + # guard against infinite loop: abort after 100 iterations ( 100 is arbitrary chosen) + IF ("${_CCSR_LOOP_COUNTER}" LESS 100) + SET(_CHECK_FOR_IMPORTED_TARGETS TRUE) +# ELSE ("${_CCSR_LOOP_COUNTER}" LESS 1) +# MESSAGE(STATUS "********* aborting loop, counter : ${_CCSR_LOOP_COUNTER}") + ENDIF ("${_CCSR_LOOP_COUNTER}" LESS 100) + + LIST(GET _importedConfigs 0 _firstImportedConfig) + GET_TARGET_PROPERTY(_firstImportedLocation ${_CURRENT_LIB} LOCATION_${_firstImportedConfig}) + GET_TARGET_PROPERTY(_linkInterfaceLibs ${_CURRENT_LIB} IMPORTED_LINK_INTERFACE_LIBRARIES_${_firstImportedConfig} ) + + LIST(APPEND _CCSR_NEW_REQ_LIBS ${_firstImportedLocation}) +# MESSAGE(STATUS "Appending lib ${_CURRENT_LIB} as ${_firstImportedLocation}") + FOREACH(_currentLinkInterfaceLib ${_linkInterfaceLibs}) +# MESSAGE(STATUS "Appending link interface lib ${_currentLinkInterfaceLib}") + LIST(APPEND _CCSR_NEW_REQ_LIBS ${_currentLinkInterfaceLib} ) + ENDFOREACH(_currentLinkInterfaceLib ${_linkInterfaceLibs}) + ELSE(_importedConfigs) + # "Normal" libraries are just used as they are. + LIST(APPEND _CCSR_NEW_REQ_LIBS ${_CURRENT_LIB} ) +# MESSAGE(STATUS "Appending lib directly: ${_CURRENT_LIB}") + ENDIF(_importedConfigs) + ENDFOREACH(_CURRENT_LIB ${_CCSR_REQ_LIBS}) + + SET(_CCSR_REQ_LIBS ${_CCSR_NEW_REQ_LIBS} ) + ENDWHILE(_CHECK_FOR_IMPORTED_TARGETS) + + # Finally we iterate once more over all libraries. This loop only removes + # all remaining imported target names (there shouldn't be any left anyway). + SET(_CCSR_NEW_REQ_LIBS ) + FOREACH(_CURRENT_LIB ${_CCSR_REQ_LIBS}) + GET_TARGET_PROPERTY(_importedConfigs ${_CURRENT_LIB} IMPORTED_CONFIGURATIONS) + IF (NOT _importedConfigs) + LIST(APPEND _CCSR_NEW_REQ_LIBS ${_CURRENT_LIB} ) +# MESSAGE(STATUS "final: appending ${_CURRENT_LIB}") + ELSE (NOT _importedConfigs) +# MESSAGE(STATUS "final: skipping ${_CURRENT_LIB}") + ENDIF (NOT _importedConfigs) + ENDFOREACH(_CURRENT_LIB ${_CCSR_REQ_LIBS}) + SET(${_RESULT} ${_CCSR_NEW_REQ_LIBS} PARENT_SCOPE) + +ENDFUNCTION(HANDLE_IMPORTED_TARGETS_IN_CMAKE_REQUIRED_LIBRARIES _CCSR_REQ_LIBS) + |