0

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.

user5280911
  • 723
  • 1
  • 8
  • 21
  • Have you read https://cmake.org/cmake/help/latest/module/FindBoost.html ? – arrowd Jul 12 '18 at 10:21
  • @arrowd: Yes, I have. So what? There is no Boost_USE_STATIC_LIBS in Field3D source. – user5280911 Jul 12 '18 at 13:06
  • I read that documentation again. I assume you are thinking I missed this "In this case setting Boost_USE_STATIC_LIBS to OFF may not achieve dynamic linking." But I don't think that sentence helps solve my question because either "may" or "may not" holds, right? If "may" holds, that's what I want -- dynamic linking is achieved and there should be no error. If "may not" holds, dynamic linking is not achieved which means VS should not try to link dynamic library but ONLY tries to link thread component of boost through static library. That way there should be no error either. ... – user5280911 Jul 12 '18 at 14:05
  • ... This is actually my workaround mentioned in the post. What motivates me to post the question is as follows: Visual Studio has nothing to do with Boost or CMake, right? So it should not hide anything that is specified secretly by Boost or CMake, right? So, if VS (or Field3D) wanna link static library file `libboost_thread....lib`, it should appear somewhere in the input library list of VS (Project Properties->Linker->Input->Additional Dependencies), do you agree? But I didn't see that. Only import lib `boost_thread....lib` is there. That is the very reason I ask the question. – user5280911 Jul 12 '18 at 14:11
  • Tried using imported targets or `Boost::disable_autolinking`? – arrowd Jul 12 '18 at 14:24
  • @arrowd: You should forward this question to Field3D developers, not to me, because that's what I am looking for in this opensource. – user5280911 Jul 13 '18 at 06:13

1 Answers1

0

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.

user5280911
  • 723
  • 1
  • 8
  • 21