如何确定在构建 Field3D 时假定链接到 Boost 线程组件静态库的位置?

How to figure out where linking to static library of Boost's thread component is postulated when building Field3D?

我正在构建 Field3D link 到 Boost 的线程库。搭建环境罗列如下:

设置VS2015的CMake命令行是:

cmake -DCMAKE_CONFIGURATION_TYPES=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=C:...\Field3D-master\install -DDOXYGEN_EXECUTABLE="C:\Program Files\doxygen\bin\doxygen.exe" -DHDF5_ROOT="C:\Program Files\HDF_Group\HDF5.10.2" -DBOOST_ROOT=C:\local\boost_1_67_0 -DBOOST_INCLUDEDIR=C:\local\boost_1_67_0\boost -DBOOST_LIBRARYDIR=C:\local\boost_1_67_0\lib64-msvc-14.0 -DIlmbase_Base_Dir=C:...\openexr-develop\IlmBase\install_ -G"Visual Studio 14 2015 Win64" ..

然后我在VS2015中打开生成的field3d.sln并尝试构建Field3D项目。报错如下:

1>------ Build started: Project: Field3D, Configuration: Release x64 ------
1>libboost_thread-vc140-mt-x64-1_67.lib(thread.obj) : error LNK2005: "public: virtual __cdecl boost::detail::thread_data_base::~thread_data_base(void)" (??1thread_data_base@detail@boost@@UEAA@XZ) already defined in boost_thread-vc140-mt-x64-1_67.lib(boost_thread-vc140-mt-x64-1_67.dll)
1>libboost_thread-vc140-mt-x64-1_67.lib(thread.obj) : error LNK2005: "public: void __cdecl boost::thread::detach(void)" (?detach@thread@boost@@QEAAXXZ) already defined in boost_thread-vc140-mt-x64-1_67.lib(boost_thread-vc140-mt-x64-1_67.dll)
1>libboost_thread-vc140-mt-x64-1_67.lib(thread.obj) : error LNK2005: "class boost::thread::id __cdecl boost::this_thread::get_id(void)" (?get_id@this_thread@boost@@YA?AVid@thread@2@XZ) already defined in boost_thread-vc140-mt-x64-1_67.lib(boost_thread-vc140-mt-x64-1_67.dll)
1>libboost_thread-vc140-mt-x64-1_67.lib(thread.obj) : error LNK2005: "public: class boost::thread::id __cdecl boost::thread::get_id(void)const " (?get_id@thread@boost@@QEBA?AVid@12@XZ) already defined in boost_thread-vc140-mt-x64-1_67.lib(boost_thread-vc140-mt-x64-1_67.dll)
1>libboost_thread-vc140-mt-x64-1_67.lib(thread.obj) : error LNK2005: "bool __cdecl boost::this_thread::interruptible_wait(void *,struct boost::detail::mono_platform_timepoint const &)" (?interruptible_wait@this_thread@boost@@YA_NPEAXAEBUmono_platform_timepoint@detail@2@@Z) already defined in boost_thread-vc140-mt-x64-1_67.lib(boost_thread-vc140-mt-x64-1_67.dll)
1>libboost_thread-vc140-mt-x64-1_67.lib(thread.obj) : error LNK2005: "private: bool __cdecl boost::thread::join_noexcept(void)" (?join_noexcept@thread@boost@@AEAA_NXZ) already defined in boost_thread-vc140-mt-x64-1_67.lib(boost_thread-vc140-mt-x64-1_67.dll)
1>libboost_thread-vc140-mt-x64-1_67.lib(thread.obj) : error LNK2005: "public: bool __cdecl boost::thread::joinable(void)const " (?joinable@thread@boost@@QEBA_NXZ) already defined in boost_thread-vc140-mt-x64-1_67.lib(boost_thread-vc140-mt-x64-1_67.dll)
1>libboost_thread-vc140-mt-x64-1_67.lib(thread.obj) : error LNK2005: "private: bool __cdecl boost::thread::start_thread_noexcept(void)" (?start_thread_noexcept@thread@boost@@AEAA_NXZ) already defined in boost_thread-vc140-mt-x64-1_67.lib(boost_thread-vc140-mt-x64-1_67.dll)
1>     Creating library C:/.../Field3D-master/build/Release/Field3D.lib and object C:/.../Field3D-master/build/Release/Field3D.exp
1>C:\...rd-parties\Field3D-master\build\Release\Field3D.dll : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========

据我所知,造成这些错误的原因是 Field3D 的第 46 行 CMakeLists.txt

FIND_PACKAGE (Boost COMPONENTS regex thread)

指定linking boost的线程组件,这反过来导致[=​​62=]ing导入库C:\local\boost_1_67_0\lib64-msvc-14.0\boost_thread-vc140-mt-x64-1_67.lib,可以在项目属性->链接器->输入->中检查VS 中的附加依赖项。但不知何故,Field3D 坚持额外 linking 到 Boost 线程组件的静态库,即 libboost_thread-vc140-mt-x64-1_67.lib(您可以在错误消息中看到它),从而导致名称冲突。如果我暂时从 FIND_PACKAGE 的 COMPONENTS 列表中删除 "thread" 以使 Field3D link 坚持到静态库,则 Field3D 项目可以正确构建。

因为我想基于Boost库的动态DLL构建Field3D,我的问题是:为什么Field3D坚持要linking到静态boost库"libboost_thread-vc140-mt-x64-1_67.lib"?这个规则是在哪里引入的?如何抑制linking Boost 的静态线程库?我已经检查了 CMakeLists.txt,以及 Boost_LIBRARY_DIRSBoost_LIBRARIESField3D_BIN_Libraries 等变量,但它们不包含静态库文件名 libboost_thread-vc140-mt-x64-1_67.lib。我知道 #pragma comment (linker, ...) 也可以要求 linking 某些用户定义的库,但是 Field3D 源包中没有这样的指令。所以我无计可施 post 这个问题是希望有人能帮我弄清楚 Boost 线程组件静态库的 linking postulation 到底来自哪里从。可能需要进行一些小的修改才能重现该问题,但我认为上面提供的信息应该涵盖老手的大部分构建内容。如果您需要任何其他信息来解决此问题,请告诉我。谢谢。

又花了几个小时检查 Field3D 的构建过程,我认为问题是 Field3D 未能利用 Boost 的机制禁用自动链接并启用 Windows 上的动态链接。已提交问题单,希望Field3D的开发者能在未来修复它:https://github.com/imageworks/Field3D/issues/96。简而言之,添加以下两个命令将 INTERFACE_COMPILE_DEFINITIONS 属性 的 Boost::disable_autolinkingBoost::dynamic_linking 导入目标复制到 Field3D 项目

TARGET_COMPILE_DEFINITIONS( Field3D PRIVATE $<TARGET_PROPERTY:Boost::disable_autolinking,INTERFACE_COMPILE_DEFINITIONS> )
TARGET_COMPILE_DEFINITIONS( Field3D PRIVATE $<TARGET_PROPERTY:Boost::dynamic_linking,INTERFACE_COMPILE_DEFINITIONS> )

在 CMakeLists.txt 的第 189 行之后。

如有错误请指出