Search code examples
boostbuildcmakestatic-librariesstatic-linking

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


I am building Field3D which links to Boost's thread library. The building environment is listed as follows:

The CMake command line to set up VS2015 is:

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\1.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" ..

Then I open the generated field3d.sln in VS2015 and try to build Field3D project. Errors are reported as below:

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:\...\3rd-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 ==========

The cause of these errors, as far as I can see, is that the line 46 of Field3D's CMakeLists.txt

FIND_PACKAGE (Boost COMPONENTS regex thread)

specifies linking boost's thread component, which in turn leads to linking import library C:\local\boost_1_67_0\lib64-msvc-14.0\boost_thread-vc140-mt-x64-1_67.lib, as can be checked in Project Properties -> Linker -> Input -> Additional Dependencies in VS. But somehow Field3D insists on additionally linking to the static library of Boost's thread component which is libboost_thread-vc140-mt-x64-1_67.lib (you can see it in the error messages), thus causing name conflicts. If I temporarily remove "thread" from the FIND_PACKAGE's COMPONENTS list to let Field3D link to the static library as it insists, the Field3D project can build correctly.

Because I wanna build Field3D based on the dynamic DLL of Boost library, my question is: Why does Field3D insist on linking to the static boost library "libboost_thread-vc140-mt-x64-1_67.lib"? Where is this rule introduced? How to suppress linking static thread library of Boost? I have checked CMakeLists.txt, and variables like Boost_LIBRARY_DIRS, Boost_LIBRARIES and Field3D_BIN_Libraries therein but they do not contain static library filename libboost_thread-vc140-mt-x64-1_67.lib. I know that #pragma comment (linker, ...) can also require linking to some user-defined library, but there is no such directive in Field3D source package whatsoever. So I am at my wit's end and post this question here in hope that someone can help me figure out where on earth the linking postulation to the static library of Boost's thread component comes from. Some minor modification may be needed to reproduce the issue but I think the information provided above should cover most of the build for a veteran. If you need any other info to troubleshoot this problem please let me know. Thank you.


Solution

  • After another bunch of hours to check Field3D's building process, I believe the problem is Field3D's failure to make use of Boost's mechanism to disable automatic linking and to enable dynamic linking on Windows. An issue ticket is submitted in hope that the developers of Field3D can fix it in future: https://github.com/imageworks/Field3D/issues/96. Briefly, add the following two commands to copy INTERFACE_COMPILE_DEFINITIONS property of Boost::disable_autolinking and Boost::dynamic_linking import targets to Field3D project

    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> )
    

    after line 189 of CMakeLists.txt.

    Please point out if I have made any mistake.