我有一个项目使用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。
答案 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)