1

I'm trying to build Botan on MinGW, which is really MinGW-w64 (x86_64-pc-msys). It is failing on MinGW as shown below. I think I have it reduced to an MCVE :

#include <sys/select.h>
#include <winsock2.h>
#include <windows.h>
#include <memory>

int main(int argc, char* argv[])
{
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(0, &fds);

    timeval tv;
    tv.tv_sec = 5;
    tv.tv_usec = 0;

    int rc = select(1, &fds, NULL, NULL, &tv);

    return 0;
}

It results in:

$ g++ -m64 -pthread -std=c++11 test.cxx -o test.exe
In file included from /usr/include/w32api/winsock2.h:56:0,
                 from test.cxx:2:
/usr/include/w32api/psdk_inc/_fd_types.h:100:2: warning: #warning "fd_set and associated macros have been defined in sys/types.      This can cause runtime problems with W32 sockets" [-Wcpp]
 #warning "fd_set and associated macros have been defined in sys/types.  \
  ^~~~~~~
In file included from test.cxx:2:0:
/usr/include/w32api/winsock2.h:995:34: error: conflicting declaration of C function ‘int select(int, _types_fd_set*, _types_fd_set*, _types_fd_set*, PTIMEVAL)’
   WINSOCK_API_LINKAGE int WSAAPI select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,const PTIMEVAL timeout);
                                  ^~~~~~
