[ovs-dev] [PATCH RFC]: windows: cross-compile using mingw-w64 gcc.

William Tu u9012063 at gmail.com
Tue Feb 11 19:13:35 UTC 2020


Currently we use MSVC to compile OVS on Windows. The patch tries
to cross-compile OVS for windows using gcc from mingw-w64.
The patch still shows lots of warnings I haven't fixed, but now
it can generate all the .exe and I tested on windows 10 (no kernel
module).

To try it on:
1) download mingw-w64
2) configure and build
  ./boot.sh

LIBS="-lws2_32 -lshlwapi -liphlpapi -lwbemuuid -lole32 -loleaut32 " \
  ./configure \
  --with-pthread=/disk2/ovs-win32/pthreads-win32/Pre-built.2 \
  --with-openssl=/usr/x86_64-w64-mingw32/include \
  CC=x86_64-w64-mingw32-gcc --host=x86_64-w64-mingw32 \
  CXX=x86_64-w64-mingw32-g++ \
  CXXCPP=x86_64-w64-mingw32-cpp-win32 \
  --includedir=/usr/x86_64-w64-mingw32/include \
  --prefix="C:/openvswitch/usr" \
  --localstatedir="C:/openvswitch/var" \
  --sysconfdir="C:/openvswitch/etc"

Signed-off-by: William Tu <u9012063 at gmail.com>
---
 Makefile.am                     |  6 +++++-
 include/openvswitch/compiler.h  | 10 ++++++++++
 include/windows/net/if.h        |  2 +-
 include/windows/netinet/icmp6.h |  4 ++++
 include/windows/windefs.h       | 18 ++++++++++++------
 lib/byte-order.h                | 16 ++++++++++++++++
 lib/dpif-netlink-rtnl.h         |  6 +++---
 lib/entropy.c                   |  2 +-
 lib/getrusage-windows.c         |  4 ++--
 lib/netlink-socket.c            |  4 ++++
 lib/packets.h                   |  7 +++++--
 lib/stdio.c                     | 40 ----------------------------------------
 lib/stdio.h.in                  | 18 ++----------------
 lib/stream-windows.c            | 16 ++++++++--------
 lib/timeval.c                   | 33 ---------------------------------
 lib/wmi.h                       |  2 +-
 m4/openvswitch.m4               |  3 +--
 17 files changed, 75 insertions(+), 116 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index b279303d186c..1426929ce45e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,6 +34,10 @@ AM_CFLAGS = -Wstrict-prototypes
 AM_CFLAGS += $(WARNING_FLAGS)
 AM_CFLAGS += $(OVS_CFLAGS)
 
+if WIN32
+AM_CFLAGS += -mno-ms-bitfields
+endif
+
 if DPDK_NETDEV
 AM_CFLAGS += -D_FILE_OFFSET_BITS=64
 DPDKSTRIP_FLAGS = --dpdk
@@ -49,7 +53,7 @@ endif
 AM_CTAGSFLAGS = $(OVS_CTAGS_IDENTIFIERS_LIST)
 
 if WIN32
-psep=";"
+psep=
 else
 psep=":"
 endif
diff --git a/include/openvswitch/compiler.h b/include/openvswitch/compiler.h
index 5289a70f6ead..cf4499adb660 100644
--- a/include/openvswitch/compiler.h
+++ b/include/openvswitch/compiler.h
@@ -20,6 +20,11 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+#ifdef _WIN32
+#define __USE_MINGW_ANSI_STDIO 1
+#include <stdio.h>
+#endif
+
 #ifndef __has_feature
   #define __has_feature(x) 0
 #endif
@@ -39,8 +44,13 @@
 
 #if __GNUC__ && !__CHECKER__
 #define OVS_UNUSED __attribute__((__unused__))
+#ifdef _WIN32
+#define OVS_PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(__MINGW_PRINTF_FORMAT, FMT, ARG1)))
+#define OVS_SCANF_FORMAT(FMT, ARG1) __attribute__((__format__(__MINGW_SCANF_FORMAT, FMT, ARG1)))
+#else
 #define OVS_PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1)))
 #define OVS_SCANF_FORMAT(FMT, ARG1) __attribute__((__format__(scanf, FMT, ARG1)))
