On 04/20/2010 09:40 PM, Benoit Thomas wrote: > On 2010-04-20 03:27, Michael Hertling wrote: >> On 04/19/2010 10:07 PM, Benoit Thomas wrote: >> >> >>> I'm using an external library which is already compiled. I have wrapped >>> the library in a MyLib.cmake and use it in cmake as an imported library. >>> It works fine, but since the include line uses relative path, it changes >>> from projects to projects and in some case it looks just wrong. >>> >> Just for my understanding: What exactly do you mean with "wrapped the >> library in a MyLib.cmake" and "use it in cmake as an imported library"? >> > I'm migrating Visual Studio project to CMake. The Visual Studio projects > use heavy configurations (20+). So, when I used a library which hasn't > yet been converted to cmake, I usually only create a small > CMakeLists.txt for it which look like this: > > add_library (MyLib IMPORTED) > set_target_properties (MyLib PROPERTIES IMPORTED_LOCATION_CONFIG1 > "${MYLIB_ROOT_DIR}/bin/config1/MyLib.lib") > set_target_properties (MyLib PROPERTIES IMPORTED_LOCATION_CONFIG2 > "${MYLIB_ROOT_DIR}/bin/config2/MyLib.lib") > ... > set_target_properties (MyLib PROPERTIES IMPORTED_LOCATION_CONFIG20 > "${MYLIB_ROOT_DIR}/bin/config20/MyLib.lib") > > Then, in another project I'm doing (something like): > > include (../../../somewhere/MyLib/CMakeLists.txt) > > add_executable (MyExe) > target_link_libraries (MyExe MyLib) > > But this line didn't feel right: > include (../../../somewhere/MyLib/CMakeLists.txt) > > I renamed the CMakeLists.txt to MyLib.cmake as it's not really a project > file on his own. Also, the path is never the same for all projects so > that's why I wanted to change the format to a find_package (it's > cleaner, and doesn't change if projects are moved).
Oh, I see: Using the IMPORT option of ADD_LIBRARY(). That's the point I didn't catch; the term "wrapped the library in..." slightly confused me. >>> I want to change this to something more like: >>> >>> find_package (MyLib) >>> include (MYLIB_CMAKE_FILE) >>> # add_executable and stuff >>> target_link_libraries (MyExe MyLib) >>> >> This is a possible approach which is also followed by FindQt4.cmake, >> but, for several reasons, you shouldn't explicitly refer to "MyLib" >> in TARGET_LINK_LIBRARIES(); use variables from FIND_PACKAGE(MyLib). >> >> > I though about using variables, but target_link_libraries doesn't > support configurations, and the other alternative I found was using > LINK_FLAGS. However, using imported library and target_link_libraries > gave me a clean solution. For me, that's absolutely reasonable. As fas as I understand, the flexible link time configuration is one of the primary motives for deploying imported targets instead of the, say, classic method of referring directly to <path/to/library>. For the use of variables in TARGET_LINK_LIBRARIES() when it comes to import libraries, see below. >>> In the book, there is an example which seems to do more what I want and >>> use *-config.cmake, which give something like >>> >>> find_package (MyLib) >>> # no include, since the MyLib-config.cmake already took care of the include >>> # add_executable and stuff >>> target_link_libraries (MyExe MyLib) >>> >> What is meant with "took care of the include"? I don't have the book. ;) >> > When I look at FindXXX.cmake, they create variables and macros, but they > don't add any targets to your project (I assume this was standard). In > the book, there's an example about creating XXX-config.cmake files. From > my understanding, the XXX-config.cmake include a XXX-targets.cmake which > create the imported target. I suppose XXX-targets.cmake is a file created by INSTALL(EXPORT ...) and, thus, contains IMPORTED definitions for all targets declared as "EXPORT" in INSTALL(TARGETS ...). This file is thought to be included by other project's CMakeLists.txt files in order to make the targets available as imported, but here, one has the same question as you had initially: Where does this "target file" resides? Though I can't cite an example, it's reasonable for me that find modules and config files include the target file; a find module searches it and a config file knows it because, usually, they were installed together by the same CMakeLists.txt. Provided that, a foreign CMakeLists.txt could invoke FIND_PACKAGE(XXX) for indirect inclusion of the target file, making XXX's libraries, executables etc. finally available as IMPORTED targets. Perhaps, it's this you're interested in? However, see: <http://www.cmake.org/Wiki/CMake_2.6_Notes#Exporting_Targets> > So I was a little confuse about the fact that if I write code like > > find_package (MyLib) > > # If MyLib is a FindMyLib.cmake, the following code should like > if (MyLib_FOUND) > include (MyLib_USE_FILE) # which would do the add_library (MyLib > IMPORTED) > else() > # print some fatal error message... > endif() > > # But if MyLib is a MyLib-config.cmake, there's nothing else to do; > find_package will display an error message if MyLib isn't found, and if > it's found, MyLib-config.cmake will include MyLib-target.cmake Since FindMyLib.cmake and mylib-config.cmake (lowercase with hyphen) would be loaded - only one of them, of course - by one and the same invocation of FIND_PACKAGE(MyLib) they should behave the same from a user's point of view, i.e. either both include ${MyLib_USE_FILE} or none. In any case, you would end up with your example above or with FIND_PACKAGE(MyLib) IF(NOT MyLib_FOUND) # Think how to proceed. ENDIF() if FindMyLib.cmake/mylib-config.cmake would actually execute the include command. Here, the main difference between find module and config file is that FindMyLib.cmake has to look for ${MyLib_USE_FILE} while mylib-config.cmake "knows" since it is part of the MyLib package, or, in other words, a find module is typically developed and installed separately from the package it is up to find; see MW's earlier reply. >>> Part of what I don't understand is when a user use the find_package >>> command, is he expecting to load a Find* file or a *-config file (or he >>> doesn't care?), [...] >>> >> In general, he doesn't care; in particular, she can tell >> FIND_PACKAGE() to look for a config file exclusively. >> > The more I'm reading about the subject, the more I'll go with a > XXX-config.cmake file which will take care of importing the library. And > as you mention, I'll try to use variables as much as possible, but in my > context is a little hard :) I'll also use the NO_MODULE option to make > it clear I'm looking for a config file and not a module. In regard to imported libraries in find modules / config files and their backward communication via variables, you should take a look at the current ${CMAKE_ROOT}/Modules/FindQt4.cmake. Up to now, this is the only find module delivered with CMake which uses both imported libraries and variables to communicate its results. Perhaps, it does quite exactly what you have in mind w.r.t. your challenges. Additionally, see here: <http://www.mail-archive.com/cmake@cmake.org/msg27109.html> <http://www.mail-archive.com/cmake@cmake.org/msg26546.html> And especially: <http://www.mail-archive.com/cmake@cmake.org/msg15760.html> Obviously, imported targets are having a bright future. ;) >> As for myself: Yes, absolutely. FIND_PACKAGE(MyLib) should try to find >> anything necessary to use Mylib, i.e. preprocessor definitions, include >> directories, libraries etc., and communicate the results as variables, >> e.g. MyLib_DEFINITIONS, MyLib_INCLUDE_DIRS, MyLib_LIBRARIES etc., but it >> should not have a direct, hard-coded impact on the configuration process >> as a target definition would be; this should be reserved for the calling >> CMake script. BTW, why would you need a target "MyLib" here? As you said >> before, the library is external and already compiled. >> > The reason why I need a MyLib target is because of the 20+ > configurations... Make my life more easy that way (Keeping the 20+ > configurations in a single project is not really my call btw...) Of course, this number of configurations is a compelling reason for the use of imported libraries. My concern about adding them in find modules or config files was that all targets - imported or, say, regular - must be unique, so I have a certain objection when FIND_PACKAGE() returns with new targets defined. In contrast, variables somehow feel more gentle on that score. Anyway, revisiting your previous question about targets brought in by FIND_PACKAGE(), IMPORTED targets are different, indeed: FindQt4.cmake defines them and the INSTALL(EXPORT ...) command supports them via the target file, so I would conclude: It's fine to bring in *imported* targets by FIND_PACKAGE(), but give a thought to namespaces; see NAMESPACE option of INSTALL(EXPORT ...) and "Qt4::". In summary, I would advise: - For a cmakified or going-to-be-cmakified project, write a target file and a config file and install them at an appropriate location where the config file can be found by FIND_PACKAGE(). - By design, the config file does know the location of the target file and, thus, can include it without any objections, but consider the use of namespaces. - The manually written target file should be set up in the same way INSTALL(EXPORT ...) would do it, so there's no regression if the project's cmakification is completed later. Again, 'hope this helps a bit, but I'm not sure if it's the way things are intended to be done. Perhaps, a CMake expert can provide us some insight into the respective "best practice". Best regards, Michael Hertling _______________________________________________ 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