[cmake-developers] Tools for handling cross project dependencies

Raffi Enficiaud raffi.enficiaud at mines-paris.org
Mon Oct 2 18:20:19 EDT 2017


Le 02.10.17 à 18:06, Egor Pugin a écrit :
> Sorry, maybe I did not understand you correctly, but why do you need
> some order of 'add_subdirectory'?

I am not sure to understand why you are asking this, please let me know 
if I am off-topic :)

I have say libOpenCV, libTIFF and libZ. libTIFF depends on libZ, 
libOpenCV depends on libTIFF and libZ.

libTIFF and libZ are doing some magic, say they compile from source or 
if those libraries are available from the OS, they just include the 
system libraries as imported targets.

In a project, I would like to link to libOpenCV, I know it depends on 
libTIFF and libZ, but I do not know if there is any dependencies between 
those libTIFF and libZ.

I know that I should do an add_subdirectory(libOpenCV) and before that, 
do an add_subdirectory of libTIFF and libZ. Depending on the orders of 
the add_subdirectory, I would be able to compile or not libTIFF and 
subsequently libOpenCV.

This should work:

"""""
add_subdirectory(libZ)
add_subdirectory(libTIFF)
add_subdirectory(libOpenCV)
"""""

and this should not work
"""""
add_subdirectory(libTIFF)
add_subdirectory(libZ)
add_subdirectory(libOpenCV)
"""""

(because the declaration of the libTIFF targets make implicit reference 
to headers and shared/static library of libZ.)

So in a "superproject" (the one that is making the 3 calls to 
add_subdirectory above), there is an implicit orchestration/ordering of 
the add_subdirectory commands, and I would somehow like to encode this 
within CMake and without any other tool.

Of course, in this very naive and simplified example, it is easy to 
address, but this does not scale up efficiently. Somehow, there is a 
need to encode the graph of dependencies, and to inject that graph into 
CMake.

This is what I suggest to do: discuss about the interest and the 
"protocol" for encoding such a graph, and what type of information which 
should carry in the graph (nodes and arrows).

> Cppan knows from config (yaml) files what deps must be included and
> just adds them one by one. If they're already in the tree, include
> guard prevents second use.

Right, but there is also an explicit order in your YAML files, isn't it? 
I have to say I have not look very deeply.

> One rule is not to have cyclic deps.

Yes, the dependencies should form a Directed Acyclic Graph, otherwise we 
have troubles. This can be checked also very easily.


>> In summary (correct me if I am wrong) what this does is (in some pseudo code):
>
> Correct pseudo code for cppan:
> ---
> if (TARGET t1)
>   return
>
> include(d1) # include file has i. guard
> include(d2) # cannot use add_subdirectory directly
> ...
>
> declare t1
> target_deps t1 d1 d2 ...
> ---

Also in a more complicated settings, you can certainly have the targets 
defined by
d1/d2 sourced by another CMakeLists.txt (say libZ used for target 
t1=OpenCV and target
t2=libYAML, those being on different CMakeLists.txt).

You address this by adding an include guard.
As a matter of facts, include guards are inducing a topological sort on 
the order
of the targets declaration (roughly speaking "include guards=an 
implementation of topological sort").

Having access to the dependency graph is however providing a richer 
information and ease
of maintenance, and I am pretty sure this can find many different use cases
(outside of mine of course).

For example:

* being agnostic to the overall directory layout: in your example you 
only care about the
   targets d1/d2 being declared, not the file/location of their 
declaration (while the include
   directive enforces some directory layout)
* detect cyclic dependencies
* easy filtering of include or add_subdirectory calls, based on the 
selection of specific
   targets (only the direct and indirect parents of the selected target 
are included in the project,
   which is easy to do if we have access to the dependency graph)
* generated installation package dependency declaration (the debian 
packages extract the
   direct dependencies from this graph)
* etc...

I hope I clarified better the problems I am trying to address,

Best,
Raffi

> On 2 October 2017 at 16:10, Raffi Enficiaud
> <raffi.enficiaud at mines-paris.org> wrote:
>> Le 27.09.17 à 19:10, Egor Pugin a écrit :
>>>>
>>>> The idea is to include several "packages" (one package ~ one project in
>>>> Boost) and make those available to the build, exactly as for a regular
>>>> CMakeLists.txt that adds several directories or subprojects through a
>>>> sequence of calls to "add_directories".
>>>> However, the difference here is that "packages" have inter-dependencies,
>>>> and the order of the "add_directories" should honor those dependencies.
>>>
>>>
>>> I solved the issue of including several dirs (via 'add_directories')
>>> using guards 'if (TARGET name); return(); endif()' in my pkg manager.
>>> See boost libraries there: https://cppan.org/search?q=boost
>>> Each library can be included to project separately with autoincluding
>>> required deps for it.
>>
>>
>> Hi,
>>
>> Thank you for your answer. What you did with CPAN is wonderful, but I think
>> this much more than what my humble scripts are trying to address.
>>
>> Also the guard mechanism does not really address the issue of ordering the
>> add_directories in some topological order. In particular, you guard because
>> you do not want to declare several times the same target, but it does not
>> tell when to include any other dependencies your target may have.
>>
>> In summary (correct me if I am wrong) what this does is (in some pseudo
>> code):
>>
>> ---------
>> if(target1, target2 ... already defined)
>>   return
>>
>> declare target1, target2 ...
>> target_dependencies target1, target1.1, target1.2 ...
>> target_dependencies target2, target2.1, target2.2 ...
>> ---------
>>
>> but it does not tell when to declare target1.1, target1.2 ... and this
>> knowledge should be encoded somewhere else in your scripts.
>>
>> Best,
>> Raffi
>>
>>
>>
>> --
>>
>> Powered by www.kitware.com
>>
>> Please keep messages on-topic and check the CMake FAQ at:
>> http://www.cmake.org/Wiki/CMake_FAQ
>>
>> Kitware offers various services to support the CMake community. For more
>> information on each offering, please visit:
>>
>> CMake Support: http://cmake.org/cmake/help/support.html
>> CMake Consulting: http://cmake.org/cmake/help/consulting.html
>> CMake Training Courses: http://cmake.org/cmake/help/training.html
>>
>> Visit other Kitware open-source projects at
>> http://www.kitware.com/opensource/opensource.html
>>
>> Follow this link to subscribe/unsubscribe:
>> http://public.kitware.com/mailman/listinfo/cmake-developers
>
>
>




More information about the cmake-developers mailing list