In our environment we have multiple different compiler versions which makes using a single static library build of ixwebsockets.lib difficult. As a result, I switched to creating a shared library (dll) with the CMake option -DBUILD_SHARED_LIBS=ON. The compilation works fine, but when trying to link the dll into our client application, there are multiple unresolved external symbols:
1>Generating Code...
1>WebSocketClient.obj : error LNK2019: unresolved external symbol "public: static unsigned short const ix::WebSocketCloseConstants::kNormalClosureCode" (?kNormalClosureCode@WebSocketCloseConstants@ix@@2GB) referenced in function "public: virtual __cdecl CWebSocketClient::~CWebSocketClient(void)" (??1CWebSocketClient@@UEAA@XZ)
1>WebSocketClient.obj : error LNK2019: unresolved external symbol "public: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ix::WebSocketCloseConstants::kNormalClosureMessage" (?kNormalClosureMessage@WebSocketCloseConstants@ix@@2V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@B) referenced in function "public: virtual __cdecl CWebSocketClient::~CWebSocketClient(void)" (??1CWebSocketClient@@UEAA@XZ)
1>WebSocketServer.obj : error LNK2019: unresolved external symbol "public: static int const ix::SocketServer::kDefaultTcpBacklog" (?kDefaultTcpBacklog@SocketServer@ix@@2HB) referenced in function "public: static class ix::WebSocketServer * __cdecl pilot::Alloc<class ix::WebSocketServer>::construct<int,char const *>(int,char const *)" (??$construct@HPEBD@?$Alloc@VWebSocketServer@ix@@@pilot@@SAPEAVWebSocketServer@ix@@HPEBD@Z)
1>WebSocketServer.obj : error LNK2019: unresolved external symbol "public: static unsigned __int64 const ix::SocketServer::kDefaultMaxConnections" (?kDefaultMaxConnections@SocketServer@ix@@2_KB) referenced in function "public: static class ix::WebSocketServer * __cdecl pilot::Alloc<class ix::WebSocketServer>::construct<int,char const *>(int,char const *)" (??$construct@HPEBD@?$Alloc@VWebSocketServer@ix@@@pilot@@SAPEAVWebSocketServer@ix@@HPEBD@Z)
1>WebSocketServer.obj : error LNK2019: unresolved external symbol "public: static int const ix::SocketServer::kDefaultAddressFamily" (?kDefaultAddressFamily@SocketServer@ix@@2HB) referenced in function "public: static class ix::WebSocketServer * __cdecl pilot::Alloc<class ix::WebSocketServer>::construct<int,char const *>(int,char const *)" (??$construct@HPEBD@?$Alloc@VWebSocketServer@ix@@@pilot@@SAPEAVWebSocketServer@ix@@HPEBD@Z)
1>WebSocketServer.obj : error LNK2019: unresolved external symbol "public: static int const ix::WebSocketServer::kDefaultHandShakeTimeoutSecs" (?kDefaultHandShakeTimeoutSecs@WebSocketServer@ix@@2HB) referenced in function "public: static class ix::WebSocketServer * __cdecl pilot::Alloc<class ix::WebSocketServer>::construct<int,char const *>(int,char const *)" (??$construct@HPEBD@?$Alloc@VWebSocketServer@ix@@@pilot@@SAPEAVWebSocketServer@ix@@HPEBD@Z)
1>WebSocketServer.obj : error LNK2019: unresolved external symbol "private: static int const ix::WebSocketServer::kPingIntervalSeconds" (?kPingIntervalSeconds@WebSocketServer@ix@@0HB) referenced in function "public: static class ix::WebSocketServer * __cdecl pilot::Alloc<class ix::WebSocketServer>::construct<int,char const *>(int,char const *)" (??$construct@HPEBD@?$Alloc@VWebSocketServer@ix@@@pilot@@SAPEAVWebSocketServer@ix@@HPEBD@Z)
1>WebSocketServer.obj : error LNK2019: unresolved external symbol "private: static int const ix::WebSocketServer::kSendTimeoutSeconds" (?kSendTimeoutSeconds@WebSocketServer@ix@@0HB) referenced in function "public: static class ix::WebSocketServer * __cdecl pilot::Alloc<class ix::WebSocketServer>::construct<int,char const *>(int,char const *)" (??$construct@HPEBD@?$Alloc@VWebSocketServer@ix@@@pilot@@SAPEAVWebSocketServer@ix@@HPEBD@Z)
1>E:\dev\git\plp-platform-pc_c\scitegic_root\src\..\bin\cloudproxy.exe : fatal error LNK1120: 8 unresolved externals
In each case, the problem stems from use of a static const member in three classes (structs):
struct WebSocketCloseConstants (IXWebSocketCloseConstants.h)
class WebSocketServer (IXWebSocketServer.h)
class SocketServer (IXSocketServer.h)
On Windows, dll exports are kind of wonky and although CMakeLists.txt specifies
if(MSVC)
# Workaround for some projects
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
This still has problems with some items as described in https://www.kitware.com/create-dlls-on-windows-without-declspec-using-new-cmake-export-all-feature/ (see the section "Real World Use Cases"):
After adding this feature to CMake, I tried it on two relatively large software projects VXL ( (http://vxl.sourceforge.net/) and ITK (www.itk.org). Although, it did take some time, it was much easier than adding dll markup to every source file. In the end the changes required fell into the following repeated issues and fixes:
Handling class static data members
Add dll import/export macros to the static data.
Eliminate the static data –
This can be done by making a static getter function with a local static variable.
Static const members
These are not exported by the new feature. In some cases to support older compilers, these are put in .cxx files and compiled into the library and are not just inlined in the .h files. If you have this case, you will need to use dllimport and dllexport markup and not just dllimport mark up as the auto export will not work.
In our environment we have multiple different compiler versions which makes using a single static library build of ixwebsockets.lib difficult. As a result, I switched to creating a shared library (dll) with the CMake option
-DBUILD_SHARED_LIBS=ON. The compilation works fine, but when trying to link the dll into our client application, there are multiple unresolved external symbols:In each case, the problem stems from use of a static const member in three classes (structs):
struct WebSocketCloseConstants(IXWebSocketCloseConstants.h)class WebSocketServer(IXWebSocketServer.h)class SocketServer(IXSocketServer.h)On Windows, dll exports are kind of wonky and although CMakeLists.txt specifies
This still has problems with some items as described in https://www.kitware.com/create-dlls-on-windows-without-declspec-using-new-cmake-export-all-feature/ (see the section "Real World Use Cases"):