Link 使用 CLion/CMake/MSVC 2015 编译 WIN32 应用程序时出错
Link error when compiling WIN32 application with CLion/CMake/MSVC 2015
我无法使用以 Visual Studio 2015 作为工具链的 CLion 编译简单的 WIN32 应用程序。这是我收到的链接器错误:
[ 50%] Linking CXX executable test-test.exe
MSVCRTD.lib(exe_winmain.obj) : error LNK2019: unresolved external symbol WinMain referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ)
test-test.exe : fatal error LNK1120: 1 unresolved externals
LINK Pass 1 failed. with 1120
以下是重现该问题的最简化代码版本。它包含在这两个文件中:
CMakeList.txt
cmake_minimum_required(VERSION 3.9.6)
add_executable(${PROJECT_NAME} WIN32 main.cpp)
main.cpp
#include <iostream>
int main(int argc, char **argv) {
std::cout << "HELLO WORLD!" << std::endl;
return 0;
}
关于我正在使用的工具的更多详细信息:
- CLION 2018.1 EAP(最新版)
- 我也用以前的非 EAP 版本测试过,结果一样
- CLion 的工具链架构设置为 x86_amd64
- CLion 的 CMake 构建类型设置为调试
- CMake 3.9.6
- Visual Studio 2015 年(社区)
请指教
编辑 1
正如我提到的,我尽可能地简化了代码以重现错误。因此,使用了std::out。真正的应用程序实际上是QT应用程序,而不是控制台应用程序。
我在 CMakeList.txt 文件中添加了 WIN32 参数,以便应用程序在执行 EXE 时直接启动 GUI(而不是加载命令行提示符,然后加载 GUI)。
该错误在意料之中。它只是遵循行
记录的行为
add_executable(${PROJECT_NAME} WIN32 main.cpp)
If WIN32
is given the property WIN32_EXECUTABLE will be set on the target created. See documentation of that target property for details.
WIN32_EXECUTABLE 的文档:
[...] When this property is set to true the executable when linked on Windows will be created with a WinMain() entry point instead of just main(). [...]
您有 2 个选择:
- 从
add_executable
命令中删除 WIN32
。
- 将
int main(int, char**)
替换为 WinMain 入口点:int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
.
如果您不想弹出控制台 window,那么第二个选项可能就是您要找的。
很好地涵盖了这一点,但我有一点补充。
由于您写道您正在使用 Qt 应用程序:Qt offers a mechanism 以可移植的方式处理此问题。
Qt 附带一个静态库 qtmain.lib
,它为您定义了一个 WinMain()
函数,它简单地将所有命令行参数转发给 main
函数(在 Win32 的情况下executable,只是一个普通的函数)。对于 Qt5,您只需将以下内容添加到您的 CMakeLists.txt
:
if(WIN32)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::WinMain)
endif()
请注意,只有在之前的 find_package
调用中正确找到 Qt5 时,这才会起作用。
我无法使用以 Visual Studio 2015 作为工具链的 CLion 编译简单的 WIN32 应用程序。这是我收到的链接器错误:
[ 50%] Linking CXX executable test-test.exe
MSVCRTD.lib(exe_winmain.obj) : error LNK2019: unresolved external symbol WinMain referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ)
test-test.exe : fatal error LNK1120: 1 unresolved externals
LINK Pass 1 failed. with 1120
以下是重现该问题的最简化代码版本。它包含在这两个文件中:
CMakeList.txt
cmake_minimum_required(VERSION 3.9.6) add_executable(${PROJECT_NAME} WIN32 main.cpp)
main.cpp
#include <iostream> int main(int argc, char **argv) { std::cout << "HELLO WORLD!" << std::endl; return 0; }
关于我正在使用的工具的更多详细信息:
- CLION 2018.1 EAP(最新版)
- 我也用以前的非 EAP 版本测试过,结果一样
- CLion 的工具链架构设置为 x86_amd64
- CLion 的 CMake 构建类型设置为调试
- CMake 3.9.6
- Visual Studio 2015 年(社区)
请指教
编辑 1
正如我提到的,我尽可能地简化了代码以重现错误。因此,使用了std::out。真正的应用程序实际上是QT应用程序,而不是控制台应用程序。
我在 CMakeList.txt 文件中添加了 WIN32 参数,以便应用程序在执行 EXE 时直接启动 GUI(而不是加载命令行提示符,然后加载 GUI)。
该错误在意料之中。它只是遵循行
记录的行为add_executable(${PROJECT_NAME} WIN32 main.cpp)
If
WIN32
is given the property WIN32_EXECUTABLE will be set on the target created. See documentation of that target property for details.
WIN32_EXECUTABLE 的文档:
[...] When this property is set to true the executable when linked on Windows will be created with a WinMain() entry point instead of just main(). [...]
您有 2 个选择:
- 从
add_executable
命令中删除WIN32
。 - 将
int main(int, char**)
替换为 WinMain 入口点:int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
.
如果您不想弹出控制台 window,那么第二个选项可能就是您要找的。
由于您写道您正在使用 Qt 应用程序:Qt offers a mechanism 以可移植的方式处理此问题。
Qt 附带一个静态库 qtmain.lib
,它为您定义了一个 WinMain()
函数,它简单地将所有命令行参数转发给 main
函数(在 Win32 的情况下executable,只是一个普通的函数)。对于 Qt5,您只需将以下内容添加到您的 CMakeLists.txt
:
if(WIN32)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::WinMain)
endif()
请注意,只有在之前的 find_package
调用中正确找到 Qt5 时,这才会起作用。