Directing cmake to link against shared object with

2019-05-30 15:48发布

I've got a cmake project that pretty much looks like this:

cmake_minimum_required(VERSION 3.0)

SET(CMAKE_DEBUG_POSTFIX "_d")

include_directories(../TransfunctionerProject)
include_directories(../TransmogrifierProject)

set(Libraries
    ContinuumTransfunctioner
    Transmogrifier
)

set(SourceFiles
    Wrapper.cpp
    Logger.cpp
)

add_library(Frobnigator SHARED ${SourceFiles})
add_library(FrobnigatorStatic STATIC ${SourceFiles})
set_target_properties(FrobnigatorStatic PROPERTIES OUTPUT_NAME Frobnigator)
target_link_libraries(Frobnigator ${Libraries})

Where ContinuumTransfunctioner and Transmogrifier projects include the debug postfix directive SET(CMAKE_DEBUG_POSTFIX "_d") so that libContinuumTransfunctioner_d.so and libTransmogrifier_d.so both exist.

The problem is that the current project appears to be linking against the static library without the _d suffix and complains:

/usr/bin/ld: cannot find -lContinuumTransfunctioner

标签: cmake
2条回答
乱世女痞
2楼-- · 2019-05-30 16:42

The Libraries that you pass into the target_link_libraries call are interpreted as filenames, not as target names.

This is the unfortunate fallback for that call in CMake: If you pass a random string to it, that cannot be interpreted in a meaningful way, CMake will always assume it to be plain library name. Sometimes this is just what you want, but the name has to be an exact match for an existing library. The whole debug postfix magic will be lost here.

What you might have wanted to do was to pass a library target name instead. This will trigger a much smarter handling of the dependency and would solve your problem. However, that only works if the library is a known target in the context of the target_link_libraries call. You can easily check this as follows:

if(TARGET ContinuumTransfunctioner)
    message("Library target name")
else()
    message("Plain library name")
endif()
target_link_libraries(Frobnigator ContinuumTransfunctioner)

So how do you get to the target name case? This depends on how your build is structured. If the library is being built as part of your CMake run, simply make sure that the corresponding add_library call is performed from a subdirectory that is pulled in via add_subdirectory from the file that performs the target_link_libraries call.

If the library in question is an external dependency, you need to build an imported target that carries all the relevant information where to find the library files (including any potential debug postfixes). This can be a bit cumbersome to do manually, so if you can, you might want to use CMake's packaging mechanism to generate this automatically as part of the library's build process.

查看更多
Evening l夕情丶
3楼-- · 2019-05-30 16:44

Here's the solution, courtesy of the good people on the cmake mailing list:

# Note:
#    $<$<CONFIG:Debug>:_d> is called a generator expression.
#    It outputs _d if the build is debug.
#
set(Libraries
    ContinuumTransfunctioner$<$<CONFIG:Debug>:_d>
    Transmogrifier$<$<CONFIG:Debug>:_d>
)
查看更多
登录 后发表回答