title: Recursive list of LINK_LIBRARIES in CMake
body: <p>I am trying to acquire a list of the absolute paths to all libraries linked to a specific target in CMake for use in a call to <code>add_custom_command</code>. However, <code>get_target_property(_LINK_LIBRARIES ${TARGET} LINK_LIBRARIES</code> only includes the direct dependencies (i.e. anything that is used in a <code>target_link_libraries(${TARGET} ...)</code> call).</p>
  
  <p>Therefore, if I link another CMake target, e.g. <code>mylibrary</code>, the list would include <code>mylibrary</code>, but as a name only and without transitively linked libraries. As this list can also include arbitrarily complex generator expressions, checking each item if it is a target and retrieving its <code>LINK_LIBRARIES</code> recursively is not viable. Furthermore the target could be specified at a later point in the <code>CMakeLists.txt</code> and <code>if(TARGET mylibrary)</code> would be skipped.</p>
  
  <p>For <code>INCLUDE_DIRECTORIES</code> and <code>COMPILE_DEFINITIONS</code> this is easily solved, as although both behave similarly when <code>get_target_property</code> is used (except that linked targets are obviously not in the list), a generator expression of the form <code>$&lt;TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES&gt;</code> produces the desired list of recursively required includes and definitions. However, <code>$&lt;TARGET_PROPERTY:${TARGET},LINK_LIBRARIES&gt;</code> produces the same list as the <code>get_target_property</code> variant.</p>
  
  <p>How can I retrieve the desired list of absolute paths?</p>
  
  <p>Demonstration:</p>
  
  <pre><code>cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
  
  file(WRITE a.cpp "void foo() {};\n")
  file(WRITE b.cpp "int main(int, char**) { return 0; }\n")
  
  find_package(Boost REQUIRED COMPONENTS filesystem system)
  
  add_library(A STATIC a.cpp)
  target_include_directories(A PUBLIC ${Boost_INCLUDE_DIRS})
  target_link_libraries(A PUBLIC ${Boost_LIBRARIES})
  
  # demonstrates (at configure time) that the LINK_LIBRARIES property can contain
  # arbitrary generator expressions, making a recursive solution infeasible
  get_target_property(A_LINK_LIBRARIES A LINK_LIBRARIES)
  message(STATUS "A LINK_LIBARIES: ${A_LINK_LIBRARIES}")
  
  add_executable(B b.cpp b_lists)
  target_link_libraries(B PRIVATE A)
  target_include_directories(B PRIVATE .)
  
  get_target_property(B_INCLUDE_DIRECTORIES B INCLUDE_DIRECTORIES)
  get_target_property(B_LINK_LIBRARIES B LINK_LIBRARIES)
  
  # demonstrates (at compile time) that method 1 is not recursive while method 2 is (for INCLUDE_DIRECTORIES)
  # demonstrates (at compile time) that the library list is never recursive
  add_custom_command(
      OUTPUT b_lists
      COMMAND ${CMAKE_COMMAND} -E echo "B INCLUDE_DIRECTORIES 1: ${B_INCLUDE_DIRECTORIES}"
      COMMAND ${CMAKE_COMMAND} -E echo "B INCLUDE_DIRECTORIES 2: $&lt;TARGET_PROPERTY:B,INCLUDE_DIRECTORIES&gt;"
      COMMAND ${CMAKE_COMMAND} -E echo "B LINK_LIBRARIES 1: ${B_LINK_LIBRARIES}"
      COMMAND ${CMAKE_COMMAND} -E echo "B LINK_LIBRARIES 2: $&lt;TARGET_PROPERTY:B,LINK_LIBRARIES&gt;"
      DEPENDS A
  )
  set_source_files_properties(b_lists PROPERTIES SYMBOLIC TRUE)
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code>(configure)
  A LINK_LIBARIES: $&lt;$&lt;NOT:$&lt;CONFIG:DEBUG&gt;&gt;:D:/libs/boost-1_55_0/lib/boost_filesystem-vc110-mt-1_55.lib&gt;;$&lt;$&lt;CONFIG:DEBUG&gt;:D:/libs/boost-1_55_0/lib/boost_filesystem-vc110-mt-gd-1_55.lib&gt;;$&lt;$&lt;NOT:$&lt;CONFIG:DEBUG&gt;&gt;:D:/libs/boost-1_55_0/lib/boost_system-vc110-mt-1_55.lib&gt;;$&lt;$&lt;CONFIG:DEBUG&gt;:D:/libs/boost-1_55_0/lib/boost_system-vc110-mt-gd-1_55.lib&gt;
  (build)
  Generating b_lists
  B INCLUDE_DIRECTORIES 1: D:/projects/cmakeminimal/.
  B INCLUDE_DIRECTORIES 2: D:/projects/cmakeminimal/.;D:/libs/boost-1_55_0/include/boost-1_55
  B LINK_LIBRARIES 1: A
  B LINK_LIBRARIES 2: A
  </code></pre>