title: CMake: How to set up source, library and CMakeLists.txt dependencies?
body: <p>I have several projects (all building with CMake from the same source tree structure) all using their own mix out of dozens of supporting libraries.</p>
  
  <p>So I came about the question how to set up this correctly in CMake. So far I have only found <em><a href="https://stackoverflow.com/questions/4905089/cmake-how-to-correctly-create-dependencies-between-targets">CMake how to correctly create dependencies between targets</a></em>, but I'm still struggling between setting up everything with global dependencies (the project level does know it all) or with local dependencies (each sub-level target only handles its own dependencies).</p>
  
  <p>Here is a reduced example of my directory structure and what I currently came up with using CMake and local dependencies (the example shows only one executable project, <code>App1</code>, but there are actually more, <code>App2</code>, <code>App3</code>, etc.):</p>
  
  <pre><code>Lib
  +-- LibA
      +-- Inc
          +-- a.h
      +-- Src
          +-- a.cc
      +-- CMakeLists.txt
  +-- LibB
      +-- Inc
          +-- b.h
      +-- Src
          +-- b.cc
      +-- CMakeLists.txt
  +-- LibC
      +-- Inc
          +-- c.h
      +-- Src
          +-- c.cc
      +-- CMakeLists.txt
  App1
  +-- Src
      +-- main.cc
  +-- CMakeLists.txt
  </code></pre>
  
  <p><strong>Lib/LibA/CMakeLists.txt</strong></p>
  
  <pre><code>include_directories(Inc ../LibC/Inc)
  add_subdirectory(../LibC LibC)
  add_library(LibA Src/a.cc Inc/a.h)
  target_link_libraries(LibA LibC)
  </code></pre>
  
  <p><strong>Lib/LibB/CMakeLists.txt</strong></p>
  
  <pre><code>include_directories(Inc)
  add_library(LibB Src/b.cc Inc/b.h)
  </code></pre>
  
  <p><strong>Lib/LibC/CMakeLists.txt</strong></p>
  
  <pre><code>include_directories(Inc ../LibB/Inc)
  add_subdirectory(../LibB LibB)
  add_library(LibC Src/c.cc Inc/c.h)
  target_link_libraries(LibC LibB)
  </code></pre>
  
  <p><strong>App1/CMakeLists.txt</strong> (for the ease of reproducing it I generate the source/header files here)</p>
  
  <pre><code>cmake_minimum_required(VERSION 2.8)
  
  project(App1 CXX)
  
  file(WRITE "Src/main.cc" "#include \"a.h\"\n#include \"b.h\"\nint main()\n{\na();\nb();\nreturn 0;\n}")
  file(WRITE "../Lib/LibA/Inc/a.h" "void a();")
  file(WRITE "../Lib/LibA/Src/a.cc" "#include \"c.h\"\nvoid a()\n{\nc();\n}")
  file(WRITE "../Lib/LibB/Inc/b.h" "void b();")
  file(WRITE "../Lib/LibB/Src/b.cc" "void b() {}")
  file(WRITE "../Lib/LibC/Inc/c.h" "void c();")
  file(WRITE "../Lib/LibC/Src/c.cc" "#include \"b.h\"\nvoid c()\n{\nb();\n}")
  
  include_directories(
      ../Lib/LibA/Inc
      ../Lib/LibB/Inc
  )
  
  add_subdirectory(../Lib/LibA LibA)
  add_subdirectory(../Lib/LibB LibB)
  
  add_executable(App1 Src/main.cc)
  
  target_link_libraries(App1 LibA LibB)
  </code></pre>
  
  <p>The library dependencies in the above example do look like this:</p>
  
  <pre><code>App1 -&gt; LibA -&gt; LibC -&gt; LibB
  App1 -&gt; LibB
  </code></pre>
  
  <p>At the moment I prefer the local dependencies variant, because it's easier to use. I just give the dependencies at the source level with <code>include_directories()</code>, at the link level with <code>target_link_libraries()</code> and at the CMake level with <code>add_subdirectory()</code>.</p>
  
  <p>With this you don't need to know the dependencies between the supporting libraries and - with the CMake level "includes" - you will only end-up with the targets you really use. Sure enough you could just make all include directories and targets be known globally and let the compiler/linker sort out the rest. But this seems like a kind of bloating to me.</p>
  
  <p>I also tried to have a <code>Lib/CMakeLists.txt</code> to handle all the dependencies in the <code>Lib</code> directory tree, but I ended up having a lot of <code>if ("${PROJECT_NAME}" STREQUAL ...)</code> checks and the problem that I can't create intermediate libraries grouping targets without giving at least one source file.</p>
  
  <p>So the above example is "so far so good", but it throws the following error because you should/can not add a <code>CMakeLists.txt</code> twice:</p>
  
  <pre><code>CMake Error at Lib/LibB/CMakeLists.txt:2 (add_library):
    add_library cannot create target "LibB" because another target with the
    same name already exists.  The existing target is a static library created
    in source directory "Lib/LibB".
    See documentation for policy CMP0002 for more details.
  </code></pre>
  
  <p>At the moment I see two solutions for this, but I think I got this way too complicated.</p>
  
  <p><strong>1.</strong> Overwriting <code>add_subdirectory()</code> to prevent duplicates</p>
  
  <pre><code>function(add_subdirectory _dir)
      get_filename_component(_fullpath ${_dir} REALPATH)
      if (EXISTS ${_fullpath} AND EXISTS ${_fullpath}/CMakeLists.txt)
          get_property(_included_dirs GLOBAL PROPERTY GlobalAddSubdirectoryOnceIncluded)
          list(FIND _included_dirs "${_fullpath}" _used_index)
          if (${_used_index} EQUAL -1)
              set_property(GLOBAL APPEND PROPERTY GlobalAddSubdirectoryOnceIncluded "${_fullpath}")
              _add_subdirectory(${_dir} ${ARGN})
          endif()
      else()
          message(WARNING "add_subdirectory: Can't find ${_fullpath}/CMakeLists.txt")
      endif()
  endfunction(add_subdirectory _dir)
  </code></pre>
  
  <p><strong>2.</strong> Adding an "include guard" to all sub-level <code>CMakeLists.txt</code>s, like:</p>
  
  <pre><code>if (NOT TARGET LibA)
      ...
  endif()
  </code></pre>
  
  <hr/>
  
  <p>I've been testing the concepts suggested by <a href="https://stackoverflow.com/users/3590849/tamas-kenez">tamas.kenez</a> and <a href="https://stackoverflow.com/users/678093/m-s">m.s.</a> with some promising results. The summaries can be found in my following answers:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/a/33587990/4763489">preferred cmake project structure</a></li>
  <li><a href="https://stackoverflow.com/a/33448011/4763489">CMake share library with multiple executables</a></li>
  <li><a href="https://stackoverflow.com/a/33568871/4763489">Making cmake library accessible by other cmake packages automatically</a></li>
  </ul>