[CMake] ADD_SUBDIRECTORY() with a higher level directory

Michael Hertling mhertling at online.de
Mon Nov 7 01:58:36 EST 2011


On 11/07/2011 04:55 AM, J Decker wrote:
> On Sun, Nov 6, 2011 at 5:23 PM, Michael Hertling <mhertling at online.de> wrote:
>> On 11/06/2011 07:49 PM, J Decker wrote:
>>>>
>>>> Of course, the CMakeLists.txt in examples (or example0 and example1) depends
>>>> on the actual library, so, from that level, we would like to call
>>>> ADD_SUBDIRECTORY() to the *higher level* library directory... which is
>>>> unacceptable for ADD_SUBDIRECTORY() (and probably conflicts with the whole
>>>> CMake structure).
>>>>
>>>> If we would move examples "up" the hierarchy there wouldn't be a problem,
>>>> but that doesn't give a nice distribution package.
>>>>
>>>> Any hints on a proper way to do this?
>>>
>>> I include higher level projects all over; you just have to specify an
>>> additional directory which is where that is built in the final output
>>> so you can do
>>> add_subdirectory( ../../whatever/example  __/__/whatever/example)
>>> which builds into the __/__ path in the build directory...
>>
>> The explicit build directory for ADD_SUBDIRECTORY() is not the actual
>> problem; the problems which arise with this practice are rather, IMO:
>>
>> (1) Without a top-level CMakeLists.txt, you've usually no bullet-proof
>> information about the other project's location, e.g. you can not refer
>> to CMAKE_SOURCE_DIR or the like. Instead, you must use a relative path
>> upwards from CMAKE_CURRENT_SOURCE_DIR like ../../whatever/example, and
>> the "../.." is a hard-coded assumption on the other project's relative
>> location w.r.t. the current project one's. If the latter or the other
>> project is once moved, this assumption proves wrong, and you will have
>> to edit possibly quite numerous ADD_SUBDIRECTORY() commands to fix up
>> things. Alternatively, you might provide the other project's location
>> via a cached variable, preferably with a reasonable default value.
>>
> 
> Thats true even if you change where a project is in a forward going direction.

Suppose your project consists of a library and n sub-projects which
refer to the library by ADD_SUBDIRECTORY(path/to/library), cf. the
OP's original concern. If the library is moved within the overall
project, you need to edit n ADD_SUBDIRECTORY() commands, whereas in
the strict top-down case with exactly one ADD_SUBDIRECTORY() command
for each CMakeLists.txt file except for the top-level one, you usually
need to edit at most two CMakeLists.txt files; this is what I've meant.

>> (2) If you additionally have an overall project as an entry point for
>> the configuration, the other project's CMakeLists.txt file might have
>> already been processed via an ADD_SUBDIRECTORY() command on behalf of
>> the overall project, so you must ensure that your current project's
>> CMakeLists.txt file doesn't invoke ADD_SUBDIRECTORY() on the other
>> one's source tree again.
>>
>> Both problems can be easily avoided if one does strictly organize the
>> projects in a top-down manner with a top-level CMakeLists.txt as the
>> sole entry point for the configuration. So, each CMakeLists.txt file
>> except for the top-level one is processed by one ADD_SUBDIRECTORY()
>> only, and you don't have to process any higher-level CMakeLists.txt
>> file because the superordinate one takes care of the correct order.
>>
> 
> So, by not having the problem in the first place, is your solution?

Do you mean the best solution of a problem is its avoidance? ;-) But
seriously, I am not sure if I got your objection correctly. In short,
my point is the following: If X calls ADD_SUBDIRECTORY(path/to/Y) and
Y isn't a sub-project of X, they're sibling projects within an overall
project; perhaps, one could say they share the same target space. Then,
no one should configure the other by ADD_SUBDIRECTORY(). Rather, there
should be a superordinate CMakeLists.txt calling ADD_SUBDIRECTORY() on
X and Y in the correct order, so that X can be sure that Y is already
configured. In this way, there is only one ADD_SUBDIRECTORY() command
for each CMakeLists.txt file, except for the top-level one, and each
ADD_SUBDIRECTORY() does actually enter a *sub*directory - no problem
with a sibling project's location, and none with multiply processed
CMakeLists.txt files. However, there might be exceptions, see [1].

Regards,

Michael

[1] http://www.mail-archive.com/cmake@cmake.org/msg39062.html

>> In other words: If a project uses ADD_SUBDIRECTORY() on a project's
>> directory other than a descendent one, this usually indicates that
>> these projects are tightly coupled parts of an overall project, so
>> it should be the job of the overall project's CMakeLists.txt to call
>> - or have call - the sub-projects' CMakeLists.txt files in a correct
>> order. Hence, each sub-project can be sure that all its prerequisite
>> projects have been configured before. OTOH, if two projects are not
>> tightly coupled parts of the same overall project, the one should
>> not invoke ADD_SUBDIRECTORY() on the other, but FIND_PACKAGE().
>>
>> Note that the above-mentioned points are just my personal liking;
>> certainly, there are different opinions, and there might very
>> well be setups which require a different approach.
>>
>> Regards,
>>
>> Michael


More information about the CMake mailing list