【C++】【Crow】我在使用Cmake构建Crow项目时遇到的3个问题

本文最后更新于:2023年8月23日 晚上 22:51

【C++】【Crow】我在使用Cmake构建Crow项目时遇到的3个问题

目录

背景:Windows

前言:GCC之罪

问题一:'POSIX_SEM_VALUE_MAX' was not declared in this scope

问题二:fatal error: crow.h: No such file or directory

问题三:Asio缺少Windows相关系统库文件链接

后续

背景:Windows

我通过Vcpkg安装了Crow:

1
2
vcpkg install crow:x64-windows-static
vcpkg install crow:x64-windows

但是在我使用Crow构建最简单的测试程序时,却不太顺利,不是想象中的即装即用。

原因是我使用了GCC😭!

看来Windows环境下还是尽可能选择MSVC编译为好。不过我经过一番研究还是成功地使用了GCC进行编译。

前言:GCC之罪

操作系统:Windows 11 22H2

编译器:GCC 13.0 x86_64-w64-mingw32

这是最新的GCC 13,其MinGW工具链来自:Github 上的x86_64-13.1.0-release-win32-seh-ucrt-rt_v11-rev1.7z

这是我的源码目录结构:

1
2
3
4
5
6
Mode                 LastWriteTime         Length Name
---- ------------- ------ ----
d---- 2023/8/23 21:25 .vscode
d---- 2023/8/23 21:31 build
d---- 2023/8/23 21:13 src
-a--- 2023/8/23 21:31 994 CMakelists.txt

这是src中的main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
#include <crow.h>
int main() {
crow::SimpleApp app;
CROW_ROUTE(app, "/")
([]() {
return "Hello world";
});
app.port(18080).multithreaded().run();
system("pause");
return 0;
}

这是我的CMakelist.txt:

1
2
3
4
5
6
7
8
9
10
11
12
13
cmake_minimum_required(VERSION 3.17)
set(PROJECT_NAME HelloWorld)
set(CMAKE_TOOLCHAIN_FILE "C:/C_CPP/Library/vcpkg/scripts/buildsystems/vcpkg.cmake") # set vcpkg toolchain file path
set(VCPKG_TARGET_TRIPLET "x64-windows")

project(${PROJECT_NAME}) # set project name
add_executable(${PROJECT_NAME} src/main.cpp) # add executable target named ${PROJECT_NAME}
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) # enable C++20 standard
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF) # disable compiler extensions

# 导入Crow库
find_package(Crow CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} Crow::Crow)

问题一:'_POSIX_SEM_VALUE_MAX' was not declared in this scope

