我正在尝试在 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 header 之后包含它不会出现问题。包括<memory>
很重要。 <memory>
包括额外的标题,如 <sys/select.h>
,已经包含在内。
据我所知,问题是由 MinGW header 引起的。它们提供具有两个不同签名的相同功能:
/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
最佳答案
I'm trying to build Botan on MinGW, which is really MinGW-w64 (x86_64-pc-msys)
我怀疑这是错误的目标——您无意中为 MSYS2 环境本身构建,这确实是 POSIXy。这就是为什么例如<sys/select.h>
被拉进来引起冲突。至少,我严重怀疑你会尝试使用 <winsock2.h>
或 <windows.h>
如果您打算构建仅在 MSYS2 环境中使用。您应该确保您从命令行正确调用了 MSYS/使用了正确的快捷方式,以便您配置为为 MINGW64 构建,或者,如果您是,请确保您实际上已经为 MINGW64 安装了 gcc 工具链。如果没有,那么即使您已正确打开 MINGW64,它也会默默地默认返回 MSYS2 的 gcc 工具链,它将继续引入特定于 MSYS2 构建的包含。可以通过运行安装(或重新安装)MINGW64 的 GCC
pacman -Sy mingw-w64-x86_64-gcc
您还可以安装或重新安装特定于 Windows 的 header :
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 已经开始了。但这是一个容易犯的配置错误。所以,无论如何,我希望这会有所帮助!不要误会我的错误!大家注意安全!
关于c++ - MinGW64 和 "conflicting declaration of C function int select(...)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48031258/