使用MSYS2/UCRT/GCC12编译Qt6程序时出现qMain未定义引用错误
问题描述
环境配置
Windows 10环境,使用工具链:
- MSYS2/UCRT/GCC 12.2
- C++23标准
- MSYS2版Qt6
- CMake 3.25.1
- Ninja 1.11.1
- 编辑器:Notepad++,操作环境:Windows命令提示符
代码文件
program.cpp
#include <QApplication> #include <QLabel> int main() { int argc = 1; const char* argv[1] { "prog" }; QApplication app { argc, const_cast<char**>(argv) }; QLabel *label = new QLabel("Hello Qt!"); label->show(); return app.exec(); }
toolchain.cmake
set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_C_COMPILER gcc) set(CMAKE_CXX_COMPILER g++)
configure.bat
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_VERBOSE_MAKEFILE=ON .
CMakeLists.txt
cmake_minimum_required(VERSION 3.16) set(CMAKE_VERBOSE_MAKEFILE on) project(test_cmake_qt VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Core Widgets) qt_standard_project_setup() qt_add_executable(program_qt_gpp_cmake program.cpp ) target_compile_options(program_qt_gpp_cmake PRIVATE -pedantic -Wall -Wextra -Werror=return-type -Wshadow=local -Wempty-body -fno-ms-extensions -fdiagnostics-color -s -Os -fmax-errors=3) target_link_libraries(program_qt_gpp_cmake PRIVATE Qt6::Widgets ) set_target_properties(program_qt_gpp_cmake PROPERTIES WIN32_EXECUTABLE ON )
build.bat
cmake --build . --config Debug --target program_qt_gpp_cmake
操作流程与错误
执行configure.bat正常完成,执行build.bat时出现链接错误:
C:/programs/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/programs/msys64/ucrt64/lib/libQt6EntryPoint.a(qtentrypoint_win.cpp.obj):(.text+0x11b): undefined reference to `qMain(int, char**)' collect2.exe: error: ld returned 1 exit status
问题原因与解决方法
错误原因
当设置WIN32_EXECUTABLE ON时,Qt会启用GUI程序的入口点封装逻辑:Qt通过libQt6EntryPoint库提供的入口函数会尝试调用qMain(int, char**),而这个函数是Qt通过宏从标准main函数转换而来的。你的main函数是无参数签名int main(),不符合Qt宏的转换要求,导致无法生成qMain,最终链接失败。
qMain的定义
qMain并非需要手动定义的函数,它是Qt通过头文件(如<QApplication>)中的预处理器宏自动生成的——当你使用标准的int main(int argc, char *argv[])签名时,Qt会将其替换为qMain,适配Windows GUI程序的入口逻辑。
解决方法
不需要额外链接库,只需修改program.cpp中的main函数为标准签名即可:
#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel *label = new QLabel("Hello Qt!"); label->show(); return app.exec(); }
如果坚持使用无参数main,可以移除CMakeLists.txt中的WIN32_EXECUTABLE ON设置,但此时程序会被识别为控制台程序(运行时会弹出控制台窗口),这不符合GUI程序的常规使用场景。
内容的提问来源于stack exchange,提问作者crillion
相关产品推荐
相关产品推荐

