Linking different libraries for Debug and Release builds in Cmake on windows?
Asked Answered
R

6

77

So I've got a library I'm compiling and I need to link different third party things in depending on if it's the debug or release build (specifically the release or debug versions of those libraries). Is there an easy way to do this in Cmake?

Edit: I should note I'm using visual studio

Ricky answered 5/2, 2010 at 19:47 Comment(0)
H
107

According to the CMake documentation:

target_link_libraries(<target> [lib1 [lib2 [...]]] [[debug|optimized|general] <lib>] ...)

A "debug", "optimized", or "general" keyword indicates that the library immediately following it is to be used only for the corresponding build configuration.

So you should be able to do this:

add_executable( MyEXE ${SOURCES})

target_link_libraries( MyEXE debug 3PDebugLib)
target_link_libraries( MyEXE optimized 3PReleaseLib)
Haroldharolda answered 8/2, 2010 at 20:45 Comment(9)
I do this all the time, even more compactly on one line: target_link_libraries(MyEXE debug 3PDebugLib optimized 3PReleaseLib)Echidna
What if the library name is the same, but you want visual studio to look for it at a different path? i.e. I want to link mylib.lib but I have two versions of it compiled. one under /path/Debug/mylib.lib and another under /path/Release/mylib.lib (as is often the case with some libraries). What do you do then?Iroquoian
@Iroquoian Define 2 variables. One for each library.Hubble
If you want "Release" as in VS 2010 then you need to specify "Release" instead of "optimized" for target_link_libraries. Note that this is case-sensitive. Also you can check for "Release" in your cmake like that: IF(CMAKE_BUILD_TYPE MATCHES Release) again case sensitive.Offense
You should not test CMAKE_BUILD_TYPE in the CMake file, it is ignored by multi configuration generators (like VS). If you run cmake with CMAKE_BUILD_TYPE=Debug but Release in VS the code in if(CMAKE_BUILD_TYPE MATCHES Release) is simply ineffective.Myrtie
It's adding both the debug and release libs when trying the above in my project...Vaishnava
And remember the DEBUG_CONFIGURATIONS property that detects which configurations are debugCharles
@Vaishnava You have to define this for each library. You can use foreachBuyse
Nope. I get a library called debug.lib and optimized.libActinometer
B
19

Somehow the answer from @Mike Willekes got CMake linking in the same target both release and debug for me :(

I only got this working by setting both configurations in one line, as suggested by @sakra in a related question - and doing so for every library that needed to be linked:

target_link_libraries ( app
    debug ${Boost_FILESYSTEM_LIBRARY_DEBUG}
    optimized ${Boost_FILESYSTEM_LIBRARY_RELEASE} )

target_link_libraries ( app
    debug ${Boost_LOG_LIBRARY_DEBUG}
    optimized ${Boost_LOG_LIBRARY_RELEASE} )

target_link_libraries ( app
    debug ${Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG}
    optimized ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE} )

# ...
Burletta answered 16/8, 2016 at 19:32 Comment(5)
Ah, this is what was happening to me! We only want to link a particular library in release mode, so your method didn't work. In the end I worked around it by using something like the following: if (CMAKE_BUILD_TYPE STREQUAL "Release") target_link_libraries(${ARG_NAME} ${LIB_TCMALLOC} ) endif()Pugilism
The drawback, @SteveLorimer, is that in multi config generators - such as for Visual Studio - this would not work as it is done in generate time.Burletta
not sure I understand? We don't link tcmalloc in debug builds. We do link tcmalloc in release builds. That is, there isn't a debug version of tcmalloc, so listing it under optimized only results in it getting linked into debug builds as wellPugilism
That's strange, @SteveLorimer. Looking into CMake's docs it's stated that: "The debug keyword corresponds to the Debug configuration (...). The optimized keyword corresponds to all other configurations." (cmake.org/cmake/help/v3.0/command/target_link_libraries.html) What I was saying about multi configuration generators is that the check you put only will work if you generate the project in two separate directories, one for release, the other for debug. In MSVC builds, it makes sense sometimes to have only one generated directory with the possibility of release and debug builds.Burletta
Ah ok, I see. Well I definitely used optimized for the tcmalloc library and it ended up in our debug builds. We use makefiles though... so not sure about VSPugilism
M
10

I would like to add a few notes to the previous answers.

If you need to create a list of multiple files you want to link and store that in a cache variable then you need to add the optimized or debug specified before each and every library. This can be especially useful for larger makefiles/projects.

So for example you could do something like this:

set( MyFavLib_LIBRARIES 
    debug debug/module1.lib optimized release/module1.lib
    debug debug/module2.lib optimized release/module2.lib )
target_link_libraries( app ${MyFavLib_LIBRARIES} )
Maki answered 13/1, 2019 at 0:17 Comment(0)
A
3

target_link_libraries with optimize and debug doesn't work for me. I follow the post of Mike Willekes, but release config also import debug library file in visual studio. Then, I use the following cmake code to solving this problem

add_library(BoostLib STATIC IMPORTED)
set_target_properties(BoostLib PROPERTIES 
             IMPORTED_LOCATION_DEBUG ${BoostLibPath}/debug/module1.lib
             IMPORTED_LOCATION_RELEASE ${BoostLibPath}/release/module1.lib)

target_link_libraries(AppTarget BoostLib)
Apricot answered 27/9, 2022 at 5:41 Comment(0)
A
1

What worked for me was to use $(Configuration) macro in a lib path provided to cmake.

So, assuming libs are stored in separate, correctly named folders, e.g.:

C:\boost\lib\Debug\libfoo.lib
C:\boost\lib\Release\libfoo.lib

You can then call cmake with:

cmake -G "Visual Studio 10 2010" -DBOOST_LIBRARYDIR=C:\boost\lib\$(Configuration)\libfoo.lib

That'll generate .vcxproj with Additional Dependencies including C:\boost\lib\$(Configuration)\libfoo.lib, what is evaluated to either C:\boost\lib\Release\libfoo.lib or C:\boost\lib\Debug\libfoo.lib depending on a chosen Configuration.

Aslam answered 12/3, 2019 at 12:28 Comment(0)
R
1

In my case, I had to build the external library like this to have both .lib and d.lib in the same directory:

cmake repo -B build -DCMAKE_DEBUG_POSTFIX=d -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>" -A x64 -T v143
cmake --build build --config Debug
cmake --install build --prefix dist --config Debug

cmake --build build --config Release
cmake --install build --prefix dist --config Release

Then, simple call to link library went fine:

target_link_libraries(MyEXE nowide::nowide)

This page can help selecting the right version of the library depending on your project configuration: https://cmake.org/cmake/help/latest/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.html#prop_tgt:MAP_IMPORTED_CONFIG_%3CCONFIG%3E

Rumsey answered 22/1 at 13:51 Comment(1)
This is the correct way. No one should bother with debug, optimized etc keywords in target_link_libraries.Soot

© 2022 - 2024 — McMap. All rights reserved.