CMake输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[main] 正在生成文件夹: vscode_vcpkg_cmake_copy 
[build] 正在启动生成
[proc] 执行命令: "D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Debug --target all -j 22 --
[build] [ 50%] Building CXX object CMakeFiles/HelloWorld.dir/src/main.cpp.obj
[build] <command-line>: warning: ISO C++11 requires whitespace after the macro name
[build] In file included from C:/C_CPP/Tookit/mingw64_13h/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c++/semaphore:37,
[build] from C:/C_CPP/Tookit/mingw64_13h/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c++/stop_token:39,
[build] from C:/C_CPP/Tookit/mingw64_13h/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c++/condition_variable:49,
[build] from C:/C_CPP/Tookit/mingw64_13h/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c++/mutex:48,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/system/detail/mutex.hpp:58,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/system/detail/error_category_impl.hpp:101,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/system/error_category.hpp:11,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/system/error_code.hpp:14,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/throw_error.hpp:20,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_tss_ptr.ipp:22,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/win_tss_ptr.hpp:76,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/tss_ptr.hpp:25,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/call_stack.hpp:20,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/thread_context.hpp:20,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/recycling_allocator.hpp:20,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/handler_alloc_helpers.hpp:21,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/executor_function.hpp:19,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/execution/any_executor.hpp:24,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/execution.hpp:19,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/any_completion_executor.hpp:22,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio.hpp:20,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/crow/socket_adaptors.h:2,
[build] from C:/C_CPP/Library/vcpkg/installed/x64-windows/include/crow.h:7,
[build] from D:\Code\Cpp\ExerciseCode\vscode_vcpkg_cmake_copy\src\main.cpp:3:
[build] C:/C_CPP/Tookit/mingw64_13h/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c++/bits/semaphore_base.h:59:41: error: '_POSIX_SEM_VALUE_MAX' was not declared in this scope
[build] 59 | static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX;
[build] | ^~~~~~~~~~~~~~~~~~~~
[build] mingw32-make.exe[2]: *** [CMakeFiles\HelloWorld.dir\build.make:76: CMakeFiles/HelloWorld.dir/src/main.cpp.obj] Error 1
[build] mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:82: CMakeFiles/HelloWorld.dir/all] Error 2
[build] mingw32-make.exe: *** [Makefile:90: all] Error 2
[proc] 命令“"D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Debug --target all -j 22 --”已退出,代码为 2
[driver] 生成完毕: 00:00:07.788
[build] 生成已完成,退出代码为 2
[cpptools] 生成的生成配置不包含活动生成配置。对 CMAKE_BUILD_TYPE 使用 "" 而不是 "Debug",以确保可以找到 IntelliSense 配置

这好像是由于这个GCC的C++20实现有点BUG,将cxx_std_20 改为cxx_std_17 C++17及以下即可。 询问Claude得到回复如下:(虽然不确定是否正确)

这个错误提示在Windows环境下编译时,不能找到_POSIX_SEM_VALUE_MAX的定义。

_POSIX_SEM_VALUE_MAX是POSIX系统中的一个宏,用于定义semaphore的最大计数值。但是在Windows环境中,并没有这个定义。

很可能是C++标准库的代码原本基于POSIX平台编写,移植到Windows的时候没有适配导致的错误。

要解决这个问题,有以下几种方法:

  1. 在Windows环境下,不要直接使用_POSIX_SEM_VALUE_MAX,可以定义一个兼容值。修改C++标准库实现,根据平台宏对_POSIX_SEM_VALUE_MAX进行隔离。

  2. 在编译命令中定义_POSIX_SEM_VALUE_MAX,使其成为一个空宏。

  3. 尝试更新编译器或标准库版本,使用更兼容的实现。

  4. 根据编译器文档报告此兼容性问题。

  5. 联系原库维护者进行跨平台适配。

  6. 隔离使用非兼容接口的代码,避免污染Windows环境。

  7. 考虑用更通用的线程同步原语替换semaphore。

总之,这主要是一个跨平台兼容性问题。需要区分平台适配相关接口,或者更新编译器和库的版本来获得修复。

问题二:fatal error: crow.h: No such file or directory

CMake输出信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
main] 正在生成文件夹: vscode_vcpkg_cmake_copy 
[build] 正在启动生成
[proc] 执行命令: "D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Release --target all -j 22 --
[build] [ 50%] Building CXX object CMakeFiles/HelloWorld.dir/src/main.cpp.obj
[build] D:\Code\Cpp\ExerciseCode\vscode_vcpkg_cmake_copy\src\main.cpp:3:10: fatal error: crow.h: No such file or directory
[build] 3 | #include <crow.h>
[build] | ^~~~~~~~
[build] compilation terminated.
[build] mingw32-make.exe[2]: *** [CMakeFiles\HelloWorld.dir\build.make:75: CMakeFiles/HelloWorld.dir/src/main.cpp.obj] Error 1
[build] mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:82: CMakeFiles/HelloWorld.dir/all] Error 2
[build] mingw32-make.exe: *** [Makefile:90: all] Error 2
[proc] 命令“"D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Release --target all -j 22 --”已退出,代码为 2
[driver] 生成完毕: 00:00:00.543
[build] 生成已完成,退出代码为 2

