CMake:Visual Studio构建查找错误的库

时间:2015-08-27 14:23:38

标签: c++ visual-studio-2010 boost cmake

我有一个项目使用CMake在Linux和Windows平台上执行构建。该项目的一些组件需要一些Boost库。许多组件都构建为共享库(.dll / .so)。当我安装Boost时,我选择构建共享库。

问题在于:

在Windows上运行CMake后,打开生成并运行构建的VS解决方案,依赖于Boost的组件失败,并显示无法找到库的错误。例如:

LINK : fatal error LNK1104: cannot open file 'libboost_thread-vc100-mt-gd-1_58.lib'

果然,Boost lib目录中没有该名称的文件。该库的共享库文件:boost_thread-vc100-mt-gd-1_58.dll(和.lib)。

我假设“lib ...”变体代表一个静态库。当我指定使用来自Boost的静态库时,为什么要查找? Linux方面似乎没有问题。

以下是我的CMakeLists.txt文件的一些摘录:

项目级别:

...
# Set to use shared libraries from Boost.
set(Boost_USE_STATIC_LIBS OFF)
#set(Boost_USE_STATIC_RUNTIME OFF)   <- I also tried with this uncommented - no difference
#set(Boost_DEBUG ON)

if(WIN32)
  find_package(Boost 1.58 REQUIRED system thread date_time chrono)
elseif(UNIX)
  find_package(Boost 1.58 REQUIRED)
endif()

include_directories(${Boost_INCLUDE_DIRS})
...

需要提升的组件:

set(source_files
  ...)

# Create library from source files.
add_library(lib_target SHARED ${source_files})

target_link_libraries(lib_target ${Boost_LIBRARIES})

看起来其他人有同样(或类似)的问题: cmake can't find boost libraries because it looks for the wrong file names。我用link=shared构建了我的Boost。

1 个答案:

答案 0 :(得分:3)

问题是Boost使用link.exe的自动链接功能以及为了在静态和动态链接之间进行选择的事实,您需要设置一些预处理器定义。也就是说,除非您禁用自动链接或定义-DBOOST_ALL_DYN_LINK(或各种-DBOOST_<WHATEVER>_DYN_LINK预处理器定义),否则标头仍会尝试引入静态库。)

要禁用boost标头的自动链接,请设置预处理器定义-DBOOST_ALL_NO_LIB。由于CMake已经在寻找库和设置标志,因此自动链接对CMake来说确实不是很有用。但是,您不必禁用它以使动态链接起作用。

如果要使用动态链接,请将Boost_USE_STATIC_LIBS设置为OFF并添加预处理器定义-DBOOST_ALL_DYN_LINK-DBOOST_ALL_DYN_LINK将对boost头中的声明启用__declspec(dllimport),并使自动链接功能(如果启用)依赖于dll而不是静态库。

请注意,某些boost库不提供静态和动态链接之间的选择,不会受-DBOOST_ALL_DYN_LINK的影响。我没有尝试过,所以我不知道CMake FindBoost模块是否处理这个问题。

如果您想使用静态链接,请将Boost_USE_STATIC_LIBS设置为ON。默认情况下,Boost标头使用静态链接,因此如果您想要静态链接,是否启用自动链接并不重要。

如果您想查看Boost的自动链接要求的库,请设置预处理器定义-DBOOST_LIB_DIAGNOSTIC或使用FindBoost模块的${Boost_LIB_DIAGNOSTIC_DEFINITIONS}"。这将导致标题输出处理它们时所要求的库的名称。

示例CMakeLists.txt片段:

set(Boost_USE_STATIC_LIBS OFF)
find_package(Boost 1.58 REQUIRED system thread date_time chrono)

set(source_files ...)
add_library(lib_target SHARED ${source_files})

target_compile_definitions(lib_target PRIVATE -DBOOST_ALL_NO_LIB -DBOOST_ALL_DYN_LINK)

target_include_directories(lib_target PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(lib_target PRIVATE ${Boost_LIBRARIES})

这是一个更新的示例,它仅使用目标而不是设置定义和包含目录:

find_package(Boost 1.67 REQUIRED system thread date_time chrono)

set(source_files ...)
add_library(lib_target SHARED ${source_files})

target_link_libraries(lib_target PRIVATE
    Boost::disable_autolinking
    Boost::dynamic_linking
    Boost::boost Boost::system Boost::thread Boost::date_time Boost::chrono)