MinGW64和“C函数的冲突声明int select(...)”

时间:2017-12-30 05:27:26

标签: c++ sockets mingw-w64 botan

我正在尝试在MinGW上构建Botan,这实际上是MinGW-w64(x86_64-pc-msys)。它在MinGW上失败,如下所示。我想我把它缩减为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;
}

结果是:

$ 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,
     ^~~~~~

首先包括<sys/select.h>非常重要。在Windows标头之后包括它没有见证问题。包括<memory>很重要。 <memory>包含其他标题,例如<sys/select.h>,已包含在内。

我能说的最好,MinGW标头导致问题。它们提供两种不同签名的相同功能:

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

问题似乎是最后一个论点。在一种情况下,它是PTIMEVAL,在另一种情况下,它是timeval*。这似乎与邮件列表有关,但我不明白我应该做什么:Replace struct timeval usage with PTIMEVAL and define TIMEVAL differently on LP64

What do I have to look out for when porting applications to 64 bit Cygwin?详细说明可能存在一些指针大小问题,但它是MinGW代码(而不是Botan代码)。

问题是什么,我该如何解决?

这是Botan的src/lib/utils/socket/socket.cpp

这是编译错误:

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

2 个答案:

答案 0 :(得分:3)

我正在尝试在MinGW上构建Botan,这实际上是MinGW-w64 ( x86_64-pc-msys

我怀疑这是错误的目标-您无意中为MSYS2环境本身(确实是POSIXy)构建。这就是为什么<sys/select.h>被拉入并引起冲突。至少,我严重怀疑如果您打算仅在MSYS2环境中构建供使用,则您将尝试使用<winsock2.h><windows.h>。您应该确保从命令行正确调用了MSYS /使用了正确的快捷方式,以便将其配置为针对MINGW64进行构建,或者,如果确实是,请确保已为MINGW64安装了gcc工具链。如果您没有这样做,那么即使您已正确打开MINGW64,它也会 默默地默认回到MSYS2的gcc工具链,它将继续引入特定于MSYS2构建的附件。可以通过运行

来安装(或重新安装)用于MINGW64的GCC
pacman -Sy mingw-w64-x86_64-gcc

您还可以使用以下方法安装或重新安装Windows专用标头:

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

完成此操作后,运行uname来确认您处在正确的构建环境中,这应该会产生结果

MINGW64_NT-10.0-18363

,然后是gcc -dumpmachine,它应该产生

x86_64-w64-mingw64

对于MSYS2,这些值为

MSYS_NT-10.0-18363

x86_64-pc-msys

分别。

为什么我知道这个?从字面上看,我整夜都熬着同样的问题,直到注意到_WIN32和_WIN64都未定义,以及包含文件来自(/usr/include而不是/mingw64/x86_64-w64-mingw32/include的地方之后,我意识到我是为x86_64-pc-msys而不是x86_64-w64-mingw32构建的。

(当然,如果您要针对32位Windows进行构建,上述所有内容同样适用。请确保已正确调用MINGW32环境,并且已运行pacman -Sy mingw-w64-i686-gcc mingw-w64-i686-headers-git,因此,您最终不会尝试使用为MSYS2配置的gcc进行构建。)

无论如何,我确定这个问题已经有两年历史了,从那以后OP就开始了。但这是一个容易犯的配置错误。因此,无论如何,我希望这会有所帮助!不要误会我的意思!并确保所有人安全!

答案 1 :(得分:1)

<sys/select.h>是Linux系统的头文件,因此不应随MinGW工具链一起提供。如果您的系统中有它,则可能是间接或不受支持的。因此,从程序中删除第一行。同样,<windows><memory>都没有为该特定程序带来任何好处。

MinGW使用Windows套接字(2)库提供的select函数,因此,必须使用build命令中的链接器标记-lws2_32将程序链接到它。 / p>