Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find RelWithDebInfo or MinSizeRel libraries with CMake?

Tags:

cmake

I'm trying to link my project to a external library that I also developed in which also also use CMake to build. When I try to find RelWithDebInfo or MinSizeRel like this:

FIND_LIBRARY(PCM_LIBRARY_DEBUG pcm
    PATHS   @CMAKE_LIBRARY_OUTPUT_DIRECTORY@
            @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/Debug
    NO_DEFAULT_PATH
)
FIND_LIBRARY(PCM_LIBRARY_RELEASE pcm
    PATHS   @CMAKE_LIBRARY_OUTPUT_DIRECTORY@
            @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/Release
            @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/MinSizeRel
            @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/RelWithDebInfo
    NO_DEFAULT_PATH
)

SET(PCM_LIBRARIES debug ${PCM_LIBRARY_DEBUG} optimized ${PCM_LIBRARY_RELEASE})

It does not search in ather directories that are not Release or Debug. I also tried creating PCM_LIBRARY_RELWITHDEBINFO and PCM_LIBRARY_MINSIZEREL but the same thing happens because there is only debug and optimized prefixes in SET. Anyone knows how can I link the correct libraries?

like image 986
Luis Avatar asked Jan 31 '14 11:01

Luis


1 Answers

This is unfortunately one of the shortcomings of using find_library. There is no easy way around this without introducing tons of boilerplate code.

The problem here is that when passing files as dependencies to target_link_libraries, you can only distinguish between debug and optimized. If you need more fine-grained control, you will have to manipulate the respective target properties like LINK_INTERFACE_LIBRARIES directly. This is not only quite cumbersome, it also requires detailed knowledge about the inner workings of CMake's property system.

Fortunately, there is another way: The aforementioned limitation only applies when specifying dependencies via filenames. When specifying them as targets, this problem does not occur. The most obvious example is if a library and the executable that depends on it are built from the same source:

add_library(foo_lib some_files.cpp)
add_executable(bar_exe more_files.cpp)

target_link_libraries(bar_exe PUBLIC foo_lib)

This 'just works'. The correct library will be chosen for each build configuration. Things get a little more complicated if the library and the executable live in different independent projects. In that case the library has to provide a configure file with an exported target in addition to the binary files.

Instead of calling find_library to locate the binaries, the dependent executable now just loads that config file and can then use the imported target as if it was a target from the same project.

Many modern libraries already use this approach instead of the classical find_library technique (Qt5 is a prominent example). So if you are at liberty to change the CMakeLists of your dependency and you do not need to support very old CMake versions (<2.6), this is probably the way to go.

like image 151
ComicSansMS Avatar answered Nov 01 '22 14:11

ComicSansMS