It will be compilation error if lib1 doesn’t really use libdl functions and lib3 does.
The question: is this a bug or I’m doing something wrong?
The problem is that lib1 doesn’t really use libdl. Only lib3 uses it. And I get the following error:
/usr/bin/ld: liblib3.a(lib3.cpp.o): in function `test_lib3()':
lib3.cpp:(.text+0xa): undefined reference to `dlclose'
collect2: ld returned 1 exit status
Once again, why we don’t have -ldl after lib3.a in the linker arguments?
Flags tend to be deduplicated, so this isn’t surprising. However, if lib3 itself needs -ldl, why only add it via the _wrapper target? Does it work if you add it directly to the target(s) that need it?
Good question. It really works but … This is only demo. In the real project I have access only to wrappers. And each *_wrapper refers to several IMPORTED libs beside it. Some libs in _wrapper need -ldl and I don’t know how to add -ldl correctly to the end of the final list of libraries. Even if I add -ldl here:
CMake does offer some control over static library cycles, but fine-grained control over the link line is not something CMake provides because IDEs make their own command lines from a list of properties CMake sets up in the IDE project files.
This says only that something that links to lib3_wrapper needs to also link to lib3 and ${CMAKE_DL_LIBS}. Importantly, it does not say that lib3_wrapper itself uses or requires either of those two libraries. If you want it to say that it does use/require them, that should be PUBLIC rather than INTERFACE.
Ah, sorry, I misread. But your expectation is still incorrect. The constraints you have specified are the following:
lib1 depends on nothing. Anything that links to lib1 doesn’t get any usage requirements at all. This implies lib1 does not depend on anything outside itself.
Similarly, lib3 depends on nothing. Anything that links to lib3 also doesn’t get any usage requirements at all. This implies lib3 does not depend on anything outside itself. Note in particular this means you are saying that lib3 does not depend on the dl library.
lib1_wrapper adds lib1 and ${CMAKE_DL_LIBS} as usage requirements for anything that links to lib1_wrapper, but note that this doesn’t imply any ordering of those two libraries.
Similarly lib3_wrapper adds lib3 and ${CMAKE_DL_LIBS} as usage requirements for anything that links to lib3_wrapper, but again this doesn’t imply any ordering of those two libraries.
So when CMake constructs the dependency graph for app, it adds lib1 and dl as dependencies of lib1_wrapper, then when it adds the dependencies for lib3_wrapper, it can see that dl has already been added and doesn’t need to be added a second time.
I suspect the actual constraints you have are that lib1 and lib3 should both link directly to ${CMAKE_DL_LIBS}. If lib1 and lib3 depend on the dl library, you must specify that constraint on lib1 and lib3, not on the wrappers.
It’s important to include these details in examples when asking questions (especially when something doesn’t match your expectations; those details could be very important, as it is here). We cannot know what you’ve simplified out based on any assumptions you’ve had on how things work. There are a few things to try:
fix the project that exports the imported libraries (if made by another project)
if made by a FindX.cmake, add ${CMAKE_DL_LIBS} to the target’s INTERFACE_LINK_LIBRARIES property.
It’s really something wrong with my project. In the test project I can add -ldl to `INTERFACE_LINK_LIBRARIES of the imported libraries and everything is ok.