# Best practices to set imported package settings

**URL:** https://discourse.cmake.org/t/best-practices-to-set-imported-package-settings/3053
**Category:** Usage
**Created:** [March 31, 2021, 11:30am UTC](https://discourse.cmake.org/t/best-practices-to-set-imported-package-settings/3053 "2021-03-31T11:30:15Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![papush](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/47e85d/32.png) [@papush](https://discourse.cmake.org/u/papush)
#### Post date: [March 31, 2021, 11:30am UTC](https://discourse.cmake.org/t/best-practices-to-set-imported-package-settings/3053/1 "2021-03-31T11:30:15Z")

</div>

In Deniz Bahadir’s “More Modern CMake” talk, slide 12 presents how he  
integrates external dependencies by having a CMakeLists.txt file for  
each of them in an `external/` subdirectory. One thing i fail to  
understand is that this means any settings passed through as variable,  
in his case it’s things like `Boost_USE_STATIC_LIBS` and others, have  
to be declared in that CMakeLists.txt file, while it seems to me that  
such options should be set from where the `target_link_libraries()`  
call is made.

More specifically in my case i have a project with a library using the  
GLAD OpenGL loader generator, and it seems a clean way to do this would  
be to have in in an `external/` subdirectory in the same way, but that  
would mean that the OpenGL extensions i want to use, passed through the  
GLAD\_EXTENSIONS variable, would have to be set there. What if someone  
wanted to take my library out of the tree and provide the GLAD  
dependency in their own way, wouldn’t that mean they couldn’t know from  
the library alone that GLAD\_EXTENSIONS need to be set? What if i had  
multiple subproject using GLAD and wanting different extensions? I was  
planning on using FetchContent to retrieve glad too, which means that  
it’s more than a simple `find_package()` call that’d have to be  
specified in each of the libraries’ CMakeLists.txt too if i went that  
route.

I’m very new to CMake (and discourse), apologies for any major  
misunderstanding on my part.

 ![mpv-shot0010.jpg](https://discourse.cmake.org/uploads/default/original/2X/0/06fbb04996db8e4ae33c8d24aa653d8b3c9aff95.jpeg)

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [April 1, 2021, 4:14am UTC](https://discourse.cmake.org/t/best-practices-to-set-imported-package-settings/3053/2 "2021-04-01T04:14:32Z")

</div>

Probably you want to focus on setting/consuming details through targets rather than variables. I’ll let @dbahadir respond with further details though, since it’s his talk you’ve referenced.

---

<div class="post-metadata">

### Author: ![dbahadir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dbahadir/32/197_2.png) [@dbahadir](https://discourse.cmake.org/u/dbahadir)
#### Post date: [April 7, 2021, 11:19am UTC](https://discourse.cmake.org/t/best-practices-to-set-imported-package-settings/3053/3 "2021-04-07T11:19:06Z")

</div>

The example I presented in my talk has a specific requirement:

**I want to look for a specific (configuration of a) set of external libraries, that should be used throughout my entire program!**

So, this external dependency is some kind of global dependency for my entire project. Each target which uses that dependency has to use it with the same settings.

* * *

### Explanation on the example from the slides

For simpler reasoning I am reproducing the code from my presentation here:

```cmake
# ./external/boost/CMakeLists.txt -- Traditional/Modern CMake

set( BOOST_VERSION 1.58.0 )

# Settings for finding correct Boost libraries.
set( Boost_USE_STATIC_LIBS FALSE )
set( Boost_USE_MULTITHREADED TRUE )
set( Boost_USE_STATIC_RUNTIME FALSE )
set( Boost_ADDITIONAL_VERSIONS "${BOOST_VERSION}" )
set( Boost_COMPILER "-gcc" )

# Search for Boost libraries.
find_package( Boost ${BOOST_VERSION} EXACT REQUIRED
    COMPONENTS program_options
               graph )

# Make found targets globally available.
if ( Boost_FOUND )
    set_target_properties( Boost::boost
                           Boost::program_options
                           Boost::graph
        PROPERTIES IMPORTED_GLOBAL TRUE )
endif ()

```

What I am doing here is to look for an installed Boost libraries collection in version 1.58.0, but specifically only for the header-only part and the _Boost.ProgramOptions_ and _Boost.Graph_ shared libraries.  
Additionally I am saying, the shared libraries need to be compiled in such a way that they support multi-threading and are linked against a dynamic runtime. (The additional `Boost_COMPILER` variable indicates that they should have been compiled with the GCC compiler, although for newer built Boost versions that variable should probably contain the GCC version, too.)  
What settings-variables need to be set to find the correct libraries depends on the individual find-script for or the import-file of the library you are looking for. (For example, newer Boost libraries, in general, require a `Boost_ARCHITECTURE` variable, too, to be able to find the correct libraries.)

This might then find the shared libraries with the following names:

```auto
libboost_program_options-gcc-mt-1_58.so
libboost_graph-gcc-mt-1_58.so

```

Due to setting the `IMPORTED_GLOBAL` property the three found targets (`Boost::boost`, `Boost::program_options` and `Boost::graph`) are made globally visible and are therefore accessible from other directories, too, and not only sub-directories.

* * *

This is fine as long as you only ever need these three Boost targets throughout your entire project and all targets are fine with linking (via `target_link_libraries`) with these.

However, if one of your targets somehow requires a statically linked Boost library it cannot use these targets. In that case, you cannot use my approach because different targets need to find different libraries.  
In this situation you need to do local searches only (= do not set `IMPORTED_GLBOAL`).

* * *

### Possible solution for you problem

If you want to give a user the chance to modify the set of variables which are needed to find your dependency, you should probably provide some CMake `option` that should be set by the user and you then set these variables according to the value of the `option`.  
Or you can require, that these variables need to be set directly by the user. (You can always provide variables externally when calling CMake.)

If, however, two or more targets require different versions of your dependency then I do not see another way then to search for this dependency twice with different settings and not make the targets externally visible.

Other settings, that are not required for finding the correct dependency but “only” for how to use such a dependency, you should probably set through specific targets that you need to link, too, at the place where you link against the dependency.

---

<div class="post-metadata">

### Author: ![papush](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/47e85d/32.png) [@papush](https://discourse.cmake.org/u/papush)
#### Post date: [April 9, 2021, 9:51am UTC](https://discourse.cmake.org/t/best-practices-to-set-imported-package-settings/3053/4 "2021-04-09T09:51:36Z")

</div>

I guess i’ll do that then, thank you for that detailed answer