In file included from test.cxx:1:0:
/usr/include/sys/select.h:73:5: note: previous declaration ‘int select(int, _types_fd_set*, _types_fd_set*, _types_fd_set*, timeval*)’
 int select __P ((int __n, fd_set *__readfds, fd_set *__writefds,
     ^~~~~~

Including <sys/select.h> first is important. Including it after the Windows headers does not witness the problem. Including <memory> is important. <memory> includes additional headers like <sys/select.h>, which has already been included.

The best I can tell, MinGW headers are causing the problem. They provide the same function with two different signatures:

/usr/include/w32api/winsock2.h:

int select(int, _types_fd_set*, _types_fd_set*, _types_fd_set*, PTIMEVAL)

/usr/include/sys/select.h

int select(int, _types_fd_set*, _types_fd_set*, _types_fd_set*, timeval*)

The problem appears to be the last argument. In one case it is PTIMEVAL and in the other case it is timeval*. This seems to be related from the mailing list, but I don't understand what I should be doing: Replace struct timeval usage with PTIMEVAL and define TIMEVAL differently on LP64.

There may be some pointer size problems as detailed at What do I have to look out for when porting applications to 64 bit Cygwin?, but it is MinGW code (and not Botan code).

What is the problem, and how do I fix it?


Here is Botan's src/lib/utils/socket/socket.cpp.

Here is the compile error:

g++ -fstack-protector -m64 -pthread   -std=c++11 -D_REENTRANT -O3 -momit-leaf-frame-pointer  \
-Wall -Wextra -Wpedantic -Wstrict-aliasing -Wcast-align -Wmissing-declarations  \
-Wpointer-arith -Wcast-qual -Wzero-as-null-pointer-constant -Wnon-virtual-dtor  \
-Ibuild/include -c src/lib/utils/socket/socket.cpp -o build/obj/lib/utils_socket.o
In file included from /usr/include/w32api/winsock2.h:56:0,
                 from src/lib/utils/socket/socket.cpp:35:
/usr/include/w32api/psdk_inc/_fd_types.h:100:2: warning: #warning "fd_set and associated macros have been defined in sys/types.      This can cause runtime problems with W32 sockets" [-Wcpp]
 #warning "fd_set and associated macros have been defined in sys/types.  \
  ^~~~~~~
In file included from src/lib/utils/socket/socket.cpp:35:0:
/usr/include/w32api/winsock2.h:995:34: error: conflicting declaration of C function ‘int select(int, _types_fd_set*, _types_fd_set*, _types_fd_set*, PTIMEVAL)’
   WINSOCK_API_LINKAGE int WSAAPI select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,const PTIMEVAL timeout);
                                  ^~~~~~
In file included from /usr/include/sys/types.h:68:0,
                 from /usr/include/pthread.h:11,
                 from /usr/lib/gcc/x86_64-pc-msys/6.3.0/include/c++/x86_64-pc-msys/bits/gthr-default.h:35,
                 from /usr/lib/gcc/x86_64-pc-msys/6.3.0/include/c++/x86_64-pc-msys/bits/gthr.h:148,
                 from /usr/lib/gcc/x86_64-pc-msys/6.3.0/include/c++/ext/atomicity.h:35,
                 from /usr/lib/gcc/x86_64-pc-msys/6.3.0/include/c++/memory:73,
                 from build/include/botan/types.h:17,
                 from build/include/botan/internal/socket.h:11,
                 from src/lib/utils/socket/socket.cpp:8:
/usr/include/sys/select.h:73:5: note: previous declaration ‘int select(int, _types_fd_set*, _types_fd_set*, _types_fd_set*, timeval*)’
 int select __P ((int __n, fd_set *__readfds, fd_set *__writefds,
     ^~~~~~
make: *** [Makefile:1066: build/obj/lib/utils_socket.o] Error 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • Note there's an extra `const` in winsock2.h's select declaration, that is likely the culprit. But as far as I can tell select.h isn't part of mingw-w64 (also it's getting pulled from /usr/include which seems very wrong), and if including winsock2.h (the win32 socket API), you (well, botan) probably shouldn't be including select.h (the posix (?) select API), I think they are conflicting in nature and usually it's one or the other. Could be a configuration problem. Also I cannot reproduce it so it would be helpful to provide more info about your build environment. – stijn Dec 30 '17 at 09:46
  • Just guessing here, but I would be a bit concerned about the warning about the `fd_set` parameter type coming from `sys/types`. Perhaps using `-pthread` isn't that good for msys/Windows? – Bo Persson Dec 30 '17 at 10:44
  • @BoPersson - I think I reduced the problem further. It happens when `` is included, then Windows headers, and `` is included. The problem in practice is, we don't have a lot of control of the headers. Everything is included for a reason, and it has an order to ensure types are defined at the right time. – jww Dec 30 '17 at 19:22
  • 2
    winsock2.h has a history of creating problems when it's not included first. – Michael Burr Dec 30 '17 at 19:42
  • Thanks @Michael. Is there a define that can be set for this particular file to signal "Windows" will be handling socket code? – jww Jan 01 '18 at 01:17
  • Your MVCE yields "test.cpp:1:24: fatal error: sys/select.h: No such file or directory", when built on latest msys2, as expected: sys/select.h is *not* part of mingw-w64. So, what exactly is your build environment? – stijn Jan 03 '18 at 08:56
  • @stijn - `gcc -dumpmachine` reports *`x86_64-pc-msys`*. The Windows machine is an Asus laptop running Windows 8.1. MinGW-w64 was downloaded from [mingw-w64 website](https://mingw-w64.org/). – jww Jan 03 '18 at 09:05
  • 1
    Ok but on what OS is that? Is it a cross-compiler? And where/how did you get this x86_64-pc-msys toolset? You see, you say you're using mingw-w64 but in that case, on Debian and MSYS2 and Cygwin `gcc -dumpmachine` should give `x86_64-w64-mingw32`. And there should be no sys/select.h. And Botan builds without problems. – stijn Jan 03 '18 at 09:21
  • @stijn had the right of it. This is why you read the comments, would have saved me an incredible amount of time. – Eli B. Apr 28 '20 at 14:48

2 Answers2

3

I'm trying to build Botan on MinGW, which is really MinGW-w64 (x86_64-pc-msys)

I suspect that this is the wrong target--you are inadvertently building for the MSYS2 environment itself, which is indeed POSIXy. That is why e.g. <sys/select.h> is being pulled in and causing conflicts. At least, I severely doubt you would be trying to use <winsock2.h> or <windows.h> if it were your intent to build for use solely within the MSYS2 environment. You should either make sure that you invoked MSYS correctly from the command-line/used the right shortcut, so that you are configured to build for MINGW64, or, if you are, make sure you've actually installed the gcc toolchain for MINGW64. If you didn't, then even though you've opened MINGW64 properly, it will silently default back to the gcc toolchain for MSYS2, which will proceed to pull in includes specific to an MSYS2 build. GCC for MINGW64 can be installed (or reinstalled) by running

pacman -Sy mingw-w64-x86_64-gcc

You can also install or reinstall the Windows-specific headers with this:

pacman -Sy mingw-w64-x86_64-headers-git 

Once you've done this, run uname to confirm that you're in the correct build environment, which should yield

MINGW64_NT-10.0-18363

and then gcc -dumpmachine, which should yield

x86_64-w64-mingw64

For MSYS2, those values would be

MSYS_NT-10.0-18363

and

x86_64-pc-msys

respectively.

Why do I know this? Literally I stayed up all night with the same problem, and it was only after noticing that _WIN32 and _WIN64 were undefined, as well as where the include files were coming from (/usr/include, rather than /mingw64/x86_64-w64-mingw32/include), that I realized I was building for x86_64-pc-msys, rather than x86_64-w64-mingw32.

(Of course, all of the above is also applicable if you'd like to build for 32-bit Windows. Make sure you've invoked the MINGW32 environment properly, and that you've run pacman -Sy mingw-w64-i686-gcc mingw-w64-i686-headers-git, so you don't end up trying to build with a gcc that's configured for MSYS2.)

Anyway, I'm sure given this question is two years old, OP has since moved on. But it's an easy configuration mistake to make. So, regardless, I hope this is helpful! Don't make my mistake! And stay safe everyone!

Eli B.
  • 151
  • 6
1

<sys/select.h> is a Linux system header file, so it shouldn't come shipped in the MinGW toolchain. If you have it in your system, you might have gotten it in an indirect or unsupported manner. So remove the first line from your program. Also both <windows> and <memory> don't bring anything to this particular program.

MinGW uses the select function provided by the Windows Sockets (2) library, and as such, your program has to be linked to it, using the linker flag -lws2_32 in the build command.

Valeriu
  • 51
  • 4
  • 1
    " is a Linux system header file". It is not. It is specified by POSIX. There is nothig wrong with shipping a file by this name with any product, even not POSIX compliant. – n. m. could be an AI Nov 11 '19 at 11:50