[CMake] How to test for the usability of a target

Andreas Mohr andi at lisas.de
Tue Oct 15 15:20:11 EDT 2013


Hi,

On Tue, Oct 15, 2013 at 12:00:05PM -0400, cmake-request at cmake.org wrote:
> Date: Tue, 15 Oct 2013 17:49:40 +0200
> From: Johannes Zarl <johannes.zarl at jku.at>

> Hi,
> 
> I'd like to make some code in my build system dependent on the existance of a 
> target. Basically I'd like to write something like this:
> 
> if(TARGET optional_lib)
>   add_library(bar ${bar_srcs})
>   target_link_library(bar optional_lib)
> endif()
> 
> The problem I have is that for a couple of reasons the CMakelists file for bar 
> needs to be read before optional_lib. Therefore the "TARGET optional_lib" test 
> fails even though I can link bar successfully against optional_lib.

May I suggest that perhaps it might happen to be these couple reasons
that are "wrong"? :)


> I'm currently working around the issue by letting the optional lib set a cache 
> variable and testing for the variable instead of the target. Is there a way to 
> actually get the information from the bulid system, or is this a hard limit of 
> the CMake parser?

Parsing does happen strictly sequentially AFAIK,
thus the only way to have some components interact in case of
non-sequential layout would be some caching/persistence mechanisms
as you are already starting to use.

Another alternative would be to provide persistence by defining some function
to be called externally to have some further dependencies added to that specific
target.

I.e., sub CMakeLists.txt provides the function,
then a more parent level CMakeLists.txt
(or, in fact, the particular level which encompasses handling
of both target and optional lib components)
could be invoking that function with the optional lib as the argument,
if and only if the optional lib caused a successful if(TARGET) check.



Or, to think somewhat more clearly and generally about it,
perhaps think of a CMake build environment as a whole
as sub scopes sometimes simply being used to define
*what* to *potentially* use/create,
and each responsible parent scope then subsequently actively
combining these pre-defined elements via utility functions
that sub scopes decided to provide.
And perhaps throw in a couple if(COMMAND foo) for good measure,
as needed to achieve sufficiently flexible handling in upper scopes.
But that will probably go against the recommendation that sub projects
be as self-contained as possible (IOW, the sub project ideally would manage
linking to the optional library via its own *internal* handling),
since one would want to encourage creating "portable" sub projects:
throw into entirely different higher-level aggregation tree (i.e.
a completely different "whole-application build"),
and bamm, sub component keeps working without any effort - think capability
directly aligned with sub projects/modules feature of **most**
[but not certain somewhat inferior proprietary ones - ahem!]
source control management tools.




In fact since at top level both targets will end up known,
one could even skip having to define some new utility functions
for that purpose, by simply directly adding link instructions there -
but that could arguably be quite a bit less clean
than providing internal helper functions to abstract certain internal
decisions...

HTH,

Andreas Mohr


More information about the CMake mailing list