+#endif
 #define OVS_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
 #define OVS_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1)
 #define OVS_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0)
diff --git a/include/windows/net/if.h b/include/windows/net/if.h
index 3a064ae7ace6..033bc609da24 100644
--- a/include/windows/net/if.h
+++ b/include/windows/net/if.h
@@ -17,7 +17,7 @@
 #ifndef __NET_IF_H
 #define __NET_IF_H 1
 
-#include <Netioapi.h>
+#include <netioapi.h>
 
 #define IFNAMSIZ IF_NAMESIZE
 
diff --git a/include/windows/netinet/icmp6.h b/include/windows/netinet/icmp6.h
index 81f8f5d237b2..13448287b2e8 100644
--- a/include/windows/netinet/icmp6.h
+++ b/include/windows/netinet/icmp6.h
@@ -86,6 +86,8 @@ struct icmp6_hdr {
 #define icmp6_seq	icmp6_data16[1]		/* echo request/reply */
 #define icmp6_maxdelay	icmp6_data16[0]		/* mcast group membership */
 
+#include <iprtrmib.h>
+#if 0
 #define ICMP6_DST_UNREACH		1	/* dest unreachable, codes: */
 #define ICMP6_PACKET_TOO_BIG		2	/* packet too big */
 #define ICMP6_TIME_EXCEEDED		3	/* time exceeded, code: */
@@ -93,6 +95,8 @@ struct icmp6_hdr {
 
 #define ICMP6_ECHO_REQUEST		128	/* echo service */
 #define ICMP6_ECHO_REPLY		129	/* echo reply */
+#endif
+
 #define MLD_LISTENER_QUERY		130 	/* multicast listener query */
 #define MLD_LISTENER_REPORT		131	/* multicast listener report */
 #define MLD_LISTENER_DONE		132	/* multicast listener done */
diff --git a/include/windows/windefs.h b/include/windows/windefs.h
index 6ed8d8722499..78dc0286540b 100644
--- a/include/windows/windefs.h
+++ b/include/windows/windefs.h
@@ -17,15 +17,21 @@
 #ifndef WINDEFS_H
 #define WINDEFS_H 1
 
-#include <Winsock2.h>
-#include <In6addr.h>
-#include <WS2tcpip.h>
+#define _WIN32_WINNT 0x600 /* Windows Visa above */
+
+#define __USE_MINGW_ANSI_STDIO 1
+
+#include <winsock2.h>
+#include <in6addr.h>
+#include <ws2tcpip.h>
 #include <windows.h>
-#include <BaseTsd.h>
+#include <basetsd.h>
+#include <shlwapi.h>
 #include <io.h>
 #include <inttypes.h>
+#include <sys/types.h>
 
-#pragma comment(lib, "advapi32")
+//#pragma comment(lib, "advapi32")
 
 #undef INET6_ADDRSTRLEN
 #define INET6_ADDRSTRLEN 46
@@ -38,7 +44,7 @@
 #define u_int32_t uint32_t
 #define u_int64_t uint64_t
 
-typedef int pid_t;
+//typedef int pid_t;
 
 char *strsep(char **stringp, const char *delim);
 
diff --git a/lib/byte-order.h b/lib/byte-order.h
index 66d29a2b37da..2e2ecb25e3e0 100644
--- a/lib/byte-order.h
+++ b/lib/byte-order.h
@@ -22,6 +22,22 @@
 #include <inttypes.h>
 #include "openvswitch/types.h"
 
+#ifdef _WIN32
+static unsigned __int64 ntohll(
+  unsigned __int64 n
+  )
+{
+    return htonl(1) == 1 ? n : ((uint64_t) ntohl(n) << 32) | ntohl(n >> 32);
+}
+static unsigned __int64 htonll(
+  unsigned __int64 n
+  )
+{
+    return htonl(1) == 1 ? n : ((uint64_t) htonl(n) << 32) | htonl(n >> 32);
+}
+
+#endif
+
 #ifndef __CHECKER__
 #if !(defined(_WIN32) || defined(htonll))
 static inline ovs_be64
diff --git a/lib/dpif-netlink-rtnl.h b/lib/dpif-netlink-rtnl.h
index 5c790e0bc06f..e6dec78c7fc0 100644
--- a/lib/dpif-netlink-rtnl.h
+++ b/lib/dpif-netlink-rtnl.h
@@ -30,20 +30,20 @@ bool dpif_netlink_rtnl_probe_oot_tunnels(void);
 #ifndef __linux__
 /* Dummy implementations for non Linux builds. */
 
-static inline int
+inline int
 dpif_netlink_rtnl_port_create(struct netdev *netdev OVS_UNUSED)
 {
     return EOPNOTSUPP;
 }
 
-static inline int
+inline int
 dpif_netlink_rtnl_port_destroy(const char *name OVS_UNUSED,
                                const char *type OVS_UNUSED)
 {
     return EOPNOTSUPP;
 }
 
-static inline bool
+inline bool
 dpif_netlink_rtnl_probe_oot_tunnels(void)
 {
     return true;
diff --git a/lib/entropy.c b/lib/entropy.c
index 05cc64835717..eaaaf6d5c924 100644
--- a/lib/entropy.c
+++ b/lib/entropy.c
@@ -21,7 +21,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #ifdef _WIN32
-#include <Wincrypt.h>
+#include <wincrypt.h>
 #endif
 #include "util.h"
 #include "socket-util.h"
diff --git a/lib/getrusage-windows.c b/lib/getrusage-windows.c
index 915725e37374..cfa3359606a5 100644
--- a/lib/getrusage-windows.c
+++ b/lib/getrusage-windows.c
@@ -50,13 +50,13 @@ getrusage(int who, struct rusage *usage)
                       ovs_lasterror_to_string());
             return -1;
         }
-
+#ifndef _WIN32
         if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
             VLOG_ERR("failed at GetProcessMemoryInfo: %s",
                       ovs_lasterror_to_string());
             return -1;
         }
