Re: [CMake] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 04/02/2011 10:52 AM, Rolf Eike Beer wrote: Am Donnerstag, 31. März 2011, 15:26:31 schrieb Brad King: On 03/31/2011 09:14 AM, Rolf Eike Beer wrote: See below. Looks like the only way to prevent this is to set LINK_INTERFACE_LIBRARIES to empty for every lib that uses the static lib. Which may be a good idea anyway as that transitive linking is harmful. CMake has always done said transitive linking for historical reasons. The default behavior cannot change now. It is not necessarily harmful if the static library objects are built with -fPIC and are not all absorbed into the shared library that initially links it. set(DONT_DO_SILLY_LEGACY_OVERLINKING true)? ;) The documented way to turn off transitive linking is to set the LINK_INTERFACE_LIBRARIES property. Once that is done then install(EXPORT) will not complain about the transitive static libraries anymore. However, it *will* complain about the *shared* libraries for the reason I explained in my earlier response to this thread. I start to get the point ;) On 03/29/2011 05:36 PM, Rolf Eike Beer wrote: Am Dienstag, 29. März 2011, 09:41:36 schrieb Brad King: CMake running in an outside application needs to know these private runtime dependencies. It needs them ensure that the application link line is generated such that the linker can find the transitive dependencies (e.g. -rpath-link) of the public library. No, why should it? See the sample script below. CMake needs to know where bar's transitive dependencies are installed so that it can pass the right thing to -rpath-link. This is is how IMPORTED_LINK_DEPENDENT_LIBRARIES is used and why the install(EXPORT) command needs all the targets in the export. Since one target can be installed to multiple locations, or accidentally not at all, the install(TARGETS) for 'foo' must list the same EXPORT as the install(TARGETS) for 'bar' so that CMake can associate the right copy of the dependency. Isn't the rpath stored inside those shared libraries? So every shared library (and the executable itself) know where it's own dependencies are located? Sometimes, there are good reasons to not set the RPATH tag in the resulting binaries, and as a default, CMake indeed doesn't do this during the installation. Look at the following CMakeLists.txt file: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(P1 C) FILE(WRITE ${CMAKE_BINARY_DIR}/private.c void private(void){}\n) ADD_LIBRARY(private SHARED private.c) FILE(WRITE ${CMAKE_BINARY_DIR}/public.c void public(void){private();}\n) ADD_LIBRARY(public SHARED public.c) TARGET_LINK_LIBRARIES(public private) SET_TARGET_PROPERTIES(public PROPERTIES LINK_INTERFACE_LIBRARIES ) INSTALL(TARGETS public EXPORT p1 LIBRARY DESTINATION lib) INSTALL(TARGETS private EXPORT p1 LIBRARY DESTINATION lib/p1) INSTALL(EXPORT p1 DESTINATION share) Configure, build and install it, e.g. with CMAKE_INSTALL_PREFIX set to /dev/shm/usr. It's allowed and quite common to have a project's private libraries in ${CMAKE_INSTALL_PREFIX}/lib/${PROJECT_NAME} instead of the usual library directory ${CMAKE_INSTALL_PREFIX}/lib, even if the project is installed to /usr[/local]. Now, look at the following CMakeLists.txt: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(P2 C) SET(CMAKE_VERBOSE_MAKEFILE ON) INCLUDE(p1) FILE(WRITE ${CMAKE_BINARY_DIR}/main.c int main(void){public();return 0;}\n) ADD_EXECUTABLE(main main.c) TARGET_LINK_LIBRARIES(main public) INSTALL(TARGETS main RUNTIME DESTINATION bin) Configure it with CMAKE_MODULE_PATH set to /dev/shm/usr/share, e.g., to have it find p1.cmake, and build: Everything should work perfectly. Now, edit /dev/shm/usr/share/p1-noconfig.cmake and remove the line with the public target's IMPORTED_LINK_DEPENDENT_LIBRARIES_NOCONFIG property, rebuild and... undefined reference to `private'. What happens here: You removed the sole information that libpublic.so depends on libprivate.so, so not only it does not appear in the link line - that's desired to prevent an explicit dependency of main - but also its directory does not appear either, and this makes ld fail to resolve the 'private' symbol. The IMPORTED_LINK_DEPENDENT_LIBRARIES property's job is exactly to provide that information in case of the transitive linking being disabled for a shared library, or in other words: If you disable transitive linking for libpublic.so and do not set the RPATH tag either, you do need the information conveyed by the IMPORTED_LINK_DEPENDENT_LIBRARIES property to make the linker succeed in resolving libprivate.so's symbols, even if they are just indirectly referred to via libpublic.so. BTW, how would you address this issue on platforms that do not have a concept like ELF's RPATH tags, e.g. W...? Ok, at the end that actually makes sense. But since I'm installing every library to the same directory on Un*x wouldn't it be possible to just drop out all those libraries somehow? [...] In fact, they *are* dropped out:
Re: [CMake] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
Michael Hertling wrote: On 03/30/2011 03:14 PM, Rolf Eike Beer wrote: [...] Only adding INSTALL(TARGETS privstatic EXPORT myexport DESTINATION trash) made CMake complete successfully, resulting in the static stuff showing up in the export, too. Could you provide a minimal but complete example with that issue? See below. Looks like the only way to prevent this is to set LINK_INTERFACE_LIBRARIES to empty for every lib that uses the static lib. Which may be a good idea anyway as that transitive linking is harmful. Eike PROJECT(cmexport C CXX) CMAKE_MINIMUM_REQUIRED(VERSION 2.8) FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/stlib.c #include \stlib.h\ int stlib_func(void) { return 42; } ) FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/stlib.h #pragma once extern int stlib_func(void); ) ADD_LIBRARY(stlib STATIC ${CMAKE_CURRENT_BINARY_DIR}/stlib.c ${CMAKE_CURRENT_BINARY_DIR}/stlib.h ) FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/privlib.c #include \privlib.h\ #include \stlib.h\ int privlib_func(void) { return stlib_func(); } ) FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/privlib.h #pragma once #ifdef __cplusplus extern \C\ { #endif extern int privlib_func(); #ifdef __cplusplus } #endif ) ADD_LIBRARY(privlib SHARED ${CMAKE_CURRENT_BINARY_DIR}/privlib.c ${CMAKE_CURRENT_BINARY_DIR}/privlib.h ) TARGET_LINK_LIBRARIES(privlib stlib) # comment out the next line to get the error # SET_TARGET_PROPERTIES(privlib PROPERTIES LINK_INTERFACE_LIBRARIES ) FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/publib.cpp #include \privlib.h\ int pubfunc(void) { return privlib_func(); } ) ADD_LIBRARY(publib SHARED ${CMAKE_CURRENT_BINARY_DIR}/publib.cpp) TARGET_LINK_LIBRARIES(publib privlib) SET_TARGET_PROPERTIES(publib PROPERTIES LINK_INTERFACE_LIBRARIES ) INSTALL(TARGETS publib privlib EXPORT cmexp DESTINATION lib) INSTALL(EXPORT cmexp DESTINATION share) ___ 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] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/31/2011 09:14 AM, Rolf Eike Beer wrote: See below. Looks like the only way to prevent this is to set LINK_INTERFACE_LIBRARIES to empty for every lib that uses the static lib. Which may be a good idea anyway as that transitive linking is harmful. CMake has always done said transitive linking for historical reasons. The default behavior cannot change now. It is not necessarily harmful if the static library objects are built with -fPIC and are not all absorbed into the shared library that initially links it. The documented way to turn off transitive linking is to set the LINK_INTERFACE_LIBRARIES property. Once that is done then install(EXPORT) will not complain about the transitive static libraries anymore. However, it *will* complain about the *shared* libraries for the reason I explained in my earlier response to this thread. On 03/29/2011 05:36 PM, Rolf Eike Beer wrote: Am Dienstag, 29. März 2011, 09:41:36 schrieb Brad King: CMake running in an outside application needs to know these private runtime dependencies. It needs them ensure that the application link line is generated such that the linker can find the transitive dependencies (e.g. -rpath-link) of the public library. No, why should it? See the sample script below. CMake needs to know where bar's transitive dependencies are installed so that it can pass the right thing to -rpath-link. This is is how IMPORTED_LINK_DEPENDENT_LIBRARIES is used and why the install(EXPORT) command needs all the targets in the export. Since one target can be installed to multiple locations, or accidentally not at all, the install(TARGETS) for 'foo' must list the same EXPORT as the install(TARGETS) for 'bar' so that CMake can associate the right copy of the dependency. -Brad echo 'int foo(void) { return 0; }' foo.c echo 'extern int foo(void); int bar(void) { return foo(); }' bar.c echo 'extern int bar(void); int main() { return bar(); }' main.c mkdir -p lib gcc -shared -fPIC -o lib/libfoo.so -Wl,-soname,libfoo.so foo.c gcc -shared -fPIC -o libbar.so -Wl,-soname,libbar.so bar.c lib/libfoo.so ldd ./libbar.so |grep libfoo.so #libfoo.so = not found gcc -o main main.c libbar.so #/usr/bin/ld: warning: libfoo.so, needed by libbar.so, not found (try using -rpath or -rpath-link) #libbar.so: undefined reference to `foo' gcc -o main -Wl,-rpath-link,lib main.c libbar.so ___ 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] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/29/2011 11:36 PM, Rolf Eike Beer wrote: Am Dienstag, 29. März 2011, 09:41:36 schrieb Brad King: On 03/29/2011 05:19 AM, Rolf Eike Beer wrote: The basic idea is: any symbols from those private libraries are, well, private. The user only ever sees the symbols from the public library. In fact he _can't_ even link to the private libraries on Windows as we never install the .lib files. And that's no problem at all as we already link to everything we need. I'm using --as-needed and --no-undefined on Un*x and see no problem there either. So the point is I want CMake to stop telling the user that he needs to those private libraries as that's simply not true. As Michael pointed out it is needed to set this property: http://www.cmake.org/cmake/help/cmake-2-8-docs.html#prop_tgt:IMPORTED_LINK_ DEPENDENT_LIBRARIES CMake running in an outside application needs to know these private runtime dependencies. It needs them ensure that the application link line is generated such that the linker can find the transitive dependencies (e.g. -rpath-link) of the public library. No, why should it? Take the attached example. Build it. Do ldd on testthing. It links against Qt. Run testthing. It prints your path. Delete libqthing. Move libcthing to libqtthing. Run testthing. It prints your path just like before. ldd testthing. It still links against Qt. Besides, ldd is not appropriate to check against which shared libraries a binary is linked because it gathers all shared libraries recursively. As a proof, set the LINK_INTERFACE_LIBRARIES property on qthing to the empty string and rebuild; ldd testthing still shows the Qt libraries, indirectly pulled in by qthing. Instead, one should apply readelf -d and look for the NEEDED fields to see which shared libraries a binary actually depends on explicitly, at least on an ELF platform. Now when I set LINK_INTERFACE_LIBRARIES on qthing to empty it will prevent testthing to be linked against Qt itself so after replacing libqthing with libcthing everything works fine but without the (now useless) dependency on Qt. So why would I import that dependency to an outside project then? I think this transitive linking for _shared_ libraries should actually be considered harmful. We provide an API and that's all a user should care about. We may change our internal libraries in any release at will and the user should care. In fact we have done this more than one and the binaries linked against older runtime versions just happily work with newer releases. If that transitive stuff would have been used none of them would work anymore because we have moved, renamed, deleted, replaced and done other things to our internal libraries. I guess you had a reason for this transitive stuff, but I don't understand it. To prevent the silly user from accidentially underlinking his executables and libs? I know where this is needed for in static libs, but for shared ones? Eike Everything you're saying above is correct, and perhaps one can argue about such a kind of transitive linking, but you can avoid it easily with the LINK_INTERFACE_LIBRARIES properties which are also honored by INSTALL(EXPORT), i.e. with imported targets. Take the exemplary project LIL from my previous post, build/install it and look at the following: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(LILUSR C) SET(CMAKE_VERBOSE_MAKEFILE ON) INCLUDE(lil) FILE(WRITE ${CMAKE_BINARY_DIR}/main.c int main(void){return 0;}\n) ADD_EXECUTABLE(main1 main.c) TARGET_LINK_LIBRARIES(main1 f1) ADD_EXECUTABLE(main2 main.c) TARGET_LINK_LIBRARIES(main2 f2) Configure with CMAKE_MODULE_PATH set to the directory containing the lil.cmake file from the LIL project and look for the linker commands; you'll see that main1 gets linked against libf1.so and libf0.so while main2 gets linked against libf2.so only - no f0 in sight. Hence, the f2 target's IMPORTED_LINK_DEPENDENT_LIBRARIES property actually does what's expected: It prevents libf0.so from appearing in the linker's command line, so there is no direct dependency of main2 on libf0.so. However, I still don't understand the relation of that transitive linking and its avoidance, respectively, to your initial complaint about CMake's error message due to the missing library in another library's export set. Unless I'm mistaken, you've a shared library target publiclib which is linked explicitly against another target privatelib via TARGET_LINK_LIBRARIES(). This means you can't place publiclib in an export set without privatelib since the former could not be set up properly w.r.t. its diverse IMPORTED properties if the latter is not installed, too, i.e. INSTALL(EXPORT) could not generate a valid export file. If you want to remove the error message, just include privatelib in publiclibs's export set; here, both targets may perfectly reside in different directories with different CMakeLists.txt files, but they must be members of the same
Re: [CMake] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/29/2011 11:36 PM, Rolf Eike Beer wrote: Am Dienstag, 29. März 2011, 09:41:36 schrieb Brad King: On 03/29/2011 05:19 AM, Rolf Eike Beer wrote: The basic idea is: any symbols from those private libraries are, well, private. The user only ever sees the symbols from the public library. In fact he _can't_ even link to the private libraries on Windows as we never install the .lib files. And that's no problem at all as we already link to everything we need. I'm using --as-needed and --no-undefined on Un*x and see no problem there either. So the point is I want CMake to stop telling the user that he needs to those private libraries as that's simply not true. As Michael pointed out it is needed to set this property: http://www.cmake.org/cmake/help/cmake-2-8-docs.html#prop_tgt:IMPORTED_LINK_ DEPENDENT_LIBRARIES CMake running in an outside application needs to know these private runtime dependencies. It needs them ensure that the application link line is generated such that the linker can find the transitive dependencies (e.g. -rpath-link) of the public library. No, why should it? Take the attached example. Build it. Do ldd on testthing. It links against Qt. Run testthing. It prints your path. Delete libqthing. Move libcthing to libqtthing. Run testthing. It prints your path just like before. ldd testthing. It still links against Qt. Besides, ldd is not appropriate to check against which shared libraries a binary is linked because it gathers all shared libraries recursively. As a proof, set the LINK_INTERFACE_LIBRARIES property on qthing to the empty string and rebuild; ldd testthing still shows the Qt libraries, indirectly pulled in by qthing. Instead, one should apply readelf -d and look for the NEEDED fields to see which shared libraries a binary actually depends on explicitly, at least on an ELF platform. Yes and no. Of course it shows the recursive things. But if you delete libqthing.so ldd on the file still shows it is linking against Qt but that can't come from libqthing anymore. So the executable is actually overlinked. Now when I set LINK_INTERFACE_LIBRARIES on qthing to empty it will prevent testthing to be linked against Qt itself so after replacing libqthing with libcthing everything works fine but without the (now useless) dependency on Qt. So why would I import that dependency to an outside project then? I think this transitive linking for _shared_ libraries should actually be considered harmful. We provide an API and that's all a user should care about. We may change our internal libraries in any release at will and the user should care. In fact we have done this more than one and the binaries linked against older runtime versions just happily work with newer releases. If that transitive stuff would have been used none of them would work anymore because we have moved, renamed, deleted, replaced and done other things to our internal libraries. I guess you had a reason for this transitive stuff, but I don't understand it. To prevent the silly user from accidentially underlinking his executables and libs? I know where this is needed for in static libs, but for shared ones? Everything you're saying above is correct, and perhaps one can argue about such a kind of transitive linking, but you can avoid it easily with the LINK_INTERFACE_LIBRARIES properties which are also honored by INSTALL(EXPORT), i.e. with imported targets. Take the exemplary project LIL from my previous post, build/install it and look at the following: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(LILUSR C) SET(CMAKE_VERBOSE_MAKEFILE ON) INCLUDE(lil) FILE(WRITE ${CMAKE_BINARY_DIR}/main.c int main(void){return 0;}\n) ADD_EXECUTABLE(main1 main.c) TARGET_LINK_LIBRARIES(main1 f1) ADD_EXECUTABLE(main2 main.c) TARGET_LINK_LIBRARIES(main2 f2) Configure with CMAKE_MODULE_PATH set to the directory containing the lil.cmake file from the LIL project and look for the linker commands; you'll see that main1 gets linked against libf1.so and libf0.so while main2 gets linked against libf2.so only - no f0 in sight. Hence, the f2 target's IMPORTED_LINK_DEPENDENT_LIBRARIES property actually does what's expected: It prevents libf0.so from appearing in the linker's command line, so there is no direct dependency of main2 on libf0.so. However, I still don't understand the relation of that transitive linking and its avoidance, respectively, to your initial complaint about CMake's error message due to the missing library in another library's export set. Unless I'm mistaken, you've a shared library target publiclib which is linked explicitly against another target privatelib via TARGET_LINK_LIBRARIES(). Yes. This means you can't place publiclib in an export set without privatelib since the former could not be set up properly w.r.t. its diverse IMPORTED properties if the latter is not installed, too, i.e. INSTALL(EXPORT) could not generate a
Re: [CMake] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/30/2011 02:02 PM, Rolf Eike Beer wrote: However, I still don't understand the relation of that transitive linking and its avoidance, respectively, to your initial complaint about CMake's error message due to the missing library in another library's export set. Unless I'm mistaken, you've a shared library target publiclib which is linked explicitly against another target privatelib via TARGET_LINK_LIBRARIES(). Yes. This means you can't place publiclib in an export set without privatelib since the former could not be set up properly w.r.t. its diverse IMPORTED properties if the latter is not installed, too, i.e. INSTALL(EXPORT) could not generate a valid export file. Yes, and that's basically the problem I have. Ok, I went and put every thing in the same export set. Which itself is a bit weird as I now have to INSTALL static libraries that were linked by the shared ones only to be able to specify that they are in the export set. And at the end all those libraries of course show up in the export. And I still see IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG of the library that this is all about set to it's dependencies. W.r.t. *static* libraries, that's not necessary: If a shared library is linked against a static one and the former prevents transitive linking for the latter by setting LINK_INTERRFACE_LIBRARIES appropriately, the static library does not need to be put in the shared one's export set: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(PRIVATE C) SET(CMAKE_VERBOSE_MAKEFILE ON) FILE(WRITE ${CMAKE_BINARY_DIR}/f.c void f(void){}\n) ADD_LIBRARY(f STATIC f.c) FILE(WRITE ${CMAKE_BINARY_DIR}/g.c void g(void){f();}\n) ADD_LIBRARY(g SHARED g.c) TARGET_LINK_LIBRARIES(g f) SET_TARGET_PROPERTIES(g PROPERTIES LINK_INTERFACE_LIBRARIES ) INSTALL(TARGETS g EXPORT public LIBRARY DESTINATION lib) INSTALL(EXPORT public DESTINATION share) In the export file, the static f isn't mentioned at all, and that's perfect. Without LINK_INTERFACE_LIBRARIES set or with a *shared* f, this does not work, of course. Regards, 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] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/30/2011 02:02 PM, Rolf Eike Beer wrote: However, I still don't understand the relation of that transitive linking and its avoidance, respectively, to your initial complaint about CMake's error message due to the missing library in another library's export set. Unless I'm mistaken, you've a shared library target publiclib which is linked explicitly against another target privatelib via TARGET_LINK_LIBRARIES(). Yes. This means you can't place publiclib in an export set without privatelib since the former could not be set up properly w.r.t. its diverse IMPORTED properties if the latter is not installed, too, i.e. INSTALL(EXPORT) could not generate a valid export file. Yes, and that's basically the problem I have. Ok, I went and put every thing in the same export set. Which itself is a bit weird as I now have to INSTALL static libraries that were linked by the shared ones only to be able to specify that they are in the export set. And at the end all those libraries of course show up in the export. And I still see IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG of the library that this is all about set to it's dependencies. W.r.t. *static* libraries, that's not necessary: If a shared library is linked against a static one and the former prevents transitive linking for the latter by setting LINK_INTERRFACE_LIBRARIES appropriately, the static library does not need to be put in the shared one's export set: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(PRIVATE C) SET(CMAKE_VERBOSE_MAKEFILE ON) FILE(WRITE ${CMAKE_BINARY_DIR}/f.c void f(void){}\n) ADD_LIBRARY(f STATIC f.c) FILE(WRITE ${CMAKE_BINARY_DIR}/g.c void g(void){f();}\n) ADD_LIBRARY(g SHARED g.c) TARGET_LINK_LIBRARIES(g f) SET_TARGET_PROPERTIES(g PROPERTIES LINK_INTERFACE_LIBRARIES ) INSTALL(TARGETS g EXPORT public LIBRARY DESTINATION lib) INSTALL(EXPORT public DESTINATION share) In the export file, the static f isn't mentioned at all, and that's perfect. Without LINK_INTERFACE_LIBRARIES set or with a *shared* f, this does not work, of course. What CMake version are you using? For me CMake is complaining that the public library depends on some private libraries that are not exported and they are static. Only adding INSTALL(TARGETS privstatic EXPORT myexport DESTINATION trash) made CMake complete successfully, resulting in the static stuff showing up in the export, too. Maybe I just write the export file by hand as what's happening here is just plain wrong IMHO. At least for my case. Eike ___ 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] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/30/2011 03:14 PM, Rolf Eike Beer wrote: On 03/30/2011 02:02 PM, Rolf Eike Beer wrote: However, I still don't understand the relation of that transitive linking and its avoidance, respectively, to your initial complaint about CMake's error message due to the missing library in another library's export set. Unless I'm mistaken, you've a shared library target publiclib which is linked explicitly against another target privatelib via TARGET_LINK_LIBRARIES(). Yes. This means you can't place publiclib in an export set without privatelib since the former could not be set up properly w.r.t. its diverse IMPORTED properties if the latter is not installed, too, i.e. INSTALL(EXPORT) could not generate a valid export file. Yes, and that's basically the problem I have. Ok, I went and put every thing in the same export set. Which itself is a bit weird as I now have to INSTALL static libraries that were linked by the shared ones only to be able to specify that they are in the export set. And at the end all those libraries of course show up in the export. And I still see IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG of the library that this is all about set to it's dependencies. W.r.t. *static* libraries, that's not necessary: If a shared library is linked against a static one and the former prevents transitive linking for the latter by setting LINK_INTERRFACE_LIBRARIES appropriately, the static library does not need to be put in the shared one's export set: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(PRIVATE C) SET(CMAKE_VERBOSE_MAKEFILE ON) FILE(WRITE ${CMAKE_BINARY_DIR}/f.c void f(void){}\n) ADD_LIBRARY(f STATIC f.c) FILE(WRITE ${CMAKE_BINARY_DIR}/g.c void g(void){f();}\n) ADD_LIBRARY(g SHARED g.c) TARGET_LINK_LIBRARIES(g f) SET_TARGET_PROPERTIES(g PROPERTIES LINK_INTERFACE_LIBRARIES ) INSTALL(TARGETS g EXPORT public LIBRARY DESTINATION lib) INSTALL(EXPORT public DESTINATION share) In the export file, the static f isn't mentioned at all, and that's perfect. Without LINK_INTERFACE_LIBRARIES set or with a *shared* f, this does not work, of course. What CMake version are you using? [...] 2.8.4 [...] For me CMake is complaining that the public library depends on some private libraries that are not exported and they are static. [...] Does the above-noted example fail with your version of CMake? [...] Only adding INSTALL(TARGETS privstatic EXPORT myexport DESTINATION trash) made CMake complete successfully, resulting in the static stuff showing up in the export, too. Could you provide a minimal but complete example with that issue? Regards, 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] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/28/2011 02:51 PM, Rolf Eike Beer wrote: I try to do an INSTALL(EXPORT) to allow others to link against one of my libraries. That libraries is linked against some other internal libraries the target's don't need to link to as everything in them is purely internal. I tried something like that: ADD_LIBRARY(publiclib SHARED ${publiclib_SOURCES}) TARGET_LINK_LIBRARIES(publiclib privatelib) SET_TARGET_PROPERTIES(publiclib PROPERTIES LINK_INTERFACE_LIBRARIES ) INSTALL(TARGETS publiclib EXPORT publiclib_export RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) INSTALL(EXPORT publiclib_export DESTINATION cmake/modules) This results in: Make Error: INSTALL(EXPORT publiclib_export ...) includes target publiclib which requires target privatelib that is not in the export set. Ehm, no, it doesn't? Is this intentional (why?), is there a workaround or should I file a bug report? Eike That's got nothing to do with the LINK_INTERFACE_LIBRARIES property. Your publiclib target is linked against the privatelib one, so you can't place the former in an export set without the latter, and this is what CMake tells you, cf. [1]. Remove the SET_TARGET_PROPERTIES() command and you'll probably see that the error message persists, i.e. LINK_INTERFACE_LIBRARIES can not be used to break any dependencies established by TARGET_LINK_LIBRARIES(); it has other purposes [2]. Besides, INSTALL(EXPORT) *does* honor LINK_INTERFACE_LIBRARIES: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(LIL C) SET(CMAKE_VERBOSE_MAKEFILE ON) FILE(WRITE ${CMAKE_BINARY_DIR}/f0.c void f0(void){}\n) ADD_LIBRARY(f0 SHARED f0.c) FILE(WRITE ${CMAKE_BINARY_DIR}/f.c void f(void){}\n) ADD_LIBRARY(f1 SHARED f.c) TARGET_LINK_LIBRARIES(f1 f0) ADD_LIBRARY(f2 SHARED f.c) TARGET_LINK_LIBRARIES(f2 f0) SET_TARGET_PROPERTIES(f2 PROPERTIES LINK_INTERFACE_LIBRARIES ) INSTALL(TARGETS f2 f1 f0 EXPORT lil RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) INSTALL(EXPORT lil DESTINATION share) Inspect the ${CMAKE_INSTALL_PREFIX}/share/lil-noconfig.cmake file after the installation; you will see that the f1 shared library target has an IMPORTED_LINK_INTERFACE_LIBRARIES_NOCONFIG property of f0 whereas the f2 target has the IMPORTED_LINK_DEPENDENT_LIBRARIES_NOCONFIG property. ^ Regards, Michael [1] http://www.cmake.org/pipermail/cmake/2011-February/042851.html [2] http://www.cmake.org/pipermail/cmake/2011-March/043560.html ___ Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/28/2011 02:51 PM, Rolf Eike Beer wrote: I try to do an INSTALL(EXPORT) to allow others to link against one of my libraries. That libraries is linked against some other internal libraries the target's don't need to link to as everything in them is purely internal. I tried something like that: ADD_LIBRARY(publiclib SHARED ${publiclib_SOURCES}) TARGET_LINK_LIBRARIES(publiclib privatelib) SET_TARGET_PROPERTIES(publiclib PROPERTIES LINK_INTERFACE_LIBRARIES ) INSTALL(TARGETS publiclib EXPORT publiclib_export RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) INSTALL(EXPORT publiclib_export DESTINATION cmake/modules) This results in: Make Error: INSTALL(EXPORT publiclib_export ...) includes target publiclib which requires target privatelib that is not in the export set. Ehm, no, it doesn't? Is this intentional (why?), is there a workaround or should I file a bug report? That's got nothing to do with the LINK_INTERFACE_LIBRARIES property. Your publiclib target is linked against the privatelib one, so you can't place the former in an export set without the latter, and this is what CMake tells you, cf. [1]. Remove the SET_TARGET_PROPERTIES() command and you'll probably see that the error message persists, i.e. LINK_INTERFACE_LIBRARIES can not be used to break any dependencies established by TARGET_LINK_LIBRARIES(); it has other purposes [2]. The basic idea is: any symbols from those private libraries are, well, private. The user only ever sees the symbols from the public library. In fact he _can't_ even link to the private libraries on Windows as we never install the .lib files. And that's no problem at all as we already link to everything we need. I'm using --as-needed and --no-undefined on Un*x and see no problem there either. So the point is I want CMake to stop telling the user that he needs to those private libraries as that's simply not true. Eike ___ 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] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
On 03/29/2011 05:19 AM, Rolf Eike Beer wrote: The basic idea is: any symbols from those private libraries are, well, private. The user only ever sees the symbols from the public library. In fact he _can't_ even link to the private libraries on Windows as we never install the .lib files. And that's no problem at all as we already link to everything we need. I'm using --as-needed and --no-undefined on Un*x and see no problem there either. So the point is I want CMake to stop telling the user that he needs to those private libraries as that's simply not true. As Michael pointed out it is needed to set this property: http://www.cmake.org/cmake/help/cmake-2-8-docs.html#prop_tgt:IMPORTED_LINK_DEPENDENT_LIBRARIES CMake running in an outside application needs to know these private runtime dependencies. It needs them ensure that the application link line is generated such that the linker can find the transitive dependencies (e.g. -rpath-link) of the public library. -Brad ___ 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] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
Am Dienstag, 29. März 2011, 09:41:36 schrieb Brad King: On 03/29/2011 05:19 AM, Rolf Eike Beer wrote: The basic idea is: any symbols from those private libraries are, well, private. The user only ever sees the symbols from the public library. In fact he _can't_ even link to the private libraries on Windows as we never install the .lib files. And that's no problem at all as we already link to everything we need. I'm using --as-needed and --no-undefined on Un*x and see no problem there either. So the point is I want CMake to stop telling the user that he needs to those private libraries as that's simply not true. As Michael pointed out it is needed to set this property: http://www.cmake.org/cmake/help/cmake-2-8-docs.html#prop_tgt:IMPORTED_LINK_ DEPENDENT_LIBRARIES CMake running in an outside application needs to know these private runtime dependencies. It needs them ensure that the application link line is generated such that the linker can find the transitive dependencies (e.g. -rpath-link) of the public library. No, why should it? Take the attached example. Build it. Do ldd on testthing. It links against Qt. Run testthing. It prints your path. Delete libqthing. Move libcthing to libqtthing. Run testthing. It prints your path just like before. ldd testthing. It still links against Qt. Now when I set LINK_INTERFACE_LIBRARIES on qthing to empty it will prevent testthing to be linked against Qt itself so after replacing libqthing with libcthing everything works fine but without the (now useless) dependency on Qt. So why would I import that dependency to an outside project then? I think this transitive linking for _shared_ libraries should actually be considered harmful. We provide an API and that's all a user should care about. We may change our internal libraries in any release at will and the user should care. In fact we have done this more than one and the binaries linked against older runtime versions just happily work with newer releases. If that transitive stuff would have been used none of them would work anymore because we have moved, renamed, deleted, replaced and done other things to our internal libraries. I guess you had a reason for this transitive stuff, but I don't understand it. To prevent the silly user from accidentially underlinking his executables and libs? I know where this is needed for in static libs, but for shared ones? Eike cmlink.tar Description: Unix tar archive signature.asc Description: This is a digitally signed message part. ___ 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] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?
You still need to install that lib even if it is not used by 3rd party application, it is used inernally by your own application. INSTALL(TARGETS publiclib privatelib...) The private libraries are of course installed. If I link against that installed public library by hand everything works fine. And of course that INSTALL instruction is not working because privatelib is in a different directory. Eike ___ 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