使用CLion / CMake / MSVC 2015编译WIN32应用程序时出现链接错误

时间:2018-02-21 20:50:46

标签: c++ winapi visual-studio-2015 cmake clion

我无法使用CLion和Visual Studio 2015作为工具链编译简单的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构建类型设置为Debug
  • CMake 3.9.6
  • Visual Studio 2015(社区)

请告知

编辑1

正如我所提到的,我尽可能地简化了代码以重现错误。因此,使用std :: out。实际应用程序实际上是QT应用程序,而不是控制台应用程序。

我在CMakeList.txt文件中添加WIN32参数,以便应用程序在执行EXE时直接启动GUI(而不是加载命令行提示符然后加载GUI)。

2 个答案:

答案 0 :(得分:1)

错误是预料之中的。它只是遵循行记录的行为

add_executable(${PROJECT_NAME} WIN32 main.cpp)

来自add_executable

  

如果给出WIN32,则将在创建的目标上设置属性WIN32_EXECUTABLE。有关详细信息,请参阅该目标属性的文档。

WIN32_EXECUTABLE的文档:

  

[...]当此属性设置为true时,在Windows上链接的可执行文件将使用WinMain()入口点而不是main()创建。 [...]

您有两个选择:

  • WIN32命令中删除add_executable
  • int main(int, char**)替换为WinMain入口点:int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

如果您不想弹出控制台窗口,第二个选项很可能就是您要找的。

答案 1 :(得分:0)

IInspectable's excellent answer很好地介绍了这一点,但我有一个小的补充。

由于您写道,您正在使用Qt应用程序:Qt offers a mechanism以便携方式处理此问题。

Qt附带了一个静态库qtmain.lib,它为您定义了一个WinMain()函数,它只是将所有命令行参数转发给main函数(如果是Win32可执行文件,只是一个普通的功能)。对于Qt5,您只需将以下内容添加到CMakeLists.txt

即可
if(WIN32)
    target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::WinMain)
endif()

请注意,这仅适用于之前find_package来电已正确找到Qt5的情况。