Re: [CMake] intercomponent link dependencies?
On Fri, Jan 15, 2010 at 6:59 PM, Alexander Neundorf a.neundorf-w...@gmx.net wrote: On Friday 08 January 2010, Ryan Pavlik wrote: On Thu, Jan 7, 2010 at 4:00 PM, Jed Brown j...@59a2.org wrote: On Thu, 07 Jan 2010 15:54:33 -0600, Ryan Pavlik rpav...@iastate.edu wrote: If you use the _LIBRARIES variable, you don't need to even mess around with the imported targets thing Dumping recursive dependencies in *_LIBRARIES causes overlinking, they should only be there when linking statically. Jed So then actually should we all be doing imported targets in our find modules then? I didn't realize it: most of the ones I looked at that come In general, yes. It's just that this feature is still relatively new (2 years now), and I think no existing Find-module has been converted. In KDE we create and install such a file (but in KDE we create the libs ourselves, so this is not what this thread here is about), but just last week I converted our (KDEs) copy of FindQt4.cmake to create imported targets for the Qt libraries, so we finally get the optimized/debug libs handled properly: http://websvn.kde.org/trunk/KDE/kdelibs/cmake/modules/FindQt4.cmake?view=log It seems to be working properly as it is now, and plan to merge this with CMakes FindQt4.cmake soon. with cmake didn't use it, so I just worked around it - wrote a function that can safely remove those dupes instead :) Is there any drawback (besides slightly longer code) to doing the imported targets route? Most Find-modules can be included multiple times without problems, if you create imported targets and include this file multiple times cmake complains that the (imported) target already exists. So you have to check in the Find-module whether the imported target already exists if(NOT TARGET Qt4ImportedTarget__QtCore) ... and handle the case properly. And I recommend then, having created the imported target, still to set the normal cmake variable: set(QT_QTCORE_LIBRARY Qt4ImportedTarget__QtCore) so outside users will not notice that something has changed. One question regarding the cmake convenience variables one exposes. Say that I'm migrating a very simple FindFOO.cmake script from module to config mode. This script only looks for one library, one headers directory, and exposes to the user FOO_FOUND, FOO_INDLUDE_DIRS and FOO_LIBRARIES. In module mode, the user can also interact with the FOO_INCLUDE_DIR and FOO_LIBRARY (advanced) cache variables created by calls to find_path and find_library. As far as I understand, in config mode, these two cache variables no longer need to exist (because foo-config.cmake sets them without requiring cmake to find the headers/lib location). Indeed, I'm currently no longer exposing them, so my question is: is this the recommended practice? TIA Adolfo To improve diagnosability of potential issues I also recommend to give these imported targets a clear prefix, to give users a hint what may be going on in in case of a problem they get a linker error like Could not find library -lQt4ImportedTarget__QtCore This is much better as if they would get Could not find library -lQtCore, because this doesn't look like there might be anything special (like imported targets) involved in the issue. Alex ___ 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 ___ 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
Re: [CMake] intercomponent link dependencies?
On Fri, 15 Jan 2010 18:59:45 +0100, Alexander Neundorf a.neundorf-w...@gmx.net wrote: In general, yes. Neat, I'd never heard of this being recommended. It's just that this feature is still relatively new (2 years now), and I think no existing Find-module has been converted. :-/ It looks like it would be well worth thinking critically about whether the _QT4_ADJUST_LIB_VARS macro is the best possible interface for setting this up, then put that functionality in a module that is distributed by CMake. Otherwise we're never going to get a library of Find* modules that do this correctly because hacking the module so that It works for me is lower incremental cost (for each value of me) than figuring out how to do it right. Jed ___ 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
Re: [CMake] intercomponent link dependencies?
On Friday 08 January 2010, Ryan Pavlik wrote: On Thu, Jan 7, 2010 at 4:00 PM, Jed Brown j...@59a2.org wrote: On Thu, 07 Jan 2010 15:54:33 -0600, Ryan Pavlik rpav...@iastate.edu wrote: If you use the _LIBRARIES variable, you don't need to even mess around with the imported targets thing Dumping recursive dependencies in *_LIBRARIES causes overlinking, they should only be there when linking statically. Jed So then actually should we all be doing imported targets in our find modules then? I didn't realize it: most of the ones I looked at that come In general, yes. It's just that this feature is still relatively new (2 years now), and I think no existing Find-module has been converted. In KDE we create and install such a file (but in KDE we create the libs ourselves, so this is not what this thread here is about), but just last week I converted our (KDEs) copy of FindQt4.cmake to create imported targets for the Qt libraries, so we finally get the optimized/debug libs handled properly: http://websvn.kde.org/trunk/KDE/kdelibs/cmake/modules/FindQt4.cmake?view=log It seems to be working properly as it is now, and plan to merge this with CMakes FindQt4.cmake soon. with cmake didn't use it, so I just worked around it - wrote a function that can safely remove those dupes instead :) Is there any drawback (besides slightly longer code) to doing the imported targets route? Most Find-modules can be included multiple times without problems, if you create imported targets and include this file multiple times cmake complains that the (imported) target already exists. So you have to check in the Find-module whether the imported target already exists if(NOT TARGET Qt4ImportedTarget__QtCore) ... and handle the case properly. And I recommend then, having created the imported target, still to set the normal cmake variable: set(QT_QTCORE_LIBRARY Qt4ImportedTarget__QtCore) so outside users will not notice that something has changed. To improve diagnosability of potential issues I also recommend to give these imported targets a clear prefix, to give users a hint what may be going on in in case of a problem they get a linker error like Could not find library -lQt4ImportedTarget__QtCore This is much better as if they would get Could not find library -lQtCore, because this doesn't look like there might be anything special (like imported targets) involved in the issue. Alex ___ 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
Re: [CMake] intercomponent link dependencies?
On 13. Jan, 2010, at 1:55 , Nico Schlömer wrote: Pheeew.. So I've now been trying to include one *single* library from an external project (liba.a) into my own project, writing FindA.cmake. Somehow I still fail to apply the dependencies correctly. What I do is [...] ADD_LIBRARY(A STATIC IMPORTED) SET_TARGET_PROPERTIES( A PROPERTIES IMPORTED_LOCATION ${A_LIBRARY} %set above LINK_INTERFACE_LIBRARIES ${A_LINK_INTERFACE_LIBRARIES} % set above to something like /usr/lib/liblapack.a;/usr/lib/blas.a; ) [...] [Setting TARGET_LINK_LIBRARIES(A LINK_INTERFACE_LIBRARIES ${A_LINK_INTERFACE_LIBRARIES} ) did *not* work for me.] Now, in the main CMakeLists.txt I say Find( A REQUIRED ), and I was naivly expecting that upon TARGET_LINK_LIBRARIES ( main.out A ) *all* the dependent libraries would be pulled in too. This is not the case. :/ What am I missing? Cheers, Nico Coming to think of it: Why don't you simply list ${A_LIBRARY}, /usr/lib/liblapack.a and /usr/lib/blas.a (shouldn't that be libblas.a?) in A_LIBRARIES and the use that in TARGET_LINK_LIBRARIES? Simpler for you and less work for CMake... Michael PS: I can't tell for sure from what you show, but you REALLY should discover lapack and blas instead of hardcoding their paths, e.g. using FindBLAS and FindLAPACK (which admittedly have their deficiencies) ___ 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
Re: [CMake] intercomponent link dependencies?
On 13. Jan, 2010, at 11:51 , Nico Schlömer wrote: Coming to think of it: Why don't you simply list ${A_LIBRARY}, /usr/lib/liblapack.a and /usr/lib/blas.a (shouldn't that be libblas.a?) in A_LIBRARIES and the use that in TARGET_LINK_LIBRARIES? Simpler for you and less work for CMake... When using ${A_LIBRARY}, ${B_LIBRARY}, ${G_LIBRARY}, and ${Z_LIBRARY} (which may all depend on blas and lapack, I'd like to avoid overlinking. Overlinking is actually only an issue for dynamic libraries. So as long as you're absolutely sure that you only have static libraries, you're fine. PS: I can't tell for sure from what you show, but you REALLY should discover lapack and blas instead of hardcoding their paths, e.g. using FindBLAS and FindLAPACK (which admittedly have their deficiencies) Well, there may be many different versions of BLAS/LAPACK installed (think of different compilers, compiler versions, for example). Against which one of those ${A_LIBRARY} is compiled is hardcoded in one of the installation files of ${A_LIBRARY}. Those I then parse and use that info and use that in FindA.cmake. Fair enough, if A really requires a specific version and that information is readily available. Does the IMPORTED_LINK_INTERFACE_LIBRARIES thing work? I just noticed that there is also IMPORTED_LINK_DEPENDENT_LIBRARIES to list libraries that are an implementation detail of a shared library and might to be specified explicitly on the link line (such as OS X). Not sure how the behavior for static libraries is, though. 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
Re: [CMake] intercomponent link dependencies?
Overlinking is actually only an issue for dynamic libraries. So as long as you're absolutely sure that you only have static libraries, you're fine. Oh, I was thinking it is *unclean* to have a link line like -llibrarya /usr/local/local/liblapack.a --llibraryb /usr/local/local/liblapack.a (1) -- which (disappointingly?) is exactly what happens now that I have FindLibraryA.cmake and FindLibraryB.cmake, both equipped with SET_TARGET_PROPERTIES(A PROPERTIES IMPORTED_LOCATION ${A_LIBRARY} IMPORTED_LINK_INTERFACE_LIBRARIES ${A_LINK_INTERFACE_LIBRARIES} ) where both ${A_LINK_INTERFACE_LIBRARIES} and ${B_LINK_INTERFACE_LIBRARIES} contain /usr/local/local/liblapack.a. Does the IMPORTED_LINK_INTERFACE_LIBRARIES thing work? So, yeap, it works, but I expected CMake to clean up after me dependency-wise -- instead of (1), this -llibrarya --llibraryb /usr/local/local/liblapack.a (1') would be sufficient. My knowledge on the linking process itself is unfortunately not deep enough to tell if that makes an actual difference. Cheers, Nico ___ 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
Re: [CMake] intercomponent link dependencies?
On 13. Jan, 2010, at 13:51 , Nico Schlömer wrote: Overlinking is actually only an issue for dynamic libraries. So as long as you're absolutely sure that you only have static libraries, you're fine. Oh, I was thinking it is *unclean* to have a link line like -llibrarya /usr/local/local/liblapack.a --llibraryb /usr/local/local/liblapack.a (1) -- which (disappointingly?) is exactly what happens now that I have FindLibraryA.cmake and FindLibraryB.cmake, both equipped with SET_TARGET_PROPERTIES(A PROPERTIES IMPORTED_LOCATION ${A_LIBRARY} IMPORTED_LINK_INTERFACE_LIBRARIES ${A_LINK_INTERFACE_LIBRARIES} ) where both ${A_LINK_INTERFACE_LIBRARIES} and ${B_LINK_INTERFACE_LIBRARIES} contain /usr/local/local/liblapack.a. No, for static linking you often NEED to specify a library multiple times, e.g. if you have mutually dependent libraries. Problem with static linking is this: The linker keeps a running list of unresolved symbols. Then, when a static library comes along, it tries to resolve as many symbols as possible, but ONLY takes the required ones, discarding the ones not used. If the newly imported symbols again contain unresolved references, they are added to the list. And then it continues its way until the input is exhausted. If all the symbols are now resolved, everything is fine, otherwise it will complain to the user. So, in static linking the ordering on the command line is important, and if you have mutually dependent libraries, you might need to list some libraries multiple times. The thing which works for me (usually) is this: gcc -o myexe src1.o src2.o src3.o /usr/lib/liba.a /usr/lib/libb.a /usr/libc.a /usr/lib/libb.a /usr/lib/liba.a As you can see, the libraries are listed as a b c b a such that if b and c need symbols from a, they appear after a (the same for c needing symbols from b). If a needs symbols from b or c, that is covered in the first pass. With static linking, the linker just picks what is needed. No information is retained from which library these symbols came (after all, they are now part of the final product) Does the IMPORTED_LINK_INTERFACE_LIBRARIES thing work? So, yeap, it works, but I expected CMake to clean up after me dependency-wise -- instead of (1), this -llibrarya --llibraryb /usr/local/local/liblapack.a (1') You shouldn't use -l flag, better specify the full path (CMake automatically adds the -l flag if a library name is not a target or a path). Further, I either it's a typo or really strange, but when using -l, the lib prefix must be dropped (and the --l is definitely a typo). would be sufficient. My knowledge on the linking process itself is unfortunately not deep enough to tell if that makes an actual difference. In your case, it might be, but that CMake can't know that (as I explained above). HTH 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
Re: [CMake] intercomponent link dependencies?
On 1/13/10 6:51 AM, Nico Schlömer wrote: Overlinking is actually only an issue for dynamic libraries. So as long as you're absolutely sure that you only have static libraries, you're fine. Oh, I was thinking it is *unclean* to have a link line like -llibrarya /usr/local/local/liblapack.a --llibraryb /usr/local/local/liblapack.a (1) -- which (disappointingly?) is exactly what happens now that I have FindLibraryA.cmake and FindLibraryB.cmake, both equipped with SET_TARGET_PROPERTIES(A PROPERTIES IMPORTED_LOCATION ${A_LIBRARY} IMPORTED_LINK_INTERFACE_LIBRARIES ${A_LINK_INTERFACE_LIBRARIES} ) where both ${A_LINK_INTERFACE_LIBRARIES} and ${B_LINK_INTERFACE_LIBRARIES} contain /usr/local/local/liblapack.a. Does the IMPORTED_LINK_INTERFACE_LIBRARIES thing work? So, yeap, it works, but I expected CMake to clean up after me dependency-wise -- instead of (1), this -llibrarya --llibraryb /usr/local/local/liblapack.a (1') would be sufficient. My knowledge on the linking process itself is unfortunately not deep enough to tell if that makes an actual difference. Cheers, Nico You could use the CleanLibraryList module I posted a few emails ago: just make a list that contains all the libraries you are going to link your target against, and then just run clean_library_list on it before doing so. Ryan -- Ryan Pavlik Human-Computer Interaction Graduate Student Virtual Reality Applications Center Iowa State University rpav...@iastate.edu http://academic.cleardefinition.com/ ___ 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
Re: [CMake] intercomponent link dependencies?
On Wed, 13 Jan 2010 13:51:57 +0100, Nico Schlömer nico.schloe...@gmail.com wrote: Overlinking is actually only an issue for dynamic libraries. So as long as you're absolutely sure that you only have static libraries, you're fine. Oh, I was thinking it is *unclean* to have a link line like Overlinking is orthogonal to this. Suppose we have libA depending on libB, but consumers of libA never call into libB directly. With shared libraries, libA.so will reference libB.so and the user only needs to link with -lA. Overlinking means using -lA -lB which means that e.g. an ABI change in libB requires not just rebuilding libA, but also the client application. With static libs, you have no choice. -llibrarya /usr/local/local/liblapack.a --llibraryb /usr/local/local/liblapack.a (1) [...] So, yeap, it works, but I expected CMake to clean up after me dependency-wise -- instead of (1), this -llibrarya --llibraryb /usr/local/local/liblapack.a (1') This cannot be done automatically because some people end up with dependency loops and CMake does not know the dependency graph. Jed ___ 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
Re: [CMake] intercomponent link dependencies?
On Wed, 13 Jan 2010 07:04:46 -0600, Ryan Pavlik rpav...@iastate.edu wrote: You could use the CleanLibraryList module I posted a few emails ago: just make a list that contains all the libraries you are going to link your target against, and then just run clean_library_list on it before doing so. The trouble is that the list of libraries is order-dependent so sorting them will definitely not work. Furthermore, list (REMOVE_DUPLICATES lst) keeps the first copy and drops subsequent ones which means that some libs will be neglected. If there are no dependency loops, you can reverse the list, REMOVE_DUPLICATES, and reverse it again (so that only the last occurrence of the library shows up). If there are loops, the library will need to be explicitly linked more than once, but CMake does not retain sufficient information to determine when this is safe, therefore it cannot be provided as a general function (so you can only clean the list when you know that the underlying dependency graph is acyclic). Jed ___ 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
Re: [CMake] intercomponent link dependencies?
On 1/13/10 7:22 AM, Jed Brown wrote: On Wed, 13 Jan 2010 07:04:46 -0600, Ryan Pavlikrpav...@iastate.edu wrote: You could use the CleanLibraryList module I posted a few emails ago: just make a list that contains all the libraries you are going to link your target against, and then just run clean_library_list on it before doing so. The trouble is that the list of libraries is order-dependent so sorting them will definitely not work. Furthermore, list (REMOVE_DUPLICATES lst) keeps the first copy and drops subsequent ones which means that some libs will be neglected. If there are no dependency loops, you can reverse the list, REMOVE_DUPLICATES, and reverse it again (so that only the last occurrence of the library shows up). If there are loops, the library will need to be explicitly linked more than once, but CMake does not retain sufficient information to determine when this is safe, therefore it cannot be provided as a general function (so you can only clean the list when you know that the underlying dependency graph is acyclic). Jed Ah, good to know - it worked with the library group I was configuring (which is indeed acyclic), so I didn't look any further into the innards of linking. I will update my script accordingly. Thanks! Ryan -- Ryan Pavlik Human-Computer Interaction Graduate Student Virtual Reality Applications Center Iowa State University rpav...@iastate.edu http://academic.cleardefinition.com/ ___ 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
Re: [CMake] intercomponent link dependencies?
Pheeew.. So I've now been trying to include one *single* library from an external project (liba.a) into my own project, writing FindA.cmake. Somehow I still fail to apply the dependencies correctly. What I do is [...] ADD_LIBRARY(A STATIC IMPORTED) SET_TARGET_PROPERTIES( A PROPERTIES IMPORTED_LOCATION ${A_LIBRARY} %set above LINK_INTERFACE_LIBRARIES ${A_LINK_INTERFACE_LIBRARIES} % set above to something like /usr/lib/liblapack.a;/usr/lib/blas.a; ) [...] [Setting TARGET_LINK_LIBRARIES(A LINK_INTERFACE_LIBRARIES ${A_LINK_INTERFACE_LIBRARIES} ) did *not* work for me.] Now, in the main CMakeLists.txt I say Find( A REQUIRED ), and I was naivly expecting that upon TARGET_LINK_LIBRARIES ( main.out A ) *all* the dependent libraries would be pulled in too. This is not the case. :/ What am I missing? Cheers, Nico On Fri, Jan 8, 2010 at 11:00 AM, Nico Schlömer nico.schloe...@gmail.com wrote: Hi, I am guessing that you're putting the detection for every library that your app can/must use into one find module, when you actually probably should have a directory in your source tree added to your CMAKE_MODULE_PATH that contains a large number of find modules, some of which are interdependent (just like how the example I sent uses find_package(BLAS) - which is a module that comes bundled with cmake). -- Exactly! I'm thinking now that this is indeed a good solution: Writing *separate* FindLibraryX.cmake files for all the libraries included in MyPackage and putting all the dependency information in there; then, make a meta .cmake file which will allow for specifying the keyword COMPONENTS, and where all the meta information goes (e.g., version number of MyPackage). Minor drawbacks of this approach I find would be that the fact that all those libraries live under one roof is entirely discarded, that is, that they all share a common LIB directory, INCLUDE directory, all have the same version string (namely the one of MyPackage). Plus also, new libraries included require their own new FindNewLib.cmake to be created, while all FindLibrary*.cmake would actually be the same file, except for the dependency info (nasty (?) code duplication). How I came to think about COMPONENTS in the first place was looking at FindBoost.cmake which I *thought does what I'm doing -- except for the intercomponent linking info. Cheers! Nico ___ 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
Re: [CMake] intercomponent link dependencies?
On Thu, 7 Jan 2010 19:24:19 -0600, Ryan Pavlik rpav...@iastate.edu wrote: So then actually should we all be doing imported targets in our find modules then? Many/most Find* modules don't work with static libraries. Jed ___ 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
Re: [CMake] intercomponent link dependencies?
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 rpav...@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 Wildthem...@gmail.com wrote: Hi Nico In that case you need to do this: add_library(${COMPONENT} IMPORTED)
Re: [CMake] intercomponent link dependencies?
On 8. Jan, 2010, at 10:20 , Marcel Loose wrote: 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. Again, this is very difficult to do. Depending on HOW the static library was built (i.e. which optional parts have been enabled) the transitive link dependencies change. E.g. if you have libcurl.a you need to find out whether that thing has been compiled against OpenSSL, GnuTLS or Mozilla NSS or no SSL implementation at all. Good luck with that... And then on Windows you currently can't determine whether that .lib file is a link-library (i.e. used to link against a .dll) or actually a static library. And if you just throw them in for good measure, you run into over-linking issues: http://wiki.mandriva.com/en/Overlinking Static linking is and will always be a mess (unless all projects install a CMake-file containing the appropriate add_library(XXX IMPORTED) and IMPORTED_LINK_INTERFACE_LIBRARIES stanzas, or CMake learns to use libtool .la files and all projects create them and write them correctly). Just my 2c. 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
Re: [CMake] intercomponent link dependencies?
Hi, 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. Yeah well, they're all static from a to z. :) --Nico ___ 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
Re: [CMake] intercomponent link dependencies?
Hi, I am guessing that you're putting the detection for every library that your app can/must use into one find module, when you actually probably should have a directory in your source tree added to your CMAKE_MODULE_PATH that contains a large number of find modules, some of which are interdependent (just like how the example I sent uses find_package(BLAS) - which is a module that comes bundled with cmake). -- Exactly! I'm thinking now that this is indeed a good solution: Writing *separate* FindLibraryX.cmake files for all the libraries included in MyPackage and putting all the dependency information in there; then, make a meta .cmake file which will allow for specifying the keyword COMPONENTS, and where all the meta information goes (e.g., version number of MyPackage). Minor drawbacks of this approach I find would be that the fact that all those libraries live under one roof is entirely discarded, that is, that they all share a common LIB directory, INCLUDE directory, all have the same version string (namely the one of MyPackage). Plus also, new libraries included require their own new FindNewLib.cmake to be created, while all FindLibrary*.cmake would actually be the same file, except for the dependency info (nasty (?) code duplication). How I came to think about COMPONENTS in the first place was looking at FindBoost.cmake which I *thought does what I'm doing -- except for the intercomponent linking info. Cheers! Nico ___ 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
[CMake] intercomponent link dependencies?
Hi, I'm writing a FintMymodule.cmake file for a set of libraries (read: components), and with the given examples in the official CMake/Modules folder it comes along nicely. One thing I couldn't figure out now is how to set link dependencies between the different components; that is, if I link against component A not only libA is required for linking but also libB and libC. With regular libraries I understand I can pull this is in by TARGET_LINK_LIBRARIES.. Cheers, Nico ___ 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
Re: [CMake] intercomponent link dependencies?
On 7. Jan, 2010, at 10:51 , Nico Schlömer wrote: Hi, I'm writing a FintMymodule.cmake file for a set of libraries (read: components), and with the given examples in the official CMake/Modules folder it comes along nicely. One thing I couldn't figure out now is how to set link dependencies between the different components; that is, if I link against component A not only libA is required for linking but also libB and libC. With regular libraries I understand I can pull this is in by TARGET_LINK_LIBRARIES.. Cheers, Nico 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
Re: [CMake] intercomponent link dependencies?
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 them...@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
Re: [CMake] intercomponent link dependencies?
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 them...@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
Re: [CMake] intercomponent link dependencies?
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 them...@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 them...@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
Re: [CMake] intercomponent link dependencies?
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 Wildthem...@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 Wildthem...@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
Re: [CMake] intercomponent link dependencies?
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 rpav...@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 Wildthem...@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
Re: [CMake] intercomponent link dependencies?
Ah, so if those components are always necessary (that is, A always needs B, and B always needs C), there's no need to use the components option. Just zip through them in this way - _LIBRARY (cache var) is a single library, _LIBRARIES (not a cache var) is the list containing the library and all its dependencies. If you use the _LIBRARIES variable, you don't need to even mess around with the imported targets thing, though you can if you really want to. I've pasted an untested full example (done both ways - so actually 2 examples) using what you've explained in your last email. It's at the bottom of this email, after the quote. Hope this helps! Ryan On 01/07/2010 02:20 PM, 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 # - try to find MyPackage library # # Example-FindMyPackage.cmake # # This example is for a fairly in-depth library that has four # internal dependencies as well as an external dependency. # The dependency tree is described below, in graphviz/dot format, and you # can remove the #'s from the following lines and run it through graphviz, # with this command: dot dependencies.dot -O -Tpdf # # --- start of dependencies.dot --- # digraph { #BLAS; #subgraph cluster_mypackage { #label = Components that are part of MyPackage; #libmypackagecore - libmypackagea; #libmypackagea - libmypackageb; #libmypackageb - libmypackagec; #libmypackagec - BLAS; #} # } # --- end of dependencies.dot --- # # Because our imaginary component c requires BLAS and BLAS needs some # linker flags, MYPACKAGE_..._LINKER_FLAGS joins the usual group of # _LIBRARY/_LIBRARIES and _INCLUDE_DIR/_INCLUDE_DIRS variables. If # you don't use a library like that, you don't need to include the # lines dealing with that group of variables. # # Start of what would be a minimal module documentation blog: # # Cache Variables: (probably not for direct use in CMakeLists.txt) # MYPACKAGE_LIBRARY # MYPACKAGE_INCLUDE_DIR # MYPACKAGE_a_LIBRARY # MYPACKAGE_a_INCLUDE_DIR # MYPACKAGE_b_LIBRARY # MYPACKAGE_b_INCLUDE_DIR # MYPACKAGE_c_LIBRARY # MYPACKAGE_c_INCLUDE_DIR # # Non-cache variables you might use in your CMakeLists.txt: # MYPACKAGE_FOUND # MYPACKAGE_MARK_AS_ADVANCED - whether to mark our vars as advanced even #if we don't find this library. # # MYPACKAGE_LIBRARIES # MYPACKAGE_INCLUDE_DIRS # MYPACKAGE_LINKER_FLAGS # # MYPACKAGE_a_LIBRARIES # MYPACKAGE_a_INCLUDE_DIRS # MYPACKAGE_a_LINKER_FLAGS # # MYPACKAGE_b_LIBRARIES # MYPACKAGE_b_INCLUDE_DIRS # MYPACKAGE_b_LINKER_FLAGS # # MYPACKAGE_c_LIBRARIES # MYPACKAGE_c_INCLUDE_DIRS # MYPACKAGE_c_LINKER_FLAGS # # Use this module this way: # find_package(MyPackage) # include_directories(MYPACKAGE_INCLUDE_DIRS) # add_executable(myapp ${SOURCES}) # target_link_libraries(myapp ${MYPACKAGE_LIBRARIES}) # set_property(TARGET myapp PROPERTY LINK_FLAGS ${MYPACKAGE_LINKER_FLAGS}) # # Requires these CMake modules: # FindPackageHandleStandardArgs (CMake standard module) # # Original Author: # 2009-2010 Ryan Pavlik rpav...@iastate.edu abir...@ryand.net # http://academic.cleardefinition.com # Iowa State University HCI Graduate Program/VRAC find_library(MYPACKAGE_LIBRARY NAMES mypackagecore PATHS ${MYPACKAGE_ROOT} PATH_SUFFIXES lib) find_path(MYPACKAGE_INCLUDE_DIR NAMES mypackage/mypackage.h PATHS ${MYPACKAGE_ROOT} PATH_SUFFIXES include) # Assuming that the components are named libmypackagea, libmypackageb, etc foreach(lib a b c) find_library(MYPACKAGE_${lib}_LIBRARY NAMES mypackage${lib} PATHS ${MYPACKAGE_ROOT} PATH_SUFFIXES lib) find_path(MYPACKAGE_${lib}_INCLUDE_DIR NAMES mypackage/${lib}/${lib}.h PATHS ${MYPACKAGE_ROOT} PATH_SUFFIXES include) endforeach() # see /usr/share/cmake-2.x/Modules/FindBLAS.cmake for the variables this will define if(NOT BLAS_FOUND) find_package(BLAS QUIETLY) endif() # handle the QUIETLY and REQUIRED arguments and set xxx_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs)
Re: [CMake] intercomponent link dependencies?
On Thu, 07 Jan 2010 15:54:33 -0600, Ryan Pavlik rpav...@iastate.edu wrote: If you use the _LIBRARIES variable, you don't need to even mess around with the imported targets thing Dumping recursive dependencies in *_LIBRARIES causes overlinking, they should only be there when linking statically. Jed ___ 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
Re: [CMake] intercomponent link dependencies?
Wow, thanks for the elaborate answer! I learn a lot just going through the examples. One thing for me to understand first: Ah, so if those components are always necessary (that is, A always needs B, and B always needs C), there's no need to use the components option. Ah, I found the components thing neat for its syntax, as one can (quite semantically) say FIND_PACKAGE( MyPackage COMPONENTS coolCompOfMyPackage anotherOne ) # very much like done in FindBoost.cmake Of course there's not only a,b,c, but a whole set of libraries a,...,z under the roof of MyPackage with a more or less complicated dependency tree. Also, it would depend on the installation of MyPackage whether all the libraries are actually there; for example, and installation with only b and c would be possible. Anyway, instead of hardcoding a,b,c one could possible FOREACH through a (hardcoded) list of components, such as SET( ALL_LIBS a b c d [...] z ) I guess how one would do that with the above suggestion is to further define MYPACKAGE_{$LIB}_FOUND, and then in the CMakeLists.txt FIND_PACKAGE( MyPackage ) IF( MYPACKAGE_a_FOUND ) # add the necessary stuff to TARGET_LINK_LIBRARIES, for example ELSE() MESSAGE( FATAL_ERROR Too bad, we need a. ) END() The disadvantage I see here is that FindMypackage.cmake had to be adapted every time a new library makes it into MyPackage. Also, the code in CMakeLists.txt would get longer than what I thought would be nice [being: FIND_PACKAGE( MyPackage COMPONENTS a g t ) # FATAL_ERRORing out if either of a, g, t hasn't been found, # otherwise providing a slim ${MyPACKAGE_LIBRARIES} to be appended to # TARGET_LINK_LIBRARIES or something. ]. Cheers, Nico ___ 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
Re: [CMake] intercomponent link dependencies?
On Thu, Jan 7, 2010 at 4:00 PM, Jed Brown j...@59a2.org wrote: On Thu, 07 Jan 2010 15:54:33 -0600, Ryan Pavlik rpav...@iastate.edu wrote: If you use the _LIBRARIES variable, you don't need to even mess around with the imported targets thing Dumping recursive dependencies in *_LIBRARIES causes overlinking, they should only be there when linking statically. Jed So then actually should we all be doing imported targets in our find modules then? I didn't realize it: most of the ones I looked at that come with cmake didn't use it, so I just worked around it - wrote a function that can safely remove those dupes instead :) Is there any drawback (besides slightly longer code) to doing the imported targets route? Here's that CleanLibraryList.cmake file: # - A smarter replacement for list(REMOVE_DUPLICATES) for library lists # # clean_library_list(listvar [additional list items...]) - where # WHATEVER_LIBRARIES is the name of a variable, such as a variable being # created in a Find script. # # Removes duplicates from the list then sorts while preserving optimized, # debug, and general labeling # # Requires CMake 2.6 or newer (uses the 'function' command) # # Original Author: # 2009-2010 Ryan Pavlik rpav...@iastate.edu abir...@ryand.net # http://academic.cleardefinition.com # Iowa State University HCI Graduate Program/VRAC function(clean_library_list _var) # combine variable's current value with additional list items set(_work ${${_var}} ${ARGN}) if(_work) # Turn each of optimized, debug, and general into flags # prefixed on their respective library (combining list items) string(REGEX REPLACE optimized; 1CLL%O% _work ${_work}) string(REGEX REPLACE debug; 1CLL%D% _work ${_work}) string(REGEX REPLACE general; 1CLL%G% _work ${_work}) # clean up list list(REMOVE_DUPLICATES _work) list(SORT _work) # Split list items back out again: turn prefixes into the # library type flags. string(REGEX REPLACE 1CLL%G% general; _work ${_work}) string(REGEX REPLACE 1CLL%D% debug; _work ${_work}) string(REGEX REPLACE 1CLL%O% optimized; _work ${_work}) # Return _work set(${_var} ${_work} PARENT_SCOPE) endif() endfunction() -- Ryan Pavlik HCI Graduate Student Virtual Reality Applications Center Iowa State University rpav...@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
Re: [CMake] intercomponent link dependencies?
Not a problem - figured putting together some clean templates could probably help me and my colleagues out too, anyway. Your comment about the syntax makes me understand a bit better... MyPackage isn't a name, it's a placeholder for one of the many general packages of third party functionality that you use. I am guessing that you're putting the detection for every library that your app can/must use into one find module, when you actually probably should have a directory in your source tree added to your CMAKE_MODULE_PATH that contains a large number of find modules, some of which are interdependent (just like how the example I sent uses find_package(BLAS) - which is a module that comes bundled with cmake). Once you make enough cmake-based build systems, you'll probably find yourself hanging on to a repository of assorted find modules. I've pasted a simple example here, since it pretty well meshes with a common use case. The sample project uses OpenSceneGraph (plus its optional components osgDB and osgUtil), as well as a large suite of libraries with internal dependencies known as VR Juggler 2.2. OSG has modules that come with CMake, while I had to make my own for VR Juggler. - cmake_minimum_required(VERSION 2.6) project(minimal-vrjuggler-osg) # Locally-developed modules dist'ed with this app list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) # This should handle all dependencies, including OpenGL, GMTL, and so on find_package(VRJuggler22 REQUIRED) find_package(OpenSceneGraph REQUIRED osgUtil osgDB) # Search for includes in these directories include_directories( ${OPENSCENEGRAPH_INCLUDE_DIRS} ${VRJUGGLER22_INCLUDE_DIRS}) # Build the project set(SOURCES main.cpp theapp.cpp theapp.h) add_executable(example ${SOURCES}) target_link_libraries(example ${OPENSCENEGRAPH_LIBRARIES} ${VRJUGGLER22_LIBRARIES}) --- That's an entire functional CMakeLists.txt file - though behind the scenes we're linking to a ton of libraries in a ton of different directories. (Read through the cmake docs online a few times - you got the imported target thing but missed the REQUIRED flag that you can pass to find_package... If you use the FindPackageHandleDefaultArgs call as suggested by the readme.txt, it takes care of handling QUIET and REQUIRED for you.) So, I made a separate FindWhatever.cmake file for each library that belongs to VR Juggler, and set it up like the examples from the last email, treating them each as a separately-usable library (since they are). Since most of the time, however, if you're writing a VR Juggler app, you're going to want a large chunk of the tree by default, I made a FindVRJuggler22.cmake meta-module sort of thing: means that for most folks, all that's needed in the cmakelists is find_package(VRJuggler22 REQUIRED) or at most find_package(VRJuggler22 COMPONENTS VRJOGL22 Tweek12). So, I have a whole bundle of find modules written (actually, in total, I have ~20 find modules in a directory I share between all my projects, with another ~20 modules that provide functions: some utilities for find scripts, some for use directly by a cmakelists) that I share between my projects, but because each find module knows its own dependencies, it works it out. In that sense, more files is better: it means you're keeping your find modules well-focused and modular. (If the library comes in a separate zip/targz file, it probably should have a separate find module - don't just smush them all into one massive file.) Here's the dependency tree for the VR Juggler find modules - each node is a separate .cmake file that goes in a directory in my source tree, and each of those find modules are set up just like the examples from the last email. (in graphviz/DOT format) : digraph { // a module that, when included, provides a function definition that can remove duplicate // libraries from a _LIBRARIES list safely, without breaking the DEBUG RELEASE GENERAL annotations // I wrote this one, so it's in my project in a directory with the custom find modules CleanLibraryList; subgraph cluster_bundled { label = Included with cmake 2.8.0; FindBoost; FindOpenSceneGraph - { FindOpenThreads; FindosgALL; } } subgraph cluster_vrjuggler22 { label = VR Juggler 2.2 suite: All require CleanLibraryList and CleanDirectoryList, and recommend FindFlagpoll; FindTweek12 - FindVPR20; FindJCCL12 - FindVPR20; FindGadgeteer12 - { FindJCCL12; FindVPR20; } FindSonix12 - FindVPR20; FindVRJ22 - { FindJCCL12; FindGadgeteer12; FindSonix12; FindVPR20; } FindVRJOGL22 - FindVRJ22; FindVRJuggler22 - FindVRJOGL22; } // commented out to make the diagram easier to read - {FindFlagpoll; CleanLibraryList; CleanDirectoryList;} FindVPR20 - { FindBoost; FindCPPDOM; } FindGadgeteer12 - FindGMTL; FindSonix12 - FindGMTL; } Hope this