[CMake] intercomponent link dependencies?

Marcel Loose loose at astron.nl
Fri Jan 8 04:20:50 EST 2010


Hi Nico,

I think you should put the knowledge of the intercomponent link
dependencies in your FindXXX script. That way, you don't have to bother
the user of this third-party package with this knowledge.

BTW, if you're on Linux and your package contains shared libraries,
instead of static libraries, then, iff the package was properly built
(i.e. with the dependencies linked into the shared libs) you won't need
to specify these indirect dependencies.

Best regards,
Marcel Loose.


On Thu, 2010-01-07 at 21:20 +0100, Nico Schlömer wrote:
> Hi Ryan,
> 
> thanks very much for your answer.
> 
> For clarification, the package I would like to link against has (say)
> three components A, B, C, where A at link time needs symbols of B
> needs symbols of C needs symbols of some external libs.
> 
> I would like to make sure that the user can say
> 
>    FIND_PACKAGE( mypackage COMPONENTS A )
> 
> and then find in some variable *all* the dependencies that are
> required for linking, e.g.,
> MYPACKAGE_A_LIBRARY="a;b;c;/usr/local/lib/libblas.a".
> Right now (and which I'm not happy with), if a user would like to link
> against liba.a, he or she has to know that libb.a, libc.a, and
> /usr/local/lib/libblas.a have to be pulled in as well, and do so
> manually.
> 
> If on the other hand I have the same dependency situation with
> libraries that I *built*, the TARGET_LINK_LIBRARIES mechanism works
> very well. If I understand correctly, this cannot be applied to
> components in a FINDmypackage.cmake
> 
> Cheers,
> Nico
> 
> 
> 
> 
> 
> 
> On Thu, Jan 7, 2010 at 8:43 PM, Ryan Pavlik <rpavlik at iastate.edu> wrote:
> > Hello,
> >
> > My apologies in advance if I'm completely mis-reading your question and if
> > this answer seems way off base: just addressing what seemed like the most
> > likely issue from the info you provided.  (This link below [1] might help
> > you get better results out of mailing lists.)
> >
> > A script called by find_package(whatever) only normally sets variables in
> > CMake - it doesn't include or link any targets against any libraries.  (You
> > might have several targets in one CMake project, each that link against
> > different libraries)  So, in addition to the find_package(Mypackage), in
> > your CMakeLists.txt, you'll also want to do, for example:
> >
> > include_directories(${MYPACKAGE_INCLUDE_DIRS})
> > add_executable(myapp ${MYAPP_SOURCES})
> > target_link_libraries(myapp ${MYPACKAGE_FOOCOMP_LIBRARY}
> > ${MYPACKAGE_BARCOMP_LIBRARY})
> >
> > Note that according to the readme.txt in the modules directory of cmake (and
> > what seems to be convention), you'll note that your find module variables
> > should probably be named as above  ( PACKAGEUPPER_COMPONENTUPPER_LIBRARY ).
> >  Additionally, once you've run find_package_handle_standard_args,
> > if(PACKAGEUPPER_FOUND), you will probably want to do the following - this
> > example assumes you have some main library for the package that's always
> > needed to link against that package, and some additional optional libraries
> > specified as components (openscenegraph is an example of one of these types
> > of packages)
> >
> > set(PACKAGEUPPER_LIBRARIES ${PACKAGEUPPER_LIBRARY})
> > foreach(COMPONENT ${list_of_requested_and_found_components})
> >    list(APPEND PACKAGEUPPER_LIBRARIES ${PACKAGEUPPER_COMPONENT_LIBRARY})
> > endforeach()
> >
> >
> > I've attached a rather simple example of this kind of script - you'd of
> > course have your component search loop and the additional foreach loop
> > explained above added to this basic structure.  (and if you're doing it by
> > creating imported targets, you'll obviously use that code instead of the
> > direct file path code)
> >
> > Hope this helps!
> >
> > Ryan
> >
> >
> > [1] http://catb.org/~esr/faqs/smart-questions.html
> >
> > On 01/07/2010 09:19 AM, Nico Schlömer wrote:
> >>
> >> Hi Michael,
> >>
> >> I added to the FindMypackage.cmake in the FOREACH(COMPONENT) loop the
> >> following snipped
> >>
> >>       ADD_LIBRARY(${COMPONENT} STATIC IMPORTED)
> >>       SET_TARGET_PROPERTIES( ${COMPONENT} PROPERTIES
> >>                              IMPORTED_LOCATION
> >> "${${UPPERCOMPONENT}_LIBRARY}"
> >>                              LINK_INTERFACE_LIBRARIES
> >> "${${COMPONENT}_LINK_INTERFACE_LIBRARIES}"
> >>                            )
> >>
> >> where "${${UPPERCOMPONENT}_LIBRARY}" is the path of the respective
> >> library in the filesystem, and
> >> "${${COMPONENT}_LINK_INTERFACE_LIBRARIES}" a semicolon-separated list
> >> of dependencies of ${COMPONENT} (being either another component, or
> >> something of the form /path/to/libfancy.a). CMake does create all the
> >> Makefiles -- good -- but the dependency information doesn't sit in
> >> there (?).
> >> I expected that I can go like
> >>
> >> FIND_PACKAGE( Mypackage COMPONENTS foocomp barcomp )
> >>
> >> and that all the necessary stuff would be included automatically. --
> >> Well, now that I think about it this is probably a pipe dream. What
> >> would I further have to include?
> >>
> >> Cheers,
> >> Nico
> >>
> >>
> >>
> >> On Thu, Jan 7, 2010 at 12:47 PM, Michael Wild<themiwi at gmail.com>  wrote:
> >>
> >>>
> >>> Hi Nico
> >>>
> >>> In that case you need to do this:
> >>>
> >>> add_library(${COMPONENT} IMPORTED)
> >>> set_target_properties(${COMPONENT} PROPERTIES
> >>>  IMPORTED_LOCATION "${${COMPONENT}_LIBRARY}"
> >>>  LINK_INTERFACE_LIBRARIES "${${COMPONENT}_LINK_INTERFACE_LIBRARIES}"
> >>>  )
> >>>
> >>> where each of the components X has a variable X_LIBRARY containing its
> >>> path on the system (e.g. determined by find_library(X_LIBRARY ...)) and a
> >>> variable X_LINK_INTERFACE_LIBRARIES which you have to set outside the
> >>> foreach loop.
> >>>
> >>> HTH
> >>>
> >>> Michael
> >>>
> >>> On 7. Jan, 2010, at 11:51 , Nico Schlömer wrote:
> >>>
> >>>
> >>>>
> >>>> Hi Michael,
> >>>>
> >>>> thanks for the explanations.
> >>>>
> >>>> I'm indeed about to write a FindModule.cmake for a library which I did
> >>>> *not* write, but to certain components of which I'd like to link
> >>>> against using CMake (in a clean fashion).
> >>>> I'm FOREACHing through the components of the library, and upon trying to
> >>>> set
> >>>>
> >>>>  ADD_LIBRARY( ${COMPONENT} )
> >>>>
> >>>> cmake complains about
> >>>>
> >>>>  add_library cannot create target "A" because another target with the
> >>>>  same name already exists.  The existing target is a static library
> >>>> created
> >>>>  in source directory "/path/to/A".  See
> >>>>  documentation for policy CMP0002 for more details.
> >>>>
> >>>> Okay, so it exists already? Fine. Let's then
> >>>>
> >>>>  SET_TARGET_PROPERTIES( ${COMPONENT} PROPERTIES
> >>>> LINK_INTERFACE_LIBRARIES "B;C;" )
> >>>>
> >>>> -- but again, cmake complains that
> >>>>
> >>>>  set_target_properties Can not find target to add properties to: A
> >>>>
> >>>> TARGET_LINK_LIBRARIES doesn't work anyway as I'm not *building the
> >>>> libraries (cmake says).
> >>>>
> >>>> Hmmm...
> >>>> Nico
> >>>>
> >>>>
> >>>>
> >>>> On Thu, Jan 7, 2010 at 11:08 AM, Michael Wild<themiwi at gmail.com>  wrote:
> >>>>
> >>>>>
> >>>>> One quick question: Are these libraries created by you? In that case
> >>>>> you shouldn't write a FindMymodule.cmake, but a MymoduleConfig.cmake (see
> >>>>> the documentation of find_package).
> >>>>>
> >>>>> Anyhow, to define the transitive link dependencies you can either use
> >>>>> target_link_libraries(A LINK_INTERFACE_LIBRARIES B C) if your CMake is new
> >>>>> enough, or you can use set_target_properties(A PROPERTIES
> >>>>> LINK_INTERFACE_LIBRARIES "B;C"). Both solutions require that you use
> >>>>> add_library(X IMPORTED) (where X = A, B and C) and set their
> >>>>> IMPORTED_LOCATION property to the location on the file system. All of this
> >>>>> is full automatic if you write a MymoduleConfig.cmake, because then you can
> >>>>> use
> >>>>>
> >>>>> install_targets(A B C EXPORT MymoduleExports
> >>>>>  ARCHIVE DESTINATION lib
> >>>>>  LIBRARY DESTINATION lib
> >>>>>  RUNTIME DESTINATION bin
> >>>>>  PUBLIC_HEADER DESTINATION include
> >>>>>  )
> >>>>>
> >>>>> install(EXPORT MymoduleExports
> >>>>>  NAMESPACE Mymodule_
> >>>>>  DESTINATION share/mymodule/cmake
> >>>>>  )
> >>>>>
> >>>>> which will install a file
> >>>>> ${CMAKE_INSTALL_PREFIX}/share/mymodule/cmake/MymoduleExports.cmake
> >>>>> containing all the IMPORT stuff and which you can INCLUDE in your
> >>>>> MymoduleConfig.cmake.
> >>>>>
> >>>>>
> >>>>> I hope I could help a bit, otherwise tell us which case it is and I'll
> >>>>> be able to help more.
> >>>>>
> >>>>> Michael
> >>>>>
> >>>>>
> >>>>>
> >>>
> >>>
> >>
> >> _______________________________________________
> >> 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
> >>
> >
> > --
> > Ryan Pavlik
> > HCI Graduate Student
> > Virtual Reality Applications Center
> > Iowa State University
> >
> > rpavlik at iastate.edu
> > http://academic.cleardefinition.com
> > Internal VRAC/HCI Site: http://tinyurl.com/rpavlik
> >
> >
> _______________________________________________
> 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




More information about the CMake mailing list