# What is the correct or best way to build/install 3rdParty code with multiple configuraions?

**URL:** https://discourse.cmake.org/t/what-is-the-correct-or-best-way-to-build-install-3rdparty-code-with-multiple-configuraions/10897
**Category:** Usage
**Created:** [May 23, 2024, 10:24pm UTC](https://discourse.cmake.org/t/what-is-the-correct-or-best-way-to-build-install-3rdparty-code-with-multiple-configuraions/10897 "2024-05-23T22:24:05Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![JRR](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/j/ecccb3/32.png) [@JRR](https://discourse.cmake.org/u/JRR)
#### Post date: [May 23, 2024, 10:24pm UTC](https://discourse.cmake.org/t/what-is-the-correct-or-best-way-to-build-install-3rdparty-code-with-multiple-configuraions/10897/1 "2024-05-23T22:24:05Z")

</div>

My company uses 3rdParty libraries with Windows and Linux compiles. We will compile these 3rdParty libraries once and deploy them to a common location on a file share.

Using the glorious magic of `find_package()` developers are able to find and integrate the 3rd Party libraries.

Recently, we started using a library whose Release binary won’t link with out VS debug binaries.

So I thought the fix would be to compile Release and Debug and then install and the glory of relocatable packages would return the correct image.

Sadly this isn’t true in this scenario because the library has the same name be it release or debug and it’s deployed to the same folder.

Is there an easy CMake way around this that doesn’t require that I edit the 3rd Party CMakefile `install()` logic?

I was toying with ideas like deploying release and debug to different locations, but that won’t work with `find_package()` logic because we don’t know the build configuration at config time for Visual Studio compiles, and that would be required to correctly set the prefix search path for `find_package()` to find the debug or release version of the library.

I cannot believe that I’m the first to encounter this problem, and so would like to learn what others have done in this scenario.

---

<div class="post-metadata">

### Author: ![JRR](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/j/ecccb3/32.png) [@JRR](https://discourse.cmake.org/u/JRR)
#### Post date: [May 23, 2024, 11:59pm UTC](https://discourse.cmake.org/t/what-is-the-correct-or-best-way-to-build-install-3rdparty-code-with-multiple-configuraions/10897/2 "2024-05-23T23:59:00Z")

</div>

I found a workaround, but I’m hoping to learn other ways.

I created a top-level `CMakeLists.txt` file that incorporates the 3rdParty library file using `add_subdirectory()`

After doing `add_subdirectory()` I found all the targets under the current folder using the following function that I created after some StackOverflow learning.

```auto
function(stvn_get_all_cmake_targets OUT_VAR START_DIR)
    get_property(CMAKE_TGTS DIRECTORY ${START_DIR} PROPERTY BUILDSYSTEM_TARGETS)
    get_property(SUBDIRS DIRECTORY ${START_DIR} PROPERTY SUBDIRECTORIES)

    foreach(SUBD ${SUBDIRS})
        stvn_get_all_cmake_targets(SUBD_TGTS ${SUBD})
        list(APPEND CMAKE_TGTS ${SUBD_TGTS})
    endforeach()

    set(${OUT_VAR} ${CMAKE_TGTS} PARENT_SCOPE)
endfunction()

```

Then I loop over each of the targets that were found and set the `DEBUG_POSTFIX`, `RELEASE_POSTFIX` and `RELWITHDBINFO_POSTFIX` values for each one.

  

This adds R, D or RD to the end of each library or executable that’s generated, making them unique entries in the install folder. And the cmake relocatable package logic correctly points to the appropriate file for the desired configuration.

i.e. fooTarget-release points at the R image, fooTarget-debug points at the D image, etc.

This works, but I’m a little nervous because I don’t know for certain if the 3rd Party libray has done anything _special_ with names, etc.

Is there a better way?

---

<div class="post-metadata">

### Author: ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)
#### Post date: [May 24, 2024, 11:37am UTC](https://discourse.cmake.org/t/what-is-the-correct-or-best-way-to-build-install-3rdparty-code-with-multiple-configuraions/10897/3 "2024-05-24T11:37:45Z")

</div>

As a small improvement, note that when a target is created, its property `DEBUG_POSTFIX` is initialised with the value of the variable `CMAKE_DEBUG_POSTFIX` if it’s set (see [docs of `<CONFIG>_POSTFIX`](https://cmake.org/cmake/help/latest/prop_tgt/CONFIG_POSTFIX.html) for details).

This means that if you set `CMAKE_DEBUG_POSTFIX` before calling `add_subdirectory()`, you should get the targets set up without the need for enumerating them and postprocessing them individually.

---

<div class="post-metadata">

### Author: ![JRR](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/j/ecccb3/32.png) [@JRR](https://discourse.cmake.org/u/JRR)
#### Post date: [May 24, 2024, 3:00pm UTC](https://discourse.cmake.org/t/what-is-the-correct-or-best-way-to-build-install-3rdparty-code-with-multiple-configuraions/10897/4 "2024-05-24T15:00:51Z")

</div>

@Angew,

Thank you for that tip.

As a company we’ve been leaning into target specific settings rather than global settings. My mentor, no longer available, was saying it’s due to better control on a target by target basis.

I really like the simplicity of what you’ve shared, but I have so many “don’t do that” code review memories… would you be able to shed some light on on this topic of global vs. targeted settings?

I know this is a shift in focus, but I would appreciate your insights.

Thank you.

---

<div class="post-metadata">

### Author: ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)
#### Post date: [May 27, 2024, 11:07am UTC](https://discourse.cmake.org/t/what-is-the-correct-or-best-way-to-build-install-3rdparty-code-with-multiple-configuraions/10897/5 "2024-05-27T11:07:07Z")

</div>

Modern CMake is moving towards a target-centric approach, specifying settings using build targets and their properties instead of global settings. Note, however, that what I suggested is in line with that approach. `CMAKE_DEBUG_POSTFIX` is not a global setting; it’s an initialiser of a per-target property, simply a shorthand for setting the propeties on many related targets (those in the given subdir tree) at the same time. Its use would look like this:

```auto
set(CMAKE_DEBUG_POSTFIX D)
set(CMAKE_RELEASE_POSTFIX R)
set(CMAKE_RELWITHDEBINFO_POSTFIX RD)
add_subdirectory(the3rdPartyLib)
unset(CMAKE_DEBUG_POSTFIX)
unset(CMAKE_RELEASE_POSTFIX)
unset(CMAKE_RELWITHDEBINFO_POSTFIX)

```

Contrast this with a truly global setting such as `CMAKE_CXX_FLAGS`. That is a variable which affects the build directly; its final value affects all targets for which it is in scope, regardless of the value it had when such targets were created. Global settings such as these is what modern CMake is moving away from, and I wholeheartedly support this move to a target-centric approach.
