[CMake] ADD_SUBDIRECTORY() with a higher level directory

Michael Hertling mhertling at online.de
Sun Nov 6 20:23:23 EST 2011


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.

(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.

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