[CMake] Figuring out in a generator expression whether a name is a target

Attila Krasznahorkay attila.krasznahorkay at gmail.com
Fri Dec 11 09:11:08 EST 2015


Hi,

Just to let people know how I solved it in the end...

After wondering for a little while, I realised that the following should actually work more robustly:

   # Get the interface directories of the linked libraries:
   if( ARG_LINK_LIBRARIES )
      # First declare an interface library that will help us collect the
      # include paths from them:
      set( _genLibName ${dictname}GeneratorLib )
      add_library( ${_genLibName} INTERFACE )
      target_link_libraries( ${_genLibName} INTERFACE ${ARG_LINK_LIBRARIES} )
      # Now use this interface library to get the include paths:
      list( APPEND incdirs
         "$<TARGET_PROPERTY:${_genLibName},INTERFACE_INCLUDE_DIRECTORIES>" )
      unset( _genLibName )
   endif()

In this case it becomes non-important what sort of libraries are given as the LINK_LIBRARIES argument. The intermediate interface library takes care of collecting the include directories from the entities that provide such a thing.

Cheers,
            Attila

> On 11 Dec 2015, at 12:58, Attila Krasznahorkay <Attila.Krasznahorkay at gmail.com> wrote:
> 
> Dear All,
> 
> I'm trying to do something a bit more complicated, so please bear with me...
> 
> In our project we use a special kind of source code generator. Called a "dictionary generator". (https://root.cern.ch/how/how-use-reflex) To simplify the life of our users a bit, we provide a helper function for generating "dictionary libraries", which has a signature like:
> 
> atlas_add_dictionary( MyDictLibrary
>                      MyDictLibrary/MyDictLibraryDict.h
>                      MyDictLibrary/selection.xml
>                      INCLUDE_DIRS ...
>                      LINK_LIBRARIES ... )
> 
> Now, in order to make sure that the dictionary generation command succeeds, we need to pull in the public include paths of all the libraries that this library is supposed to be linked against, recursively. To do this, I do the following behind the scenes:
> 
> foreach( l ${ARG_LINK_LIBRARIES} )
>   # Skip physical libraries:
>   if( EXISTS ${l} )
>      continue()
>   endif()
>   # Skip generator expressions:
>   if( ${l} MATCHES "[$]<" )
>      continue()
>   endif()
>   # Get the include directories of this library:
>   list( APPEND includes "$<TARGET_PROPERTY:${l}:INTERFACE_INCLUDE_DIRECTORIES>" )
> endforeach()
> 
> As long as the users only specify either library targets, or absolute library path names here, this works well. But I just ran into some issues where this function is called with a system library name like "rt". So the project generation bails, complaining that "rt" is not a target.
> 
> Would it be possible to figure out in a generator expression if a given name is a target or not? Clearly I can't make this decision in an
> 
> if( TARGET ${l} )
> 
> statement, as the target may only get defined after this function call.
> 
> For now I'll be able to work around this issue, but I wonder if it would be possible to provide a full-proof implementation that would not be killed by the users specifying a low-level system library like this in the future.
> 
> Cheers,
>           Attila



More information about the CMake mailing list