-
+#endif
         usage_to_timeval(&kernel_time, &usage->ru_stime);
         usage_to_timeval(&user_time, &usage->ru_utime);
         usage->ru_majflt = pmc.PageFaultCount;
diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c
index 47077e94780f..e7dde329b0f0 100644
--- a/lib/netlink-socket.c
+++ b/lib/netlink-socket.c
@@ -39,6 +39,10 @@
 #include "util.h"
 #include "openvswitch/vlog.h"
 
+#ifdef _WIN32
+#include <mswsock.h>
+#endif
+
 VLOG_DEFINE_THIS_MODULE(netlink_socket);
 
 COVERAGE_DEFINE(netlink_overflow);
diff --git a/lib/packets.h b/lib/packets.h
index 5d7f82c45b6a..e03b874b0639 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -749,18 +749,21 @@ struct ip_header {
 BUILD_ASSERT_DECL(IP_HEADER_LEN == sizeof(struct ip_header));
 
 /* ICMPv4 types. */
+#include <iprtrmib.h>
+#if 0
 #define ICMP4_ECHO_REPLY 0
 #define ICMP4_DST_UNREACH 3
-#define ICMP4_SOURCEQUENCH 4
 #define ICMP4_REDIRECT 5
 #define ICMP4_ECHO_REQUEST 8
 #define ICMP4_TIME_EXCEEDED 11
 #define ICMP4_PARAM_PROB 12
+#endif
+
+#define ICMP4_SOURCEQUENCH 4
 #define ICMP4_TIMESTAMP 13
 #define ICMP4_TIMESTAMPREPLY 14
 #define ICMP4_INFOREQUEST 15
 #define ICMP4_INFOREPLY 16
-
 #define ICMP_HEADER_LEN 8
 struct icmp_header {
     uint8_t icmp_type;
diff --git a/lib/stdio.c b/lib/stdio.c
index 5c5c92466588..97b6b5af3eaa 100644
--- a/lib/stdio.c
+++ b/lib/stdio.c
@@ -18,43 +18,3 @@
 
 #include <stdio.h>
 #include <sys/types.h>
-
-#ifdef _WIN32
-#undef snprintf
-#undef vsnprintf
-
-int
-ovs_snprintf(char *s, size_t n, const char *format, ... )
-{
-    va_list args;
-    int len;
-
-    va_start(args, format);
-    len = ovs_vsnprintf(s, n, format, args);
-    va_end(args);
-
-    return len;
-}
-
-int
-ovs_vsnprintf(char *s, size_t n, const char *format, va_list args)
-{
-    int needed = _vscprintf(format, args);
-    if (s && n) {
-        vsnprintf(s, n, format, args);
-        s[n - 1] = '\0';
-    }
-    return needed;
-}
-
-int
-fseeko(FILE *stream, off_t offset, int whence)
-{
-    int error;
-    error = _fseeki64(stream, offset, whence);
-    if (error) {
-        return -1;
-    }
-    return error;
-}
-#endif  /* _WIN32 */
diff --git a/lib/stdio.h.in b/lib/stdio.h.in
index 7adb9ed2a400..7f4d7b9d4856 100644
--- a/lib/stdio.h.in
+++ b/lib/stdio.h.in
@@ -24,23 +24,9 @@
 #include <stdarg.h>
 #include <stddef.h>
 #include <sys/types.h>
+#define __USE_MINGW_ANSI_STDIO 1
+#include <stdio.h>
 
-/* Windows libc has defective snprintf() and vsnprintf():
- *
- *     - They return -1 if the output won't fit.
- *
- *     - They don't null-terminate the output if it won't fit.
- *
- * We need working versions so here we define substitutes. */
-#undef snprintf
-#define snprintf ovs_snprintf
-int ovs_snprintf(char *, size_t, const char *, ...);
-
-#undef vsnprintf
-#define vsnprintf ovs_vsnprintf
-int ovs_vsnprintf(char *, size_t, const char *, va_list);
-
-int fseeko(FILE *stream, off_t offset, int whence);
 #endif /* _WIN32 */
 
 #endif /* stdio.h wrapper */
diff --git a/lib/stream-windows.c b/lib/stream-windows.c
index 5c4c55e5d4aa..7b549673cde9 100644
--- a/lib/stream-windows.c
+++ b/lib/stream-windows.c
@@ -148,14 +148,14 @@ windows_open(const char *name, char *suffix, struct stream **streamp,
     }
 
     if (!retry && npipe == INVALID_HANDLE_VALUE) {
-        VLOG_ERR_RL(&rl, "Could not connect to named pipe: %s",
-                    ovs_lasterror_to_string());
+        VLOG_ERR_RL(&rl, "Could not connect to named pipe: %s at %s",
+                    ovs_lasterror_to_string(), connect_path);
         free(connect_path);
         return ENOENT;
     }
     if (!retry && !SetNamedPipeHandleState(npipe, &mode, NULL, NULL)) {
-        VLOG_ERR_RL(&rl, "Could not set named pipe options: %s",
-                    ovs_lasterror_to_string());
+        VLOG_ERR_RL(&rl, "Could not set named pipe options: %s at %s",
+                    ovs_lasterror_to_string(), connect_path);
         free(connect_path);
         CloseHandle(npipe);
         return ENOENT;
@@ -239,7 +239,7 @@ windows_recv(struct stream *stream, void *buffer, size_t n)
 
     /* If the read operation was pending, we verify its result. */
     if (s->read_pending) {
-        if (!GetOverlappedResult(s->fd, ov, &(DWORD)retval, FALSE)) {
+        if (!GetOverlappedResult(s->fd, ov, (LPDWORD)retval, FALSE)) {
             last_error = GetLastError();
             if (last_error == ERROR_IO_INCOMPLETE) {
                 /* If the operation is still pending, retry again. */
@@ -261,7 +261,7 @@ windows_recv(struct stream *stream, void *buffer, size_t n)
         return retval;
     }
 
-    result = ReadFile(s->fd, buffer, n, &(DWORD)retval, ov);
+    result = ReadFile(s->fd, buffer, n, (LPDWORD)retval, ov);
 
     if (!result && GetLastError() == ERROR_IO_PENDING) {
         /* Mark the read operation as pending. */
@@ -297,7 +297,7 @@ windows_send(struct stream *stream, const void *buffer, size_t n)
 
     /* If the send operation was pending, we verify the result. */
     if (s->write_pending) {
-        if (!GetOverlappedResult(s->fd, ov, &(DWORD)retval, FALSE)) {
+        if (!GetOverlappedResult(s->fd, ov, (LPDWORD)retval, FALSE)) {
             last_error = GetLastError();
             if (last_error == ERROR_IO_INCOMPLETE) {
                 /* If the operation is still pending, retry again. */
@@ -319,7 +319,7 @@ windows_send(struct stream *stream, const void *buffer, size_t n)
         return retval;
     }
 
-    result = WriteFile(s->fd, buffer, n, &(DWORD)retval, ov);
+    result = WriteFile(s->fd, buffer, n, (LPDWORD)retval, ov);
     last_error = GetLastError();
     if (!result && last_error == ERROR_IO_PENDING) {
         /* Mark the send operation as pending. */
diff --git a/lib/timeval.c b/lib/timeval.c
index 193c7bab1781..21ac09acb631 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -418,39 +418,6 @@ xgetfiletime(void)
     return current_time;
 }
 
-static int
-clock_gettime(clock_t id, struct timespec *ts)
-{
-    if (id == CLOCK_MONOTONIC) {
-        static LARGE_INTEGER freq;
-        LARGE_INTEGER count;
-        long long int ns;
-
-        if (!freq.QuadPart) {
-            /* Number of counts per second. */
-            QueryPerformanceFrequency(&freq);
-        }
-        /* Total number of counts from a starting point. */
-        QueryPerformanceCounter(&count);
-
-        /* Total nano seconds from a starting point. */
-        ns = (double) count.QuadPart / freq.QuadPart * 1000000000;
-
-        ts->tv_sec = count.QuadPart / freq.QuadPart;
-        ts->tv_nsec = ns % 1000000000;
-    } else if (id == CLOCK_REALTIME) {
-        ULARGE_INTEGER current_time = xgetfiletime();
-
-        /* Time from Epoch to now. */
-        ts->tv_sec = (current_time.QuadPart - unix_epoch) / 10000000;
-        ts->tv_nsec = ((current_time.QuadPart - unix_epoch) %
-                       10000000) * 100;
-    } else {
-        return -1;
-    }
-
-    return 0;
-}
 #endif /* _WIN32 */
 
 #if defined(__MACH__) && !defined(HAVE_CLOCK_GETTIME)
diff --git a/lib/wmi.h b/lib/wmi.h
index 28910e78320f..40d755e8ebf2 100644
--- a/lib/wmi.h
+++ b/lib/wmi.h
@@ -18,7 +18,7 @@
 #define WMI_H 1
 
 #include <windefs.h>
-#include <Wbemidl.h>
+#include <wbemidl.h>
 
 static inline void fill_context(IWbemContext *pContext)
 {
diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
index add3aabcc278..5cdd451d3cd1 100644
--- a/m4/openvswitch.m4
+++ b/m4/openvswitch.m4
@@ -111,7 +111,7 @@ AC_DEFUN([OVS_CHECK_WIN32],
             fi
             PTHREAD_INCLUDES=-I$withval/include
             PTHREAD_LDFLAGS=-L$PTHREAD_WIN32_DIR
-            PTHREAD_LIBS="-lpthreadVC2"
+            PTHREAD_LIBS="-lpthread"
             AC_SUBST([PTHREAD_WIN32_DIR_DLL_WIN_FORM])
             AC_SUBST([PTHREAD_WIN32_DIR_DLL])
             AC_SUBST([PTHREAD_INCLUDES])
@@ -136,7 +136,6 @@ AC_DEFUN([OVS_CHECK_WIN32],
       )
 
       AC_DEFINE([WIN32], [1], [Define to 1 if building on WIN32.])
-      AC_CHECK_TYPES([struct timespec], [], [], [[#include <time.h>]])
       AH_BOTTOM([#ifdef WIN32
 #include "include/windows/windefs.h"
 #endif])
-- 
2.7.4



More information about the dev mailing list