73

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

gct
  • 14,100
  • 15
  • 68
  • 107

5 Answers5

103

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)
qz-
  • 674
  • 1
  • 4
  • 14
Mike Willekes
  • 5,960
  • 10
  • 33
  • 33
  • 17
    I do this all the time, even more compactly on one line: target_link_libraries(MyEXE debug 3PDebugLib optimized 3PReleaseLib) – Christopher Bruns Feb 08 '10 at 21:37
  • 16
    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? – Jubei Apr 27 '12 at 04:52
  • 2
    @Jubei Define 2 variables. One for each library. – Qsiris Mar 20 '13 at 17:06
  • 4
    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. – Anton Andreev Dec 25 '13 at 20:26
  • 23
    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. – markand Mar 10 '14 at 15:53
  • 6
    It's adding both the debug *and* release libs when trying the above in my project... – vidstige Aug 12 '14 at 09:12
  • And remember the DEBUG_CONFIGURATIONS property that detects which configurations are debug – Lothar Nov 24 '15 at 05:40
  • @vidstige You have to define this for each library. You can use foreach – brahmin Feb 13 '21 at 18:32
  • Nope. I get a library called debug.lib and optimized.lib – jjxtra Apr 21 '23 at 00:06
18

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} )

# ...
Community
  • 1
  • 1
Tarc
  • 3,214
  • 3
  • 29
  • 41
  • 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()` – Steve Lorimer Nov 02 '16 at 14:58
  • 1
    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. – Tarc Nov 03 '16 at 16:29
  • 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 well – Steve Lorimer Nov 03 '16 at 16:30
  • 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." (https://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. – Tarc Nov 03 '16 at 16:48
  • 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 VS – Steve Lorimer Nov 03 '16 at 16:50
8

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} )
akaltar
  • 1,002
  • 1
  • 19
  • 25
2

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)
Aaron Zhang
  • 111
  • 2
  • 2
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.

Konrad
  • 355
  • 6
  • 18