MantisBT - CMake
View Issue Details
0010395CMakeCMakepublic2010-03-09 11:062015-03-27 15:56
Alex Neundorf 
Brad King 
normalminoralways
closedfixed 
CMake-2-8 
CMake 2.8.4CMake 2.8.4 
0010395: cannot use add_dependencies() for imported libraries (together with externalproject_add())
Hi,

I want to use externalproject_add(), and in order to make sure that the external project (log4cplus) is built before my targets which link against it, I tried to create the dependency by creating an imported library, which depends on the externalproject-target, and then link against this imported library:

externalproject_add(EP_log4cplus
       SOURCE_DIR ${CMAKE_SOURCE_DIR}/Packages/log4cplus/log4cplus-1.0.3
       DOWNLOAD_COMMAND ""
       INSTALL_DIR ${CMAKE_BINARY_DIR}/Packages/Install
       CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
       BUILD_COMMAND make -j4
       )

add_library(log4cplus UNKNOWN IMPORTED)
set_property(TARGET log4cplus PROPERTY
  IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/Packages/Install/lib/liblog4cplus.so )
add_dependencies(log4cplus EP_log4cplus)

...
add_executable(foo main.cpp)
target_link_libraries(foo log4cplus)

When I try to do this, cmake complains:
trunk/build-281/shared/tests/SystemInformation> make
CMake Error at CMakeLists.txt:31 (add_dependencies):
  add_dependencies Adding dependency to non-existent target: log4cplus


It would be nice if this could be made to work.
Otherwise I didn't find an easier way than additionally to linking against the library, also make the target dependent on the external project target:

target_link_libraries(foo -llog4cplus)
add_dependencies(foo EP_log4cplus)

It would be much more elegant if I could avoid the add_dependencies() call here and instead just use the imported library.

Alex
No tags attached.
related to 0011598closed Brad King Two 'ALL_BUILD' projects into generated solution 
related to 0015414closed Brad King Consider add_dependencies for INTERFACE libraries. 
txt CMakeLists.txt (227) 2010-03-09 16:02
https://public.kitware.com/Bug/file/2948/CMakeLists.txt
Issue History
2010-03-09 11:06Alex NeundorfNew Issue
2010-03-09 11:06Alex NeundorfStatusnew => assigned
2010-03-09 11:06Alex NeundorfAssigned To => Brad King
2010-03-09 11:09Bill HoffmanAssigned ToBrad King => David Cole
2010-03-09 16:02Alex NeundorfFile Added: CMakeLists.txt
2010-03-09 16:07Alex NeundorfNote Added: 0019782
2010-07-27 15:49Brad KingNote Added: 0021499
2010-07-27 16:03Alex NeundorfNote Added: 0021502
2010-07-27 16:14Brad KingNote Added: 0021503
2010-07-27 16:16Brad KingNote Added: 0021504
2010-07-27 16:20Brad KingNote Added: 0021505
2010-07-28 16:00Nicole AucoinNote Added: 0021528
2010-07-28 16:03Brad KingNote Added: 0021529
2010-07-28 16:11Nicole AucoinNote Added: 0021530
2010-08-01 17:17devurandomNote Added: 0021591
2010-08-18 00:32David ColeAssigned ToDavid Cole => Brad King
2010-08-31 17:54David ColeTarget Version => CMake 2.8.3
2010-09-14 09:19David ColeNote Added: 0022218
2010-09-14 09:19David ColeTarget VersionCMake 2.8.3 =>
2010-11-10 12:58David ColeTarget Version => CMake 2.8.4
2010-11-22 09:16Brad KingNote Added: 0023477
2010-11-22 09:17Brad KingStatusassigned => closed
2010-11-22 09:17Brad KingResolutionopen => fixed
2010-12-13 08:53Brad KingRelationship addedrelated to 0011598
2011-01-12 07:24David ColeFixed in Version => CMake 2.8.4
2015-03-27 15:56Brad KingRelationship addedrelated to 0015414

Notes
(0019782)
Alex Neundorf   
2010-03-09 16:07   
The attached CMakeLists.txt basically shows what I want to do.
(for real use I would not want to make it depend on the "hello" target but on the external-project target).
I understand that cmake says it can't do this, because it doesn't have any rules for the imported target. Still it would be nice if this was possible.
Maybe something like a custom target could be created for each imported target, but with an empty body (does nothing, depends on nothing).
Then add_dependencies() could be used to add dependencies.

