[CMake] Generator Expressions and FetchContent

Craig Scott craig.scott at crascit.com
Mon Mar 19 07:11:01 EDT 2018


On Mon, Mar 19, 2018 at 8:25 AM, Saad Khattak <saadrustam at gmail.com> wrote:

> Thank you for the clarification Craig.
>
> >> If you made your main target link against LibA, you'd see that CMake
> automatically expands out the generator expressions when it constructs the
> link command line for main, so the example as it stands doesn't actually
> have any error.
>
> In my actual project, a library like LibA has .cmake files that can be
> included by dependent projects to reuse. Of course, CMake `include` does
> not get affected by target_link_libraries.
>
> I would like dependent projects to have the ability to use an existing
> clone of LibA, if found (e.g. using find_package), otherwise clone locally
> for using ExternalProject_Add which I am now trying to refactor to
> FetchContent. Another option open to dependent projects is to force the
> FetchContent on all repositories regardless of what find_package returns
> (this is great for testing locally to ensure I have no uncommitted,
> unpushed changes).
>
> Using existing clones is a way to ensure that every project dependent on
> LibA doesn't clone it's own copy (unless forced to do so).
>
> To allow the possibility for any dependent project to include the .cmake
> files properly, I get the INTERFACE_INCLUDE_DIRECTORIES target property
> (using get_target_property) for LibA and then include the .cmake utility
> files like this:
>
> include(${LibA_INCLUDE_DIRECTORY}/my_utility.cmake)
>
> Perhaps I am approaching the problem incorrectly? Essentially, I would
> like a way to reliably include .cmake files found in LibA's include folder
> regardless of how LibA was acquired (e.g. cloned and built and/or installed
> separately or acquired using FetchContent). In my case, I could only think
> of the above as a reliable way to include the files.
>

Rather than focusing on including files, I would choose to base things
around targets. If the rest of your project simply links against the
required target name, the target itself should bring with it any transitive
dependencies such as required header search paths, dependent libraries that
must also be linked, etc. These are the INTERFACE_... properties that can
be set on a target, usually by commands such as
target_include_directories(foo INTERFACE ...), target_link_libraries(foo
INTERFACE ...), etc. When building directly from your source tree, the
targets will be directly available. When using find_package(), the package
should provide import targets. The rest of your project shouldn't really
need to care which one of the two it is dealing with. This is the
recommended way to structure a situation like this. You shouldn't need to
also pull in a secondary .cmake file in most circumstances, but maybe I'm
missing something about your particular situation.



>
> On Sun, Mar 18, 2018 at 4:22 PM Craig Scott <craig.scott at crascit.com>
> wrote:
>
>> On Mon, Mar 19, 2018 at 3:44 AM, Saad Khattak <saadrustam at gmail.com>
>> wrote:
>>
>>> Absolutely. Please find the example project here: https://github.com/
>>> samaursa/cmake_fetch_content_and_generator_expressions
>>>
>>> The repository README also includes the output from running
>>> `./setup.sh`.
>>>
>>
>>
>> Okay that's much clearer, thanks. The example is doing what I'd expect
>> and the generator expressions are also expected to be visible at the point
>> your example is printing them. If you made your main target link against
>> LibA, you'd see that CMake automatically expands out the generator
>> expressions when it constructs the link command line for main, so the
>> example as it stands doesn't actually have any error.
>>
>> Generator expressions are not expanded when CMake is processing the files
>> (called the *configure* stage), they are expanded only when writing out
>> the Makefiles during the *generation* stage. When running cmake from the
>> command line, one doesn't tend to think of these two phases as being
>> distinct, but you can see it at the end of the cmake log with these two
>> messages:
>>
>> -- Configuring done
>> -- Generating done
>>
>> It is clearer when using the CMake GUI application because you get two
>> different buttons, one for Configure and another for Generate, so you have
>> to trigger both phases manually. So if you look at the contents of various
>> properties and variables with CMake commands like message(...), you are
>> doing that during the configure stage and therefore will see unexpanded
>> generator expressions.
>>
>>
>>
>>
>>>
>>> On Sat, Mar 17, 2018 at 6:47 PM Craig Scott <craig.scott at crascit.com>
>>> wrote:
>>>
>>>> Can you provide a small project example that can be used to demonstrate
>>>> your problem? The specifics of how you are doing things may be important.
>>>>
>>>>
>>>> On Sun, Mar 18, 2018 at 8:12 AM, Saad Khattak <saadrustam at gmail.com>
>>>> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> ExternalProject_Add builds, generates and installs and thus any
>>>>> generator expressions used will be expanded by the time another library
>>>>> uses it.
>>>>>
>>>>> For example, if I add a library LibA using ExternalProject_Add, I can
>>>>> then query the target property INTERFACE_INCLUDE_DIRECTORIES and get the
>>>>> include directory for the library:
>>>>>
>>>>> get_target_property(LibA_INCLUDE_DIRECTORIES LibA
>>>>>   INTERFACE_INCLUDE_DIRECTORIES
>>>>>   )
>>>>>
>>>>> This allows me to then use the variable LibA_INCLUDE_DIRECTORIES in my
>>>>> CMake include(...) statements. However, with FetchContent, this is no
>>>>> longer possible.
>>>>>
>>>>> The reason I would like to query a variable is because at project
>>>>> generation time, I invoke FetchContent only if LibA is not found by
>>>>> find_package(LibA).
>>>>>
>>>>> Thus, the include directory for LibA may be in the current build
>>>>> directory (through FetchContent) OR it may be found in the folder where
>>>>> LibA is cloned by the user and generated/built OR an INSTALL of LibA.
>>>>>
>>>>> Perhaps I should not be using `get_target_property` to get the a
>>>>> library's include directory? Either way, would like some guidance in
>>>>> solving this issue.
>>>>>
>>>>> Thank you,
>>>>> Saad
>>>>>
>>>>
>>


-- 
Craig Scott
Melbourne, Australia
https://crascit.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cmake.org/pipermail/cmake/attachments/20180319/e9be5146/attachment-0001.html>


More information about the CMake mailing list