From 2e20bfb7960dcc31dddb7ba24458b7e3729333a8 Mon Sep 17 00:00:00 2001 From: hayati ayguen Date: Fri, 4 May 2018 00:08:30 +0200 Subject: [PATCH] compiler/linker options for build with mingw and msvc * mingw is missing inet_pton() function. - added replacement implementation - switched on with cmake option CLSOCKET_OWN_INET_PTON * msvc: static build against c runtime with cmake CLSOCKET_SHARED off * build examples with msvc - except clsocket-example requiring pthread Signed-off-by: hayati ayguen --- CMakeLists.txt | 36 +++++++-- src/PassiveSocket.cpp | 5 +- src/SimpleSocket.cpp | 174 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6588b4..fd8103f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,10 +44,16 @@ elseif(WIN32) SET(PROJECT_LIBS Ws2_32.lib) if(MINGW) # Special MINGW stuff here + OPTION(CLSOCKET_OWN_INET_PTON "Use own inet_pton() implementation (required on MINGW)" ON) + if(CLSOCKET_OWN_INET_PTON) + add_definitions(-DCLSOCKET_OWN_INET_PTON) + endif() # see https://cmake.org/pipermail/cmake/2012-September/051970.html # see http://stackoverflow.com/questions/13768515/how-to-do-static-linking-of-libwinpthread-1-dll-in-mingw - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static -static-libgcc") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static -static-libgcc -static-libstdc++") + # looks, the following compiler options produce linker errors. -static, .. options should only be used for linker + #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static -static-libgcc") + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static -static-libgcc -static-libstdc++") + # commenting out upper two CMAKE_C[XX]_FLAG now compiles and links with and without CLSOCKET_SHARED cmake option set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -static -static-libgcc -s") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS} -static -static-libgcc -static-libstdc++ -s") elseif(MSVC) @@ -75,6 +81,18 @@ else() else() ADD_LIBRARY(clsocket STATIC ${CLSOCKET_SOURCES}) endif() + + if(MSVC) + # Special MSVC stuff here + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -MT") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -MT") + set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -MT") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -MT") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -MT") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -MT") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -MTd") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -MTd") + endif() endif() TARGET_LINK_LIBRARIES(clsocket ${PROJECT_LIBS}) @@ -89,14 +107,18 @@ endif() set_target_properties(clsocket PROPERTIES VERSION ${BUILD_VERSION} SOVERSION ${BUILD_MAJOR}) -if(UNIX OR (WIN32 AND MINGW)) +if(UNIX OR (WIN32 OR MINGW)) OPTION(CLSOCKET_EXAMPLES "Build the examples" OFF) if(CLSOCKET_EXAMPLES) - ADD_EXECUTABLE(clsocket-example examples/RecvAsync.cpp) - TARGET_LINK_LIBRARIES(clsocket-example clsocket pthread) - if(NOT CLSOCKET_DEP_ONLY) - install(TARGETS clsocket-example DESTINATION bin) + + if (NOT MSVC) + # pthread not available with MSVC + ADD_EXECUTABLE(clsocket-example examples/RecvAsync.cpp) + TARGET_LINK_LIBRARIES(clsocket-example clsocket pthread) + if(NOT CLSOCKET_DEP_ONLY) + install(TARGETS clsocket-example DESTINATION bin) + endif() endif() ADD_EXECUTABLE(querydaytime-example examples/QueryDayTime.cpp) diff --git a/src/PassiveSocket.cpp b/src/PassiveSocket.cpp index 4806b1a..ab36819 100644 --- a/src/PassiveSocket.cpp +++ b/src/PassiveSocket.cpp @@ -42,7 +42,10 @@ *----------------------------------------------------------------------------*/ #include "PassiveSocket.h" - +#ifdef CLSOCKET_OWN_INET_PTON +// implemented in SimpleSocket.cpp +extern int inet_pton(int af, const char *src, void *dst); +#endif CPassiveSocket::CPassiveSocket(CSocketType nType) : CSimpleSocket(nType) { diff --git a/src/SimpleSocket.cpp b/src/SimpleSocket.cpp index 80d9ad7..9624b33 100644 --- a/src/SimpleSocket.cpp +++ b/src/SimpleSocket.cpp @@ -48,6 +48,10 @@ #include #include +#ifdef CLSOCKET_OWN_INET_PTON +#include +#endif + #ifdef _MSC_VER #pragma warning( disable : 4996 ) #define snprintf _snprintf @@ -71,6 +75,176 @@ static void CoreDump() #endif +#ifdef CLSOCKET_OWN_INET_PTON +// source from +// https://stackoverflow.com/questions/15370033/how-to-use-inet-pton-with-the-mingw-compiler +// Author: Paul Vixie, 1996. +// added "static" for inet_pton4() and inet_pton6() + +#define NS_INADDRSZ 4 +#define NS_IN6ADDRSZ 16 +#define NS_INT16SZ 2 + +static +int inet_pton4(const char *src, char *dst) +{ + uint8_t tmp[NS_INADDRSZ], *tp; + + int saw_digit = 0; + int octets = 0; + *(tp = tmp) = 0; + + int ch; + while ((ch = *src++) != '\0') + { + if (ch >= '0' && ch <= '9') + { + uint32_t n = *tp * 10 + (ch - '0'); + + if (saw_digit && *tp == 0) + return 0; + + if (n > 255) + return 0; + + *tp = n; + if (!saw_digit) + { + if (++octets > 4) + return 0; + saw_digit = 1; + } + } + else if (ch == '.' && saw_digit) + { + if (octets == 4) + return 0; + *++tp = 0; + saw_digit = 0; + } + else + return 0; + } + if (octets < 4) + return 0; + + memcpy(dst, tmp, NS_INADDRSZ); + + return 1; +} + +static +int inet_pton6(const char *src, char *dst) +{ + static const char xdigits[] = "0123456789abcdef"; + uint8_t tmp[NS_IN6ADDRSZ]; + + uint8_t *tp = (uint8_t*) memset(tmp, '\0', NS_IN6ADDRSZ); + uint8_t *endp = tp + NS_IN6ADDRSZ; + uint8_t *colonp = NULL; + + /* Leading :: requires some special handling. */ + if (*src == ':') + { + if (*++src != ':') + return 0; + } + + const char *curtok = src; + int saw_xdigit = 0; + uint32_t val = 0; + int ch; + while ((ch = tolower(*src++)) != '\0') + { + const char *pch = strchr(xdigits, ch); + if (pch != NULL) + { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return 0; + saw_xdigit = 1; + continue; + } + if (ch == ':') + { + curtok = src; + if (!saw_xdigit) + { + if (colonp) + return 0; + colonp = tp; + continue; + } + else if (*src == '\0') + { + return 0; + } + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, (char*) tp) > 0) + { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return 0; + } + if (saw_xdigit) + { + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + } + if (colonp != NULL) + { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + + if (tp == endp) + return 0; + + for (int i = 1; i <= n; i++) + { + endp[-i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return 0; + + memcpy(dst, tmp, NS_IN6ADDRSZ); + + return 1; +} + +int inet_pton(int af, const char *src, void *dst) +{ + switch (af) + { + case AF_INET: + return inet_pton4(src, (char*)dst); + case AF_INET6: + return inet_pton6(src, (char*)dst); + default: + return -1; + } +} + +#endif + CSimpleSocket::CSimpleSocket(CSocketType nType) : m_socket(INVALID_SOCKET),