这个是有点概率出现,不太好复现,清理一下build文件夹,重启一下VSCode似乎就好了。未知原因。

问题三:Asio缺少Windows相关系统库文件链接

CMake输出信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
[main] 正在生成文件夹: vscode_vcpkg_cmake_copy 
[main] 缺少包含 CMake 缓存的文件夹。将重新生成缓存。
[main] 正在配置项目: vscode_vcpkg_cmake_copy
[proc] 执行命令: "D:\Program Files\CMake\bin\cmake.EXE" --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=C:\C_CPP\Tookit\mingw64_13h\bin\gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=C:\C_CPP\Tookit\mingw64_13h\bin\g++.exe -SD:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy -Bd:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build -G "MinGW Makefiles"
[cmake] Not searching for unused variables given on the command line.
[cmake] -- The C compiler identification is GNU 13.1.0
[cmake] -- The CXX compiler identification is GNU 13.1.0
[cmake] -- Detecting C compiler ABI info
[cmake] -- Detecting C compiler ABI info - done
[cmake] -- Check for working C compiler: C:/C_CPP/Tookit/mingw64_13h/bin/gcc.exe - skipped
[cmake] -- Detecting C compile features
[cmake] -- Detecting C compile features - done
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Check for working CXX compiler: C:/C_CPP/Tookit/mingw64_13h/bin/g++.exe - skipped
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] -- Found Boost: C:/C_CPP/Library/vcpkg/installed/x64-windows/include (found suitable version "1.82.0", minimum required is "1.64") found components: system date_time
[cmake] -- Performing Test CMAKE_HAVE_LIBC_PTHREAD
[cmake] -- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
[cmake] -- Looking for pthread_create in pthreads
[cmake] -- Looking for pthread_create in pthreads - not found
[cmake] -- Looking for pthread_create in pthread
[cmake] -- Looking for pthread_create in pthread - found
[cmake] -- Found Threads: TRUE
[cmake] -- Configuring done (7.6s)
[cmake] -- Generating done (0.0s)
[cmake] -- Build files have been written to: D:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build
[build] 正在启动生成
[proc] 执行命令: "D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Debug --target all -j 22 --
[build] [ 50%] Building CXX object CMakeFiles/HelloWorld.dir/src/main.cpp.obj
[build] <command-line>: warning: ISO C++11 requires whitespace after the macro name
[build] [100%] Linking CXX executable HelloWorld.exe
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::winsock_init_base::startup(boost::asio::detail::winsock_init_base::data&, unsigned char, unsigned char)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/winsock_init.ipp:39: undefined reference to `__imp_WSAStartup'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::winsock_init_base::cleanup(boost::asio::detail::winsock_init_base::data&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/winsock_init.ipp:56: undefined reference to `__imp_WSACleanup'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::clear_last_error()':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:73: undefined reference to `__imp_WSASetLastError'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::get_last_error(boost::system::error_code&, bool)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:91: undefined reference to `__imp_WSAGetLastError'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::complete_iocp_accept(unsigned long long, void*, unsigned long, void*, unsigned long long*, unsigned long long, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:206: undefined reference to `GetAcceptExSockaddrs'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::close(unsigned long long, unsigned char&, bool, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:321: undefined reference to `__imp_closesocket'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:339: undefined reference to `__imp_ioctlsocket'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:353: undefined reference to `__imp_closesocket'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::shutdown(unsigned long long, int, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:466: undefined reference to `__imp_shutdown'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::listen(unsigned long long, int, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:694: undefined reference to `__imp_listen'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::send(unsigned long long, _WSABUF const*, unsigned long long, int, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:1381: undefined reference to `__imp_WSASend'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::socket(int, int, int, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:1817: undefined reference to `__imp_WSASocketW'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:1828: undefined reference to `__imp_setsockopt'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::poll_write(unsigned long long, unsigned char, int, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:2295: undefined reference to `__imp_select'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::inet_ntop(int, void const*, char*, unsigned long long, unsigned long, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:2497: undefined reference to `__imp_WSAAddressToStringA'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::inet_pton(int, char const*, void*, unsigned long*, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:2711: undefined reference to `__imp_WSAStringToAddressA'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::network_to_host_long(unsigned long)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:3932: undefined reference to `__imp_ntohl'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::host_to_network_long(unsigned long)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:3947: undefined reference to `__imp_htonl'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::network_to_host_short(unsigned short)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:3959: undefined reference to `__imp_ntohs'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::host_to_network_short(unsigned short)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:3972: undefined reference to `__imp_htons'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::win_iocp_socket_service_base::start_send_op(boost::asio::detail::win_iocp_socket_service_base::base_implementation_type&, _WSABUF*, unsigned long long, int, bool, boost::asio::detail::win_iocp_operation*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:400: undefined reference to `__imp_WSASend'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:402: undefined reference to `__imp_WSAGetLastError'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::win_iocp_socket_service_base::start_receive_op(boost::asio::detail::win_iocp_socket_service_base::base_implementation_type&, _WSABUF*, unsigned long long, int, bool, boost::asio::detail::win_iocp_operation*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:454: undefined reference to `__imp_WSARecv'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:457: undefined reference to `__imp_WSAGetLastError'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::win_iocp_socket_service_base::start_accept_op(boost::asio::detail::win_iocp_socket_service_base::base_implementation_type&, bool, boost::asio::detail::socket_holder&, int, int, int, void*, unsigned long, boost::asio::detail::win_iocp_operation*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:538: undefined reference to `AcceptEx'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:540: undefined reference to `__imp_WSAGetLastError'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::win_iocp_socket_service_base::restart_accept_op(unsigned long long, boost::asio::detail::socket_holder&, int, int, int, void*, unsigned long, long*, boost::asio::detail::win_iocp_operation*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:569: undefined reference to `AcceptEx'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:571: undefined reference to `__imp_WSAGetLastError'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `int boost::asio::detail::socket_ops::call_bind<int>(int boost::asio::detail::socket_ops::msghdr::*, unsigned long long, void const*, unsigned long long)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:283: undefined reference to `__imp_bind'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `int boost::asio::detail::socket_ops::call_setsockopt<int>(int boost::asio::detail::socket_ops::msghdr::*, unsigned long long, int, int, void const*, unsigned long long)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:1862: undefined reference to `__imp_setsockopt'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `int boost::asio::detail::socket_ops::call_getsockopt<int>(int boost::asio::detail::socket_ops::msghdr::*, unsigned long long, int, int, void*, unsigned long long*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:1949: undefined reference to `__imp_getsockopt'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `int boost::asio::detail::socket_ops::call_getpeername<int>(int boost::asio::detail::socket_ops::msghdr::*, unsigned long long, void*, unsigned long long*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:2054: undefined reference to `__imp_getpeername'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `int boost::asio::detail::socket_ops::call_getsockname<int>(int boost::asio::detail::socket_ops::msghdr::*, unsigned long long, void*, unsigned long long*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:2107: undefined reference to `__imp_getsockname'
[build] collect2.exe: error: ld returned 1 exit status
[build] mingw32-make.exe[2]: *** [CMakeFiles\HelloWorld.dir\build.make:101: HelloWorld.exe] Error 1
[build] mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:82: CMakeFiles/HelloWorld.dir/all] Error 2
[build] mingw32-make.exe: *** [Makefile:90: all] Error 2
[proc] 命令“"D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Debug --target all -j 22 --”已退出,代码为 2
[driver] 生成完毕: 00:00:38.628
[build] 生成已完成,退出代码为 2

网上(Google、Bing、Github、StackOverFlow)难以找到答案,因为报错信息有点太了,询问Claude得到答案:

这个链接错误的原因是目标可执行文件在链接过程中无法解析 Windows sockets API 所需要的符号,包括:

  • WSAStartup, WSACleanup - Winsock 初始化和清理函数

  • WSAGetLastError, WSASetLastError - 获取和设置错误码的函数

  • AcceptEx, GetAcceptExSockaddrs - 接受连接的函数

  • closesocket, ioctlsocket 等 - 套接字操作的函数

  • ntohl, htonl, ntohs, htons - 网络字节序转换函数

  • select, WSASend, WSARecv 等 - 套接字I/O操作函数

导致这个错误的常见原因:

  1. 没有链接 Windows socket 库 ws2_32.lib,它包含上述 API 的实现。

  2. 依赖的网络库没有自动链接所需的系统库。

  3. 编译设置没有指定使用 Winsock。

  4. vcpkg动态链接设置不正确,应使用动态CRT链接。

  5. 没有根据平台预定义正确隔离连接代码。

解决方法是:

  1. 显式链接 ws2_32.lib

  2. 确认依赖库已自动链接必要的系统库。

  3. 定义相关宏以开启Winsock支持。

  4. 使用动态链接选项并检查编译器设置。

  5. 根据Windows平台预定义隔离特定实现。

明确添加对 ws2_32.lib 的链接可以解决大部分此类问题。

于是在链接Crow库前先显式链接 ws2_32.lib库:(注意MSVC直接可以支持,无需GCC这样)

1
2
3
4
# 导入Crow库
find_package(Crow)
target_link_libraries(${PROJECT_NAME} ws2_32) # 显式链接 ws2_32.lib 库
target_link_libraries(${PROJECT_NAME} Crow::Crow)

运行CMake,仍然无法成功编译:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[build] 正在启动生成
[proc] 执行命令: "D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Debug --target all -j 22 --
[build] [ 50%] Building CXX object CMakeFiles/HelloWorld.dir/src/main.cpp.obj
[build] <command-line>: warning: ISO C++11 requires whitespace after the macro name
[build] [100%] Linking CXX executable HelloWorld.exe
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::socket_ops::complete_iocp_accept(unsigned long long, void*, unsigned long, void*, unsigned long long*, unsigned long long, boost::system::error_code&)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/socket_ops.ipp:206: undefined reference to `GetAcceptExSockaddrs'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::win_iocp_socket_service_base::start_accept_op(boost::asio::detail::win_iocp_socket_service_base::base_implementation_type&, bool, boost::asio::detail::socket_holder&, int, int, int, void*, unsigned long, boost::asio::detail::win_iocp_operation*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:538: undefined reference to `AcceptEx'
[build] C:/C_CPP/Tookit/mingw64_13h/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\HelloWorld.dir/objects.a(main.cpp.obj): in function `boost::asio::detail::win_iocp_socket_service_base::restart_accept_op(unsigned long long, boost::asio::detail::socket_holder&, int, int, int, void*, unsigned long, long*, boost::asio::detail::win_iocp_operation*)':
[build] C:/C_CPP/Library/vcpkg/installed/x64-windows/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp:569: undefined reference to `AcceptEx'
[build] collect2.exe: error: ld returned 1 exit status
[build] mingw32-make.exe[2]: *** [CMakeFiles\HelloWorld.dir\build.make:101: HelloWorld.exe] Error 1
[build] mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:82: CMakeFiles/HelloWorld.dir/all] Error 2
[build] mingw32-make.exe: *** [Makefile:90: all] Error 2
[proc] 命令“"D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Debug --target all -j 22 --”已退出,代码为 2
[driver] 生成完毕: 00:00:39.516
[build] 生成已完成,退出代码为 2

再次询问Claude,得知:

这些 undefined reference 错误表示项目链接时无法找到 Windows 套接字编程中的 AcceptExGetAcceptExSockaddrs 这两个API函数。

在使用像 Asio 这样的 C++ 网络库开发 Windows 应用时,需要链接 mswsock.lib 库才能使用这些扩展套接字函数。

可以通过以下方式修复:

  1. 在 CMakeLists 里添加:
1
target_link_libraries(myapp PRIVATE mswsock)

来显式链接 mswsock.lib

  1. 确保网络库如 Asio 已经自动链接了依赖的系统库。

  2. 为目标添加编译宏:

1
target_compile_definitions(myapp PUBLIC ASIO_WINDOWS)  
  1. 如果使用 vcpkg,指定动态 CRT 链接:
1
vcpkg install xxx:x64-windows-dynamic
  1. 检查项目是否已经自动链接了 Windows 平台所需的系统库。

  2. 尝试更新网络库至最新版本以获取缺失链接的修复。

综上,明确链接 mswsock.lib 或在上层网络库处理依赖,是解决大多数类似问题的办法。

这里我在链接Crow库前加上mswsock即可解决:

1
2
3
4
find_package(Crow)
target_link_libraries(${PROJECT_NAME} ws2_32)
target_link_libraries(${PROJECT_NAME} mswsock)
target_link_libraries(${PROJECT_NAME} Crow::Crow)

再次运行CMake,完美解决:

1
2
3
4
5
6
7
[main] 正在生成文件夹: vscode_vcpkg_cmake_copy 
[build] 正在启动生成
[proc] 执行命令: "D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Debug --target all -j 22 --
[build] [ 50%] Linking CXX executable HelloWorld.exe
[build] [100%] Built target HelloWorld
[driver] 生成完毕: 00:00:26.796
[build] 生成已完成,退出代码为 0

后续

后面我直接改用MSVC,啥问题都没有,编译时间仅为GCC的40%,同时完美支持C++20🤣 (Visual Studio Enterprise 2022 Preview - amd64,MSVC 19.38.32919.0)

1
2
3
4
5
6
7
8
9
10
11
12
cmake_minimum_required(VERSION 3.17)
set(PROJECT_NAME HelloWorld)
set(CMAKE_TOOLCHAIN_FILE "C:/C_CPP/Library/vcpkg/scripts/buildsystems/vcpkg.cmake") # set vcpkg toolchain file path
set(VCPKG_TARGET_TRIPLET "x64-windows")

project(${PROJECT_NAME}) # set project name
add_executable(${PROJECT_NAME} src/main.cpp) # add executable target named ${PROJECT_NAME}
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) # enable C++20 standard
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF) # disable compiler extensions

find_package(Crow)
target_link_libraries(${PROJECT_NAME} Crow::Crow)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[build] 正在启动生成
[proc] 执行命令: "D:\Program Files\CMake\bin\cmake.EXE" --build d:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/build --config Debug --target ALL_BUILD -j 22 --
[build] 适用于 .NET Framework MSBuild 版本 17.8.0-preview-23376-06+f413f5497
[build]
[build] 1>Checking Build System
[build] Building Custom Rule D:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/CMakeLists.txt
[build] main.cpp
[build] Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
[build] - add -D_WIN32_WINNT=0x0601 to the compiler command line; or
[build] - add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.
[build] Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).
[build] HelloWorld.vcxproj -> D:\Code\Cpp\ExerciseCode\vscode_vcpkg_cmake_copy\build\Debug\HelloWorld.exe
[build] Building Custom Rule D:/Code/Cpp/ExerciseCode/vscode_vcpkg_cmake_copy/CMakeLists.txt
[driver] 生成完毕: 00:00:10.848
[build] 生成已完成,退出代码为 0

Fuck you, GCC !


【C++】【Crow】我在使用Cmake构建Crow项目时遇到的3个问题
https://qalxry.github.io/2023/08/23/【C++】【Crow】我在使用Cmake构建Crow项目时遇到的3个问题/
作者
しずり雪
发布于
2023年8月23日
更新于
2023年8月23日
许可协议