1

I have multiple libraries which utilize the target_include_directories(myLib PUBLIC myLib/inc) command to populate their INTERFACE_INCLUDE_DIRECTORIES property. Now if I build a target which is linked against such a library the INTERFACE_INCLUDE_DIRECTORIES are propagated (as wanted) to the target.

My problem occurs when I try to use the get_property command to snatch the list of INCLUDE_DIRECTORIES of such a created target as - according to this already answered question - the linking of libraries is only evaluated at generate time and thus also the propagation of the INCLUDE_DIRECTORIES is only done at generate time.

What happens is that the list created via get_property is empty / incomplete. Is there a way to force CMake to evaluate the list again at generate time when all linking is also done? I want to use some string-operations on the list and use the result for a custom_command later on...

I'm using:

  • Cmake version 3.5.0
  • Scientific Linux release 7.2

Minimal Example of the problem

  1. Main CMakeLists.txt
    cmake_minimum_required (VERSION 2.8)
    project(MINIMAL LANGUAGES CXX) 
    
    add_subdirectory(${PROJECT_SOURCE_DIR}/libA)
    add_subdirectory(${PROJECT_SOURCE_DIR}/libB)
    
  2. libA CMakeLists.txt
    cmake_minimum_required (VERSION 2.8) 
    project (libA) 
    add_library(libA ${Some_Sources} ${Some_Header})
    # Set include_directories, this populates INTERFACE_INCLUDE_DIRECTORIES
    target_include_directories(libA PUBLIC "../libA/src")
    
  3. libB CMakeLists.txt
    cmake_minimum_required (VERSION 2.8) 
    project (libB) 
    add_library(libB ${Some_Sources} ${Some_Header})
    target_link_libraries(libB PUBLIC libA)
    target_include_directories(libB PUBLIC "../libB/src")
    
    # this contains only the value set here directly as 
    # get_property is evaluated at configure_time
    get_property(INC_DIR_LIST TARGET libB PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
    message(${INC_DIR_LIST})
    # >>> Output: ../libB/src
    
    # this expression is evaluated at generate time, 
    # thus it contains all needed information as the linking is done already
    file(GENERATE 
         OUTPUT "includes.txt" 
         CONTENT "$<TARGET_PROPERTY:libB,INTERFACE_INCLUDE_DIRECTORIES>\n
    # >>> Output in text-file: ../libB/src;../libA/src
    

Possible (but bad??) solution

As I know that (in the example) libB is linked against libA I could manually add:

get_property(INC_DIRS_LIBA TARGET libA PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(libB PUBLIC INC_DIRS_LIBA)

This would work as the property is now set correctly at configure time BUT it is now set twice at generate time (as CMake sets it again automatically when evaluating the linking) and it seems just wrong to me...

Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
Otherian
  • 11
  • 3
  • It is very unlikely that CMake will evaluate user-provided CMake code after generator-expressions are evaluated: that code may add something, that modifies value of generator expressions, so previous evaluation becomes invalid. You write, that you want to use list of include directories in custom COMMAND. What prevent you to read that list from the file, created with `file(GENERATE)`? If you need a scripting language for perform list processing, you may use `cmake -P – Tsyvarev Apr 10 '18 at 08:07
  • Thanks for your answer @Tsyvarev, but using the created file may be a good solution for this small example but doesn't scale well for a bigger project. In my case I would have to perform the task of creating and reading in the list for every target wich is linked against some others wich would result in 30+ textfiles and doesn't appear like a desired result to me... but I get your point that it's not easily possible (and not desired by CMake) to evaluate a list at generate time. Hm :( – Otherian Apr 10 '18 at 08:24

0 Answers0