Populate INCLUDE_DIRECTORIES of object libraries from INTERFACE_INCLUDE_DIRECTORIES of other libraries

Populate INCLUDE_DIRECTORIES of object libraries from INTERFACE_INCLUDE_DIRECTORIES of other libraries

Hello,

I'm trying to improve parallelization of a massive parallel
Ninja/icecream build by using object libraries. We are already using
interface include directories extensively.

While moving the compilation to separate object libraries I need to
define the include directories for these object targets. Previously
this simply worked by target_link_library(x PRIVATE a) so that x uses
the public and interface include directories of a. With object
libraries this is not possible, for example

gives the error message
Object library target "b" may not link to anything
with CMake 3.7, 3.9 and 3.10rc3. The documentation of the later
version says "OBJECT libraries may not be used in the right hand side
of target_link_libraries()" but does not restrict the left hand side.
I would expect it to build b with include-directory "include" from a.

Currently I'm using a workaround
FOREACH(Lib ${ARG_LINK})
IF(TARGET ${Lib})
TARGET_INCLUDE_DIRECTORIES(MyObjectLib PRIVATE
$<TARGET_PROPERTY:${Lib},INTERFACE_INCLUDE_DIRECTORIES>)
ENDIF()
ENDFOREACH()
but this only works for targets previously defined or only target
libraries may be used. Otherwise the generator fails for file names or
system library names because there is no generator expression to check
for existing targets (see
https://gitlab.kitware.com/cmake/cmake/issues/17123). I want to avoid
explicitly import all these libraries.

Is there an other reliable way to populate include_directories that I
have not yet found? Of course compile_definitions and compile_options
should be added from the other libraries too.

Re: Populate INCLUDE_DIRECTORIES of object libraries from INTERFACE_INCLUDE_DIRECTORIES of other libraries

Which version of CMake and Ninja are you using?
It seems like you are trying to reimplement what has been added in CMake
3.9. Quote from the changelog:

The Ninja generator has loosened the dependencies of object compilation.
Object compilation now depends only on custom targets and custom
commands associated with libraries on which the object’s target depends
and no longer depends on the libraries themselves. Source files in
dependent targets may now compile without waiting for their targets’
dependencies to link.

Have you tried it? It shouldn't need any change in your project, but I'm
not sure how it will behave if you already started to migrate to OBJECT
libraries.

Regards,
Florent

On 14/11/2017 17:48, Bernhard Burgermeister wrote:

> Hello,
>
> I'm trying to improve parallelization of a massive parallel
> Ninja/icecream build by using object libraries. We are already using
> interface include directories extensively.
>
> While moving the compilation to separate object libraries I need to
> define the include directories for these object targets. Previously
> this simply worked by target_link_library(x PRIVATE a) so that x uses
> the public and interface include directories of a. With object
> libraries this is not possible, for example
>
> ======================================
> CMAKE_MINIMUM_REQUIRED(VERSION 3.7)
> PROJECT(ObjectLibLink C)
>
> ADD_LIBRARY(a INTERFACE)
> TARGET_INCLUDE_DIRECTORIES(a INTERFACE include)
>
> ADD_LIBRARY(b OBJECT b.c)
> TARGET_LINK_LIBRARIES(b PRIVATE a)
> ======================================
>
> gives the error message
> Object library target "b" may not link to anything
> with CMake 3.7, 3.9 and 3.10rc3. The documentation of the later
> version says "OBJECT libraries may not be used in the right hand side
> of target_link_libraries()" but does not restrict the left hand side.
> I would expect it to build b with include-directory "include" from a.
>
> Currently I'm using a workaround
> FOREACH(Lib ${ARG_LINK})
> IF(TARGET ${Lib})
> TARGET_INCLUDE_DIRECTORIES(MyObjectLib PRIVATE
> $<TARGET_PROPERTY:${Lib},INTERFACE_INCLUDE_DIRECTORIES>)
> ENDIF()
> ENDFOREACH()
> but this only works for targets previously defined or only target
> libraries may be used. Otherwise the generator fails for file names or
> system library names because there is no generator expression to check
> for existing targets (see
> https://gitlab.kitware.com/cmake/cmake/issues/17123). I want to avoid
> explicitly import all these libraries.
>
>
> Is there an other reliable way to populate include_directories that I
> have not yet found? Of course compile_definitions and compile_options
> should be added from the other libraries too.
>
>
> Regards,
> Bernhard.

Re: Populate INCLUDE_DIRECTORIES of object libraries from INTERFACE_INCLUDE_DIRECTORIES of other libraries

Hi Florent,

thanks for the hint about changed Ninja behaviour. We started the
separation into object libraries with CMake 3.7 and want to use this
also together with Unix Makefiles or JOM on Windows (and perhaps also
Visual Studio 2015 generator).

Even together with CMake 3.10 and Ninja I have to stay with the object
libraries because we have many mixed language libraries
(C/C++/Fortran) so the object libraries give me more control. With
separate object libraries I can assign a compile_pool for the Fortran
files (which can not be distributed by icecream) and I can avoid
dependency of the C/C++ files on the generated Fortran files we use
for automatic interface check (and I need to keep the Fortran files in
the main library to have full Fortran 90 dependency detection, so the
C/C++ files have to be moved to the object library).

> Which version of CMake and Ninja are you using?
> It seems like you are trying to reimplement what has been added in CMake
> 3.9. Quote from the changelog:
>
> The Ninja generator has loosened the dependencies of object compilation.
> Object compilation now depends only on custom targets and custom commands
> associated with libraries on which the object’s target depends and no longer
> depends on the libraries themselves. Source files in dependent targets may
> now compile without waiting for their targets’ dependencies to link.
>
> Have you tried it? It shouldn't need any change in your project, but I'm not
> sure how it will behave if you already started to migrate to OBJECT
> libraries.
>
> Regards,
> Florent
>
>
> On 14/11/2017 17:48, Bernhard Burgermeister wrote:
>>
>> Hello,
>>
>> I'm trying to improve parallelization of a massive parallel
>> Ninja/icecream build by using object libraries. We are already using
>> interface include directories extensively.
>>
>> While moving the compilation to separate object libraries I need to
>> define the include directories for these object targets. Previously
>> this simply worked by target_link_library(x PRIVATE a) so that x uses
>> the public and interface include directories of a. With object
>> libraries this is not possible, for example
>>
>> ======================================
>> CMAKE_MINIMUM_REQUIRED(VERSION 3.7)
>> PROJECT(ObjectLibLink C)
>>
>> ADD_LIBRARY(a INTERFACE)
>> TARGET_INCLUDE_DIRECTORIES(a INTERFACE include)
>>
>> ADD_LIBRARY(b OBJECT b.c)
>> TARGET_LINK_LIBRARIES(b PRIVATE a)
>> ======================================
>>
>> gives the error message
>> Object library target "b" may not link to anything
>> with CMake 3.7, 3.9 and 3.10rc3. The documentation of the later
>> version says "OBJECT libraries may not be used in the right hand side
>> of target_link_libraries()" but does not restrict the left hand side.
>> I would expect it to build b with include-directory "include" from a.
>>
>> Currently I'm using a workaround
>> FOREACH(Lib ${ARG_LINK})
>> IF(TARGET ${Lib})
>> TARGET_INCLUDE_DIRECTORIES(MyObjectLib PRIVATE
>> $<TARGET_PROPERTY:${Lib},INTERFACE_INCLUDE_DIRECTORIES>)
>> ENDIF()
>> ENDFOREACH()
>> but this only works for targets previously defined or only target
>> libraries may be used. Otherwise the generator fails for file names or
>> system library names because there is no generator expression to check
>> for existing targets (see
>> https://gitlab.kitware.com/cmake/cmake/issues/17123). I want to avoid
>> explicitly import all these libraries.
>>
>>
>> Is there an other reliable way to populate include_directories that I
>> have not yet found? Of course compile_definitions and compile_options
>> should be added from the other libraries too.
>>
>>
>> Regards,
>> Bernhard.
>
>
>