0

I have widely-separated dirs, each with a CMakeLists.txt. I'd like to keep them independently-buildable. Two are libs; libA, libB. libB uses libA. exeC uses libA and libB.

When I organize them via add_subdirectory(), as in: libB (CMakeLists.txt):

add_subdirectory($DIRA somebuild)
target_linked_libraries(libB PUBLIC libA)

exeC (CMakeLists.txt):

add_subdirectory($DIRA somebuild)
add_subdirectory($DIRB somebuild)
target_linked_libraries(exeC PUBLIC libB libA)

and then building exeC, CMake complains about the target name of libA not being unique (CMP0002). If I squelch that warning, I get funky results as the docs warn against.

When I organize them via: add_library(), and add_dependencies() as in: libB (CMakeLists.txt):

add_library(libA SHARED IMPORTED)
set_target_properties(libA PROPERTIES IMPORTED_LOCATION $DIRA)
add_dependencies(libB libA)

target_linked_libraries(libB PUBLIC libA)

exeC (CMakeLists.txt):

add_library(libA SHARED IMPORTED)
set_target_properties(libA PROPERTIES IMPORTED_LOCATION $DIRA)
add_dependencies(exeC libA)

add_library(libB SHARED IMPORTED)
set_target_properties(libB PROPERTIES IMPORTED_LOCATION $DIRB)
add_dependencies(exeC libB)

target_linked_library(exeC PUBLIC libA libB)

It doesn't seem like the dependencies propagate - when I build exeC, it chokes on not finding libA and libB there, as indeed the docs warn about, although I thought I saw some other doc that said they would build if the required libs were all based on CMake. I'm using CMake 2.8.12.

Is it possible to have nested inclusions like this, or is that not The CMake Way?

edit: it further turns out, that one solution - relying on the transitivity of add_subdirectory(), isn't enough because my case is actually diamond-shaped, I have libB1 and libB2 who each 'include' libA and are included by exeC. It looks like include guards may be the way to go. I'll acknowledge @Drop's answer as correct, if I get this working.

JDonner
  • 492
  • 6
  • 15
  • 1
    You don't have to add "libA" to "exeC" at all (no linking, hence no add subdir). It should propagate transitively from "libB" if "libA" is declared public there (which it is)... unless you have CMake version that is too old, which seems to be the case (then either upgrade or keep suffering). For specifics (including versioning madness), check "Effective CMake" and "Modern CMake" for current "The CMake Way" (there are at least 3 video talks + PDF slides, plus some git repos here and there). – Ivan Aksamentov - Drop Jul 16 '18 at 17:50
  • @Drop - but I do link libA directly from exeC, and everything's shared (thus not /obviously/ automatically included. I'll try dropping libA as a separate dependency though. – JDonner Jul 16 '18 at 17:54
  • 1
    That's what I am saying. You shouldn't. It WILL link libA into exeC for you automagically, because libB is linked against it already (unless... see above ^) – Ivan Aksamentov - Drop Jul 16 '18 at 17:55
  • So I use the add_subdirectory libB and rely on the fact that it already includes libA, avoiding the double include? Makes sense. I'll try it. I like seeing all dependencies explicitly, but, working comes first. – JDonner Jul 16 '18 at 18:02
  • Ack - I left it out for simplicity, but there's actually libB1 and libB2, both of which use libA - if I add_subdirectory libA from both, and add_subdirectory(exeC libB1) add_sub..(exeC libB2), I'm going to be in trouble again. Maybe I can mess with PRIVATE for one of them .. – JDonner Jul 16 '18 at 18:08
  • 1
    Hm. This is a classic "diamond problem". You may try to use [guards](https://stackoverflow.com/questions/33086122/using-cmake-with-libraries-with-diamond-depedencies) (similar to header guards or `#pragma once` in C++) – Ivan Aksamentov - Drop Jul 16 '18 at 18:36

0 Answers0