Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Missing BOOST_ALL_NO_LIB and BOOST_ALL_DYN_LINK on Windows, causing automatic linking and duplicated symbols #96

Open
ghost opened this issue Jul 13, 2018 · 3 comments

Comments

@ghost
Copy link

ghost commented Jul 13, 2018

My environment:

  • Windows 10
  • Visual Studio 2015 Update 3
  • CMake 3.11.4
  • master branch of Field3D downloaded from here
  • Release x64 DLL mode in VS

According to documentation of CMake's FindBoost module, automatic linking is default on Windows on which Boost_USE_STATIC_LIBS sometimes does not take effect, e.g., for thread component. In this case, Field3D would attempt to link static library libboost_thread-vc140-mt-x64-1_67.lib of Boost's thread component. But at the same time, line 46 of CMakeLists.txt
FIND_PACKAGE (Boost COMPONENTS regex thread)
tries to direct the generated VS project to link import library of the dynamic DLL boost_thread-vc140-mt-x64-1_67.lib. Since both static and dynamic library files contain the same symbols, errors like below would result when building Field3D project:

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 is that Field3D fails to disable the automatic linking in Boost. On the other hand, Boost provides mechanism for users to disable automatic linking and to link dynamic Boost libraries only. CMake also exposes the mechanism. But unfortunately, Field3D fails to use it and therefore leads to the above building errors on Windows.

Boost introduces Boost::disable_autolinking and Boost::dynamic_linking import targets. CMake adds BOOST_ALL_NO_LIB and BOOST_ALL_DYN_LINK preprocessor definitions into the INTERFACE_COMPILE_DEFINITIONS property of them, respectively; see line 1166 to 1169 of FindBoost.cmake. As a result, I request Field3D could make use of them to avoid automatic linking and to link dynamic libraries. To this end, we need to copy them to the COMPILE_DEFINITIONS property of the Field3D target. This can be done using the following CMake command with the aid of generator expressions:

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

Because line 191 resets the COMPILE_DEFINITIONS property, the above two lines should be placed after it, i.e., line 192-193 of CMakeLists.txt.

Please kindly point out any mistake I have made. If no mistake, I I hope Field3D can be modified as explained above to improve its portability on Windows. Thanks.

@magnusw
Copy link
Collaborator

magnusw commented Jul 15, 2018 via email

@ghost
Copy link
Author

ghost commented Jul 15, 2018

Sure, I'd be glad to do it, together with some other issues on Windows.

@magnusw
Copy link
Collaborator

magnusw commented Jul 15, 2018 via email

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant