Different Debug and Release library linking with CMAKE
Asked Answered
B

5

25

There was already a Thread which did not help really. I want to be able to link for example Foo.lib for Release Config and Foo_d.lib for Debug Config , how can I achieve this? If I do this:

target_link_libraries(MyEXE debug Foo_d)
target_link_libraries(MyEXE optimized Foo)

then I have both libraries in my project for the debug config? Why is there no Release option? (I am using Visual Studio).

Beery answered 31/3, 2011 at 8:53 Comment(0)
A
22

There is no problems when your library is a part of the project or you're importing it using config mode of find_package command (see documentation and example). In case you can't modify 3rd party so it will produce <package>Config.cmake (it may not use cmake tool or you don't want to do it) the answer is to emulate such process:

add_library(foo STATIC IMPORTED)
set_target_properties(foo PROPERTIES IMPORTED_LOCATION_DEBUG "/path/to/foo-d.lib")
set_target_properties(foo PROPERTIES IMPORTED_LOCATION_RELEASE "/path/to/foo.lib")

target_link_libraries(MyEXE foo)

note that unlike "debug"/"optimized" feature such approach is not limited to Debug/Release configs:

set_target_properties(foo PROPERTIES IMPORTED_LOCATION_MINSIZEREL "/path/to/foo-small.lib")

also you've got some goodies like INTERFACE_INCLUDE_DIRECTORIES:

set_target_properties(foo PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "/path/to/foo/includes")

include_directories("/path/to/foo/includes") # this line not needed
target_link_libraries(MyEXE foo) # this command will add "/path/to/foo/includes" for you

and transitive linking:

add_library(boo STATIC IMPORTED)
set_target_properties(boo PROPERTIES IMPORTED_LOCATION_DEBUG "/path/to/boo-d.lib")
set_target_properties(boo PROPERTIES IMPORTED_LOCATION_RELEASE "/path/to/boo.lib")

add_library(foo STATIC IMPORTED)
set_target_properties(foo PROPERTIES IMPORTED_LOCATION_DEBUG "/path/to/foo-d.lib")
set_target_properties(foo PROPERTIES IMPORTED_LOCATION_RELEASE "/path/to/foo.lib")

set_target_properties(foo PROPERTIES INTERFACE_LINK_LIBRARIES boo) # foo depends on boo

target_link_libraries(MyEXE foo) # boo will be linked automatically

Of course you can use regular cmake commands like find_library and find_package(... MODULE) to estimate locations instead of hardcoding them.

Atthia answered 20/2, 2015 at 12:41 Comment(2)
I'm using CMake 3.20 and if I don't set IMPORTED_LOCATION as a property I get the following warnings CMake Warning (dev) in CMakeLists.txt: Policy CMP0111 is not set: An imported target missing its location property fails during generation. Run "cmake --help-policy CMP0111" for policy details. Use the cmake_policy command to set the policy and suppress this warning. IMPORTED_LOCATION not set for imported target "mytarget::mytarget" configuration "Debug". This warning is for project developers. Use -Wno-dev to suppress it. Eley
Setting IMPORTED_LOCATION based on the mytarget_LIBRARY set using set_library_configurations(mytarget) then it's back to being limited to optimized/debug. It works well for DEBUG and RELEASE configs just not as flexible as it might seem.Eley
H
31

target_link_libraries takes a list, you don't need to call it twice. The following will work:

target_link_libraries(MyEXE debug Foo_d optimized Foo)

And to answer a question asked in the comments of another answer, working with multiple libraries works like so:

target_link_libraries(MyEXE
    debug Foo1_d optimized Foo1
    debug Foo2_d optimized Foo2)

Note that if you also build the library as part of the CMake project, you don't need to specify debug or optimized. CMake will choose the right one for you.

Hau answered 26/2, 2015 at 12:25 Comment(1)
This is the only answer I've seen that calls out debug and optimized have to be done per lib fileCongressional
L
25

The solution is:

SET(LINK_LIBRARY optimized Foo debug Foo_d)
target_link_libraries(MyEXE ${LINK_LIBRARY})
Lunetta answered 31/3, 2011 at 9:0 Comment(2)
I am always looking for solution in pre-made modules. E.g.: in FindQt4.cmake.Lunetta
how will this work if I have multiple debug and release libraries. For example I have Foo1_d,Foo2_d & Foo1,Foo2. How can I club them under single variable? Currently it is only able to detect the keywords for the first associated lib(debug or release) and does not recognize for the nextBargeboard
A
22

There is no problems when your library is a part of the project or you're importing it using config mode of find_package command (see documentation and example). In case you can't modify 3rd party so it will produce <package>Config.cmake (it may not use cmake tool or you don't want to do it) the answer is to emulate such process:

add_library(foo STATIC IMPORTED)
set_target_properties(foo PROPERTIES IMPORTED_LOCATION_DEBUG "/path/to/foo-d.lib")
set_target_properties(foo PROPERTIES IMPORTED_LOCATION_RELEASE "/path/to/foo.lib")

target_link_libraries(MyEXE foo)

note that unlike "debug"/"optimized" feature such approach is not limited to Debug/Release configs:

set_target_properties(foo PROPERTIES IMPORTED_LOCATION_MINSIZEREL "/path/to/foo-small.lib")

also you've got some goodies like INTERFACE_INCLUDE_DIRECTORIES:

set_target_properties(foo PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "/path/to/foo/includes")

include_directories("/path/to/foo/includes") # this line not needed
target_link_libraries(MyEXE foo) # this command will add "/path/to/foo/includes" for you

and transitive linking:

add_library(boo STATIC IMPORTED)
set_target_properties(boo PROPERTIES IMPORTED_LOCATION_DEBUG "/path/to/boo-d.lib")
set_target_properties(boo PROPERTIES IMPORTED_LOCATION_RELEASE "/path/to/boo.lib")

add_library(foo STATIC IMPORTED)
set_target_properties(foo PROPERTIES IMPORTED_LOCATION_DEBUG "/path/to/foo-d.lib")
set_target_properties(foo PROPERTIES IMPORTED_LOCATION_RELEASE "/path/to/foo.lib")

set_target_properties(foo PROPERTIES INTERFACE_LINK_LIBRARIES boo) # foo depends on boo

target_link_libraries(MyEXE foo) # boo will be linked automatically

Of course you can use regular cmake commands like find_library and find_package(... MODULE) to estimate locations instead of hardcoding them.

Atthia answered 20/2, 2015 at 12:41 Comment(2)
I'm using CMake 3.20 and if I don't set IMPORTED_LOCATION as a property I get the following warnings CMake Warning (dev) in CMakeLists.txt: Policy CMP0111 is not set: An imported target missing its location property fails during generation. Run "cmake --help-policy CMP0111" for policy details. Use the cmake_policy command to set the policy and suppress this warning. IMPORTED_LOCATION not set for imported target "mytarget::mytarget" configuration "Debug". This warning is for project developers. Use -Wno-dev to suppress it. Eley
Setting IMPORTED_LOCATION based on the mytarget_LIBRARY set using set_library_configurations(mytarget) then it's back to being limited to optimized/debug. It works well for DEBUG and RELEASE configs just not as flexible as it might seem.Eley
E
8

If you have debug/release libs that follow a certain pattern, like _d on the debug ones, you can avoid repeating yourself with:

set (MY_LIBS
    foo
    bar
    baz
)

# Generate the list of files to link, per flavor.
set (LINK_LIST "")
foreach(x ${MY_LIBS})
    list (APPEND LINK_LIST debug ${x}_d optimized ${x})
endforeach()

target_link_libraries (mytarget
    commonlib1
    commonlib2
    ${LINK_LIST}
    )

This will generate the appropriate

debug foo_d optimized foo
debug bar_d optimized bar

lines that target_link_libraries expects.

Ethicize answered 21/8, 2015 at 0:12 Comment(0)
T
1

The upper answer of using target_link_libraries with debug and optimized param not working for my cmake 3.14.6. If you encounter this bug, try using the following type of code:

set (FreeImage debug "FreeImageD" optimized "FreeImage")
set (Glog debug "glogd" optimized "glog")
set (EXTRA_LIBS ${FreeImage} ${Glog})
target_link_libraries(TexCompressor ${EXTRA_LIBS})

It just change the debug/optimized pair to variable definition. It works for my version.

Tarn answered 24/8, 2020 at 9:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.