Alex
(0021499)
Brad King   
2010-07-27 15:49   
We just need a target property on the imported target that names another target known to provide it (the external project target in this case). For example:

  set_property(TARGET log4cplus PROPERTY DEPENDS EP_log4cplus)

says that in order to use log4cplus the EP_log4cplus target must be up to date.
When add_dependencies is asked to depend on log4cplus it can replace it with EP_log4cplus automatically.
(0021502)
Alex Neundorf   
2010-07-27 16:03   
" set_property(TARGET log4cplus PROPERTY DEPENDS EP_log4cplus)
 
says that in order to use log4cplus the EP_log4cplus target must be up to date."

Isn't that the same as
"add_dependencies(log4cplus EP_log4cplus)" tries to express ?

With the following cmake code:

add_library(log4cplus UNKNOWN IMPORTED)
set_property(TARGET log4cplus PROPERTY
   IMPORTED_LOCATION
   ${CMAKE_BINARY_DIR}/Packages/Install/lib/liblog4cplus.so )
add_dependencies(log4cplus EP_log4cplus) "
 
I wanted to make it work that
target_link_libraries(foo log4cplus)
automatically triggers building EP_log4cplus.
So the target_link_libraries() would then actually have to check that target property, not add_dependencies(), right ?
I mean, I wouldn't need the add_dependencies() then anymore, right ?

Alex
(0021503)
Brad King   
2010-07-27 16:14   
Yes, add_dependencies can be an interface to accomplish the same goal. I was thinking in the mindset that all information for an imported target is always set as properties.

Other than teaching add_dependencies() to accept imported targets as their first (but not second or later) argument, the place to change is cmComputeTargetDepends::AddTargetDepend. The code

  // Check the target's makefile first.
  cmTarget* dependee =
    depender->GetMakefile()->FindTarget(dependee_name);

  // Then search globally.
  if(!dependee)
    {
    dependee = this->GlobalGenerator->FindTarget(0, dependee_name);
    }

should be replaced with

  cmTarget* dependee =
    depender->GetMakefile()->FindTargetToUse(dependee_name);

Then the rest of the method must be taught to deal with imported targets.
(0021504)
Brad King   
2010-07-27 16:16   
Actually the rest of cmComputeTargetDepends::AddTargetDepend should not try to deal directly with imported targets. Instead, if it sees that it got an imported target from FindTargetToUse, it should recursively invoke itself on the GetUtilities() entries of the imported target and then return.
(0021505)
Brad King   
2010-07-27 16:20   
It looks like some of the VS generators have not been updated to use the results of cmComputeTargetDepends. Places like cmGlobalVisualStudio71Generator::WriteProjectDepends will also need to be taught to follow dependencies through imported targets and leave out the imported targets themselves.
(0021528)
Nicole Aucoin   
2010-07-28 16:00   
I'm struggling with this issue as well, I have a custom target that I'm adding that has to be run after a few external projects have finished. I've added the target properties to the custom target, but it's still running and failing before the output of the external project build steps are done.
Should I just try to craft another external project for my custom command?
(0021529)
Brad King   
2010-07-28 16:03   
If it is not an imported target then it is not the same as this issue. For a custom target, just use

  add_dependencies(mycustomtarget myexternalproject)
(0021530)
Nicole Aucoin   
2010-07-28 16:11   
Apologies, from the code snippet above it seemed that I had a similar issue with an external project. Your add_dependencies suggestion fixed my problem, thanks!

For reference: The DEPENDS in the add custom target can't point at an external project, so this doesn't work:
ExternalProject_Add(
  myexternalproject
[...]
)
ADD_CUSTOM_TARGET (mycustomtarget ALL
[...]
DEPENDS myexternalproject
[...]
)
(0021591)
devurandom   
2010-08-01 17:17   
I am also experiencing this issue: http://www.cmake.org/pipermail/cmake/2010-August/038646.html [^]
Would be nice to have a solution, however it may look like.
(0022218)
David Cole   
2010-09-14 09:19   
We will not be addressing this for the upcoming CMake 2.8.3 release. Partial progress towards this goal, but ran out of time. Changing target release value back to empty for now.
(0023477)
Brad King   
2010-11-22 09:16   
After some major rework of target dependencies in the VS generators to use cmComputeTargetDepends results, this feature is now possible:

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e01cce28 [^]