[CMake] How do I select a different lib based on the configuration of the consuming project?

Michael Hertling mhertling at online.de
Sat Jul 9 09:38:27 EDT 2011


On 07/08/2011 11:57 PM, Benjamin Lindley wrote:
> I made a library named Zik.  I compiled it in both release and debug 
> mode in Visual Studio, then installed it like this:
> 
> Zik
> |--source
> |--build
> +--distribution
>     |--include
>     +--bin
>        +--Visual Studio 10
>           |--Zik.lib      (release version)
>           +--Zik_d.lib    (debug version)
> 
> My question is, how do I edit my Find script so that it selects the 
> right version of the library based on the configuration of the project 
> that wants to use the library?
> 
> Here is my find script so far:
> 
> #################################################################
>    # - Find Zik
>    # Find the Zik includes and library.
>    # Once done this will define
>    #
>    #  Zik_INCLUDE_DIRS    - where to Zik include directory
>    #  Zik_LIBRARIES       - List of libraries when using Zik.
>    #  Zik_FOUND           - True if Zik found.
> 
>    FIND_PATH(Zik_INCLUDE_DIR Zik/Window.h
>        HINTS
>            C:/Users/Cold/Dev/C++/Library/Zik/distribution/include
>    )
> 
>    FIND_LIBRARY(Zik_LIBRARY
>        NAMES
>            ${Zik_NAMES}
>        HINTS
>  
> C:/Users/Cold/Dev/C++/Library/Zik/distribution/bin/${CMAKE_GENERATOR}
>        )
> 
>    SET(Zik_INCLUDE_DIRS ${Zik_INCLUDE_DIR})
>    SET(Zik_LIBRARIES ${Zik_LIBRARY})
> 
>    INCLUDE(FindPackageHandleStandardArgs)
>    FIND_PACKAGE_HANDLE_STANDARD_ARGS(Zik DEFAULT_MESSAGE
>                                      Zik_INCLUDE_DIR Zik_LIBRARY)
> 
>    MARK_AS_ADVANCED(Zik_LIBRARY Zik_INCLUDE_DIR)
> #################################################################

First of all, you should not provide a find module for a package which
is developed by yourself; instead, you should provide a configuration
file ZikConfig.cmake or zik-config.cmake along with your Zik package.
See the Wiki for more information about writing configuration files.

With configuration files, you can use INSTALL(EXPORT ...) to install
files which contain information about your package's binaries w.r.t.
different build types. Look at the following exemplary project:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(F C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
FILE(WRITE ${CMAKE_BINARY_DIR}/f.c "void f(void){}\n")
ADD_LIBRARY(f STATIC f.c)
SET_TARGET_PROPERTIES(f
    PROPERTIES
    OUTPUT_NAME_RELEASE f
    OUTPUT_NAME_DEBUG f_d)
INSTALL(TARGETS f EXPORT f ARCHIVE DESTINATION ${CMAKE_BINARY_DIR}/lib)
INSTALL(EXPORT f DESTINATION ${CMAKE_BINARY_DIR})

After configuring/building/installing with build type "release", there
are f.cmake and f-release.cmake; the former contains a declaration for
the library as imported target, and the latter contains the associated
IMPORTED_LOCATION_RELEASE property. Re-configuring/building/installing
with build type "debug" adds f-debug.cmake with the IMPORTED_LOCATION_
DEBUG property. Both f-*.cmake files are included by f.cmake, and if
this file is, in turn, included in the package's configuration file,
other projects which issue FIND_PACKAGE(f ...) will learn about the f
package's binaries and their different locations due to the different
build types, i.e.

PROJECT(XYZ ...)
FIND_PACKAGE(f ...)
ADD_EXECUTABLE(xyz ...)
TARGET_LINK_LIBRARIES(xyz ... f ...)

will make the xyz executable link against libf.a if XYZ's build type is
"release", and against libf_d.a if the build type is "debug". Usually,
this usage of imported targets in connection with INSTALL(EXPORT ...)
and configuration files is the preferable solution to your concern.

'hope that helps.

Regards,

Michael


More information about the CMake mailing list