[CMake] ExternalProject and clean targets

Michael Hertling mhertling at online.de
Sat Oct 15 09:27:25 EDT 2011


On 10/15/2011 12:34 PM, David Cole wrote:
> On Sat, Oct 15, 2011 at 3:48 AM, Michael Hertling <mhertling at online.de> wrote:
>> On 10/12/2011 10:22 PM, Lori Pritchett-Sheats wrote:
>>>
>>> I'm building external packages in my CMake system using the
>>> ExternalPackages_Add function. When a package is built this way and I
>>> execute a 'make clean' at the top of my build tree,  all targets are
>>> cleaned including the external packages. Is there a way to remove the
>>> external package targets from the the default clean target?
>>
>> The following exemplary project does not exhibit this behavior:
>>
>> # CMakeLists.txt:
>> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
>> PROJECT(CLEAN C)
>> SET(CMAKE_VERBOSE_MAKEFILE ON)
>> INCLUDE(ExternalProject)
>> ExternalProject_Add(external
>>    SOURCE_DIR ${CMAKE_SOURCE_DIR}/external
>>    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>)
>> FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return 0;}\n")
>> ADD_EXECUTABLE(main main.c)
>> ADD_DEPENDENCIES(main external)
>> INSTALL(TARGETS main DESTINATION bin)
>>
>> # external/CMakeLists.txt:
>> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
>> PROJECT(EXTERNAL C)
>> SET(CMAKE_VERBOSE_MAKEFILE ON)
>> FILE(WRITE ${CMAKE_BINARY_DIR}/f.c "void f(void){}\n")
>> ADD_LIBRARY(f SHARED f.c)
>> INSTALL(TARGETS f DESTINATION lib)
>>
>> After configuring and building:
>>
>> % ls main external-prefix/src/external-build/libf.so
>> external-prefix/src/external-build/libf.so  main
>>
>> After "make clean" in CMAKE_BINARY_DIR:
>>
>> % ls main external-prefix/src/external-build/libf.so
>> ls: cannot access main: No such file or directory
>> external-prefix/src/external-build/libf.so
>>
>> The top-level project's target is gone whereas the external project's
>> one is intact, and [1] reports the same, i.e. the opposite of your
>> concern. Thus, could you boil down your issue to a minimal but
>> self-contained example for further investigation?
>>
>> Regards,
>>
>> Michael
>>
>> [1] http://www.mail-archive.com/cmake@cmake.org/msg35411.html
>> --
>>
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>>
>> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>>
>> Follow this link to subscribe/unsubscribe:
>> http://www.cmake.org/mailman/listinfo/cmake
>>
> 
> When Lori said "all targets are cleaned including the external
> packages" I think she meant that she would like the ExternalProject
> stamp files to remain intact across a "clean" such that the
> ExternalProject steps do not re-execute on the next make. Is that
> indeed what you meant, Lori?
> 
> If so, I do not know of an easy way to achieve that goal.
> 
> One thing that comes to mind is separating out the parts that you
> don't want to re-build after a clean into a separate project, and
> build/[install] that into a place where you can reference the
> built/installed products from a second project in which you frequently
> 'clean'...
> 
> Another alternative would be to avoid the top-level clean altogether,
> and simply go down into an individual external project's build tree
> and do the make clean in there so as to only clean the individual
> project you're immediately working with.
> 
> I've frequently thought we should cache/share ExternalProject builds
> across other multiple builds that could reference them.... but I
> hesitate to put legs on that idea because of possibly introducing easy
> ways to create giant tangled messes of projects with incompatible
> compiler/linker flags. It's worth keeping on the idea pile, though,
> and a motivated individual could certainly already achieve this by
> placing the build/install products of ExternalProject_Add calls in
> shared locations (i.e., in the HOME directory instead of as
> sub-directories of the present build tree).
> 
> 
> HTH,
> David

Ah, I see. Would it be an alternative to get the external projects'
stamp files out of the way, trigger the top-level project's clean
target and restore the stamp files right after that? If I add the
following to the above-noted top-level CMakeLists.txt

ExternalProject_Get_Property(external STAMP_DIR)
SET(DIRS "${STAMP_DIR}")  # Mind the separator.
ADD_CUSTOM_TARGET(tl-clean
    COMMAND ${CMAKE_COMMAND} -DDIRS=${DIRS} -DSEP=":"
        -P ${CMAKE_SOURCE_DIR}/savestampfiles.cmake
    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
        --target clean
    COMMAND ${CMAKE_COMMAND} -DDIRS=${DIRS} -DSEP=":"
        -P ${CMAKE_SOURCE_DIR}/restorestampfiles.cmake)

with

# savestampfiles.cmake:
STRING(REPLACE "${SEP}" ";" DIRS ${DIRS})
FOREACH(i IN LISTS DIRS)
    FILE(GLOB FILES ${i}/*)
    FOREACH(j IN LISTS FILES)
        FILE(RENAME ${j} ${j}.bak)
    ENDFOREACH()
ENDFOREACH()

# restorestampfiles.cmake:
STRING(REPLACE "${SEP}" ";" DIRS ${DIRS})
FOREACH(i IN LISTS DIRS)
    FILE(GLOB FILES ${i}/*.bak)
    FOREACH(j IN LISTS FILES)
        STRING(REGEX REPLACE "\\.bak\$" "" k ${j})
        FILE(RENAME ${j} ${k})
    ENDFOREACH()
ENDFOREACH()

a "make tl-clean" in CMAKE_BINARY_DIR cleans the top-level project
- not the external ones' targets - as expected, and a subsequent
"make" does not rebuild the external projects, as Lori probably
desires. Is there any catch with this approach?

Regards,

Michael


More information about the CMake mailing list