using check_cxx_source_runs

Alexander Neundorf neundorf at kde.org
Thu Mar 12 22:46:50 CET 2009


On Thursday 12 March 2009, Leo Franchi wrote:
> n 12 Mar 2009, at 20:12, Alexander Neundorf wrote:
> > On Thursday 12 March 2009, Leo Franchi wrote:
> >> On 12 Mar 2009, at 19:49, Alexander Neundorf wrote:
> >
> > ...
> >
> >>> Can you please post a minimal example ?
> >>> So I can just try and see what goes wrong ?
> >>
> >> and the cmake stuff is this:
> >>
> >> include(CheckCXXSourceRuns)
> >>
> >> file( READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/
> >> QtScriptBindingsTest.cpp" source )
> >> message(STATUS "Checking if the QtScript Qt Bindings are installed.")
> >>
> >> #set( BINDINGS_RUN_RESULT -10 )
> >> set(CMAKE_REQUIRED_DEFINTIONS ${QT_DEFINITIONS} ${KDE4_DEFINITIONS} )
> >> set(CMAKE_REQUIRED_INCLUDES ${QT_QTCORE_INCLUDE_DIR} $
> >> {QT_QTSCRIPT_INCLUDE_DIR} ${KDE4_INCLUDES})
> >> set(CMAKE_REQUIRED_LIBRARIES QtScript kdeui)
> >
> > I guess you tried ${QT_QTSCRIPT_LIBRARY} and ${KDE4_KDEUI_LIBS} ?
>
> First of all, apologies for the confusing emails. I've been hitting my
> head against this for a while, so what came out was probably pretty
> garbled and only made half sense.

No, no, it made sense.

> I didn't have a completely clean build dir (I guess on that test I had
> just removed CMakeCache.txt) 

Yes, this was part of the problem.

> and also I couldn't figure out why $ 
> {KDE4_KDECORE_LIBS} didn't work. For some reason here the
> KDE4_KDE*_LIBS variables resolve to something like KDE4__kdeui instead
> of the actual path to the library. 

This is a new feature of cmake 2.6.
It is a so-called imported target. The nice thing about an imported library 
target (compared to a plain path) is that cmake can know more about it. E.g. 
it knows the "LINK_INTERFACE_LIBRARIES" of such imported library targets. So 
when you link against ${KDE4_KDEUI_LIBS}, which resolves to the imported 
target KDE4__kdeui, cmake checks the properties of this imported target (set 
in KDELibs4LibraryTargets.cmake, included by FindKDE4Internal.cmake installed 
with kdelibs, included by FindKDE4.cmake coming with cmake). It then finds 
the location of the file on disk (here: /opt/kdelibs/libkdeui.so.5.2.0), and 
also its link interface libraries (here:  
KDE4__kdecore;/usr/lib/qt4/lib/libQtSvg.so;/usr/lib/qt4/lib/libQtGui.so )

So now when you link a target against this imported library target, you will 
link against the library itself and the libraries from the link interface 
(which is a good thing).

Now you use ${KDE4_KDEUI_LIBS} with check_cxx_source_runs(). The problem here 
now is that this creates a tiny cmake project itself, and then tries to build 
and run it. But here this tiny independent cmake project is told to link 
against KDE4__kdeui, but inside that project there are no imported targets, 
so it just takes that string and tries to link against it 
using -lKDE4__kdeui, which of course fails.

Please replace the CheckCXXSourceRuns.cmake which is installed by the cmake on 
your system with the one attached to this email. It adds some basic handling 
for using imported targets with check_cxx_source_runs(). 
It's not perfect yet, but it works here for me.
Please let me know if it works for you, then we can add it to 
kdelibs/cmake/modules/.
A real fix for this should go into cmake itself.

Alex


> However, I worked around it by
> passing it ${KDE4_LIB_DIR} -lkdecore -lkdeui.
>
> cheers,
> leo
>
> ---
> Leo Franchi				(650) 704 3680
> Tufts University 2010
>
> lfranchi at kde.org
> leonardo.franchi at tufts.edu


-------------- next part --------------
# - 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

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)
# handle imported library targets
      SET(_CCSR_IMP_TARGETS_MAP)
      SET(_CCSR_REQ_LIBS)
      FOREACH(_CURRENT_LIB ${CMAKE_REQUIRED_LIBRARIES})
         GET_TARGET_PROPERTY(_importedConfigs ${_CURRENT_LIB} IMPORTED_CONFIGURATIONS)
         IF (_importedConfigs)
# ok, so this is an imported target
# we'll get it's first location and put this into the map
# then we'll get its link interface libraries property
# iterate through it and replace all imported targets we find there
# with there location from the map
# easy...
            LIST(GET _importedConfigs 0 _firstImportedConfig)
            GET_TARGET_PROPERTY(_firstImportedLocation ${_CURRENT_LIB} LOCATION_${_firstImportedConfig})
            SET(_CCSR_IMP_TARGETS_MAP_${_CURRENT_LIB} ${_firstImportedLocation})
         ELSE(_importedConfigs)
            SET(_CCSR_IMP_TARGETS_MAP_${_CURRENT_LIB} ${_CURRENT_LIB})
         ENDIF(_importedConfigs)
         message(STATUS "mapping lib ${_CURRENT_LIB} to ${_CCSR_IMP_TARGETS_MAP_${_CURRENT_LIB}}")
      ENDFOREACH(_CURRENT_LIB ${CMAKE_REQUIRED_LIBRARIES})

# append the lib (mapped to its name on disk) itself
# then, if it is an imported target, also append each of the link interface libraries
      FOREACH(_CURRENT_LIB ${CMAKE_REQUIRED_LIBRARIES})
         message(STATUS "Appending ${_CCSR_IMP_TARGETS_MAP_${_CURRENT_LIB}}" )
         LIST(APPEND _CCSR_REQ_LIBS ${_CCSR_IMP_TARGETS_MAP_${_CURRENT_LIB}} )
         GET_TARGET_PROPERTY(_importedConfigs ${_CURRENT_LIB} IMPORTED_CONFIGURATIONS)
         IF (_importedConfigs)
            LIST(GET _importedConfigs 0 _firstImportedConfig)
            GET_TARGET_PROPERTY(_linkInterfaceLibs ${_CURRENT_LIB} IMPORTED_LINK_INTERFACE_LIBRARIES_${_firstImportedConfig} )
            FOREACH(_currentLinkInterfaceLib ${_linkInterfaceLibs})
               message(STATUS "Appending link interface lib ${_currentLinkInterfaceLib} as ${_CCSR_IMP_TARGETS_MAP_${_currentLinkInterfaceLib}}")
               LIST(APPEND _CCSR_REQ_LIBS ${_CCSR_IMP_TARGETS_MAP_${_currentLinkInterfaceLib}} )
            ENDFOREACH(_currentLinkInterfaceLib ${_linkInterfaceLibs})
         ENDIF (_importedConfigs)
      ENDFOREACH(_CURRENT_LIB ${CMAKE_REQUIRED_LIBRARIES})
      
      message(STATUS "******* final req libs: ${_CCSR_REQ_LIBS}") 

      SET(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES
        "-DLINK_LIBRARIES:STRING=${_CCSR_REQ_LIBS}")
#        "-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)



More information about the Kde-buildsystem mailing list