I do use target_link_libraries when it comes to C++ projects and it works wonderfully for them. However, in this case, my base project has a bunch of helper files with CMake functionality that help me work with and build my library of projects (which you can see here https://github.com/2LoC/tl_base_ci).
Of course, these helper .cmake files (with the functionality I want) are in the tl_base_ci project which can be either (1) cloned separately, built, (2) Installed without building, or (3) cloned through ExternalProject_Add (which I am trying to convert to FetchContent). In all cases, the include directories might differ, which is why I use rely on the generator expressions expanding. In projects depending on tl_base_ci (e.g. https://github.com/2LoC/tl_proj_template), I have CMake includes like this: include("${tl_base_ci_INCLUDE_DIRECTORY}/tl_base_ci/tl_common.cmake") # in the actual project, it's slightly different as it searches for the file in a list of directories returned by get_target_property(... INTERFACE_INCLUDE_DIRECTORIES) Where the tl_base_ci_INCLUDE_DIRECTORY might differ. So ultimately I was hoping for a way to reliably include the helper .cmake files (i.e. figure out tl_base_ci's include directory path). I did that with get_target_property(...) which worked great for ExternalProject_Add, but did not work so well for FetchContent because the generator expressions did not expand. Hopefully I was able to explain the problem well. If there is any confusion, please let me know. On Mon, Mar 19, 2018 at 7:11 AM Craig Scott <[email protected]> wrote: > On Mon, Mar 19, 2018 at 8:25 AM, Saad Khattak <[email protected]> > 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 <[email protected]> >> wrote: >> >>> On Mon, Mar 19, 2018 at 3:44 AM, Saad Khattak <[email protected]> >>> 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 <[email protected]> >>>> 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 <[email protected]> >>>>> 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 >
-- 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: https://cmake.org/mailman/listinfo/cmake
