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

Campbell Barton ideasman42 at gmail.com
Sat Sep 17 09:01:53 EDT 2011


On Sat, Sep 17, 2011 at 10:36 AM, Michael Hertling <mhertling at online.de> wrote:
> 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


Thanks for the example, but perhaps I should have explained my end
goal better at first.

My aim is to run source code checkers with the correct defines and
includes for each file - cppcheck, splint, sparse are the ones I'm
using right now.


I was trying to figure it out bit by bit but seems like its just not
supported to get source from the target.

We're already using macro's to add source code and libraries so this
could be made build a source list too, but I was hoping this could be
done in a less intrusive, stand-alone way (just grab source files from
target at the end and do operations on them).



So far I managed to get this working in a shoddy, makefile specific way.

$ gmake --always-make --dry-run --keep-going VERBOSE=1

...  read the compilers in from CMakeCache.txt and parse the output of
make for lines that contain the compiler strings.

for the script see:
  https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/cmake/project_source_info.py

example usage with cppcheck.
  https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/cmake/cmake_static_check_cppcheck.py

I have this setup so I can run "make check_splint / check_cppcheck /
check_sparse" and it goes over all the files in the project and runs
the checker.

Until there is a way to get this info from CMake I prefer scanning the
makefile output, but think it would be useful to be able to have give
a configuration and a target and be able to get a list of files, their
defines and includes.

-- 
- Campbell


More information about the CMake mailing list