[CMake] Getting the source file list for an executable fails

Michael Hertling mhertling at online.de
Fri Sep 16 20:36:08 EDT 2011


On 09/16/2011 03:24 AM, Campbell Barton wrote:
> On Fri, Sep 16, 2011 at 11:11 AM, Michael Hertling <mhertling at online.de> wrote:
>> On 09/16/2011 02:59 AM, Campbell Barton wrote:
>>> Hi, I would expect this would work from reading the docs but it gives
>>>
>>>       add_executable(mytarget ${SRC})
>>>       get_property(TESTPROP_A TARGET mytarget PROPERTY SOURCE)
>>>         get_target_property(TESTPROP_B mytarget SOURCE)
>>>       message(FATAL_ERROR "Testing ${TESTPROP_A}, ${TESTPROP_B}")
>>>
>>> The output I get is:
>>>
>>> Testing '', 'TESTPROP_B-NOTFOUND'
>>>
>>> This is odd since properties "TYPE" and "LOCATION" are found
>>>
>>> Obviously in this case ${SRC} is already available, but I'm just
>>> trying to figure out why it fails.
>>>
>>> tested on cmake 2.8.5
>>
>> The property you probably refer to is named SOURCES, not SOURCE. The
>> different results returned by GET_PROPERTY() and GET_TARGET_PROPERTY()
>> are documented: The former returns an empty value if the property isn't
>> set, and the latter returns the NOTFOUND value, both evaluating to FALSE.
>>
>> Regards,
>>
>> Michael
> 
> Ack!, sorry for the dumb mistake, but now I'm faced with a different problem.
> 
> Getting the sources for a library defined in another directory, and it
> gives me relative paths.
> 
> How do you get the path a library is defined in so I can make the
> absolute paths? - tried LOCATION but this gives the output location.
> PREFIX, SUFFIX are not set.

AFAIK, CMake doesn't provide a mean to achieve this, so you must DIY:

# CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(TARGETSOURCES C)
SET(CMAKE_VERBOSE_MAKEFILE ON)

FUNCTION(SET_TARGET_DIRECTORIES TARGET)
    SET_TARGET_PROPERTIES(
        ${TARGET}
        PROPERTIES
        TARGET_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
        TARGET_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
ENDFUNCTION()

FUNCTION(GET_TARGET_SOURCES TARGET RESULT)
    GET_PROPERTY(HASSRCDIR
        TARGET ${TARGET}
        PROPERTY TARGET_SOURCE_DIR SET)
    GET_PROPERTY(HASBINDIR
        TARGET ${TARGET}
        PROPERTY TARGET_BINARY_DIR SET)
    IF(HASSRCDIR AND HASBINDIR)
        GET_TARGET_PROPERTY(SRCDIR ${TARGET} TARGET_SOURCE_DIR)
        GET_TARGET_PROPERTY(BINDIR ${TARGET} TARGET_BINARY_DIR)
        GET_TARGET_PROPERTY(SRCS ${TARGET} SOURCES)
        UNSET(SOURCES)
        FOREACH(i IN LISTS SRCS)
            IF(IS_ABSOLUTE ${i})
                LIST(APPEND SOURCES ${i})
            ELSEIF(EXISTS ${SRCDIR}/${i})
                LIST(APPEND SOURCES ${SRCDIR}/${i})
            ELSEIF(EXISTS ${BINDIR}/${i})
                LIST(APPEND SOURCES ${BINDIR}/${i})
            ENDIF()
        ENDFOREACH()
        SET(${RESULT} ${SOURCES} PARENT_SCOPE)
    ENDIF()
ENDFUNCTION()

ADD_SUBDIRECTORY(xyz)
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return 0;}\n")
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main xyz)
GET_TARGET_SOURCES(xyz SOURCES)
MESSAGE("SOURCES: ${SOURCES}")

# xyz/CMakeLists.txt:
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/x.c "void x(void){}\n")
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/y.c "void y(void){}\n")
FILE(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/y.c "void y(void){}\n")
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/z.c "void z(void){}\n")
FILE(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/z.c "void z(void){}\n")
FILE(WRITE /tmp/z.c "void z(void){}\n")
ADD_LIBRARY(xyz SHARED x.c y.c /tmp/z.c)
SET_TARGET_DIRECTORIES(xyz)

The SET_TARGET_DIRECTORIES() function records a target's source/binary
directories as user-defined target properties and must be invoked from
within the concerned target's CMakeLists.txt. The GET_TARGET_SOURCES()
function reconstructs the list of a target's sources with full paths
based on the above-noted target properties. Compare the contents of
the SOURCES variable with Make's output to see that the precedence of
absolute paths over the source directory and the latter's precedence
over the binary directory in ADD_EXECUTABLE/LIBRARY() is respected.

'hope that helps.

Regards,

Michael


More information about the CMake mailing list