Re: [CMake] INSTALL(EXPORT) does not honor LINK_INTERFACE_LIBRARIES?

2011-04-03 Thread Michael Hertling
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?

2011-03-31 Thread Rolf Eike Beer
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?

2011-03-31 Thread 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.

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?

2011-03-30 Thread Michael Hertling
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?

2011-03-30 Thread Rolf Eike Beer
 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?

2011-03-30 Thread Michael Hertling
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?

2011-03-30 Thread Rolf Eike Beer
 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?

2011-03-30 Thread Michael Hertling
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?

2011-03-29 Thread Michael Hertling
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?

2011-03-29 Thread Rolf Eike Beer
 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?

2011-03-29 Thread 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.

-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?

2011-03-29 Thread Rolf Eike Beer
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?

2011-03-28 Thread Rolf Eike Beer
 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