there is another (static) library named libraryB which has a link time dependency on libraryA (specified via target_link_libraries(libraryB PRIVATE libraryA))
there is a third (static) library named libraryAmockup which contains mockup versions of the functions in libraryA (with the same interface)
there is an executable named test_executable which has a link time dependency on libraryB (specified via target_link_libraries(test_executable PRIVATE libraryB))
test_executable does not directly use functionality from libraryA
As test_executable is for testing purposes, I’d like to link with libraryAmockup rather than libraryA.
Is it possible to (reliably) exchange the dependencies only for the test_executable target? I.e. use libraryB -> libraryAmockup when linking test_executable and libraryB -> libraryA in all other situations.
Thanks, @marc.chevrier, for this suggestion. I had not yet been aware of INTERFACE_LINK_LIBRARIES_DIRECT and INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE.
I might misunderstand the documentation, so please correct me if applicable: I’d have to set the INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE property of libraryB to libraryA and then explicitly link test_executable with libraryAmockup. The consequence would be that all normal users (aka dependent targets) of libraryB would get into trouble if they don’t know that they have to link with libraryA (which should be an implementation detail of libraryB which is usually dealt with by the normal CMake transitive closure).
My goal was to keep the normal transitive closure mechanism for users of libraryB and override it only when linking that special test_executable.
You do not need to change the dependency of libB if the mock symbols are linked before libB. The linker should only pull in the symbols from libA if such a symbol is needed by libB but not mocked.
So you just need to make sure that your mock of libA appears before libB in the linker command but linked either dynamic or the whole library.
So you just need to make sure that your mock of libA appears before libB in the linker command but linked either dynamic or the whole library.
Is there a way (in CMake) to reliably have libraryAmockup injected before the first occurence of libraryB and any libraryA occurrences (which might be caused by different dependencies)?
(I’d also need to wrap linking of libraryAmockup in a --whole-archive/--no-whole-archive pair (I’m using a GNU toolchain), but I know how to do that.)
The link order given by target_link_libraries() is kept.
Yes, you are right. I was assuming (wrongly) that CMake would delay linking if several involved targets depend on the same target, i.e. that for instance in the case e->{l1,l2}, l2->l1 CMake would link l2 first and then l1 because both e and l2 depend on l1. But apparently CMake just links l1 several times.
By the way, is there a reason you use static libraries?
I link libraries because the tests operate on the interfaces of the library under test (operating the public interface and mocking subordinates). The libraries are static because it’s an embedded environment without support for shared/dynamic libraries.