使用qmake编译Qt程序时遇链接错误与头文件找不到问题求助
Qt5 qmake编译时链接失败与头文件找不到的解决办法
问题场景
使用以下代码编译Qt5程序:
/* * Copyright (c) 2006-2007, Johan Thelin * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of APress nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include <QtWidgets/QApplication> #include <QtWidgets/QWidget> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QLabel> #include <QtWidgets/QLineEdit> int main (int argc, char **argv) { QApplication app (argc, argv); QWidget widget; QLineEdit *lineEdit = new QLineEdit (); QLabel *label = new QLabel (); QVBoxLayout *layout = new QVBoxLayout (); layout->addWidget (lineEdit); layout->addWidget (label); widget.setLayout (layout); widget.show (); return app.exec (); }
执行LC_ALL=C qmake -project; LC_ALL=C qmake; LC_ALL=C make后出现链接错误:
$ LC_ALL=C qmake -project; LC_ALL=C qmake; LC_ALL=C make Info: creating stash file /path/to/my/dir/.qmake.stash g++ -c -pipe -O2 -Wall -Wextra -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I. -I. -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtGui -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I. -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -o main.o main.cpp g++ -Wl,-O1 -o build main.o /usr/lib/x86_64-linux-gnu/libQt5Gui.so /usr/lib/x86_64-linux-gnu/libQt5Core.so -lGL -lpthread /usr/bin/ld: main.o: in function `main.cold': main.cpp:(.text.unlikely+0x11): undefined reference to `QWidget::~QWidget()' /usr/bin/ld: main.cpp:(.text.unlikely+0x19): undefined reference to `QApplication::~QApplication()' /usr/bin/ld: main.o: in function `main': main.cpp:(.text.startup+0x2b): undefined reference to `QApplication::QApplication(int&, char**, int)' /usr/bin/ld: main.cpp:(.text.startup+0x37): undefined reference to `QWidget::QWidget(QWidget*, QFlags<Qt::WindowType>)' /usr/bin/ld: main.cpp:(.text.startup+0x4e): undefined reference to `QLineEdit::QLineEdit(QWidget*)' /usr/bin/ld: main.cpp:(.text.startup+0x67): undefined reference to `QLabel::QLabel(QWidget*, QFlags<Qt::WindowType>)' /usr/bin/ld: main.cpp:(.text.startup+0x7c): undefined reference to `QVBoxLayout::QVBoxLayout()' /usr/bin/ld: main.cpp:(.text.startup+0x8b): undefined reference to `QBoxLayout::addWidget(QWidget*, int, QFlags<Qt::AlignmentFlag>)' /usr/bin/ld: main.cpp:(.text.startup+0x9a): undefined reference to `QBoxLayout::addWidget(QWidget*, int, QFlags<Qt::AlignmentFlag>)' /usr/bin/ld: main.cpp:(.text.startup+0xa5): undefined reference to `QWidget::setLayout(QLayout*)' /usr/bin/ld: main.cpp:(.text.startup+0xad): undefined reference to `QWidget::show()' /usr/bin/ld: main.cpp:(.text.startup+0xb2): undefined reference to `QApplication::exec()' /usr/bin/ld: main.cpp:(.text.startup+0xbc): undefined reference to `QWidget::~QWidget()' /usr/bin/ld: main.cpp:(.text.startup+0xc4): undefined reference to `QApplication::~QApplication()' collect2: error: ld returned 1 exit status make: *** [Makefile:142: build] Error 1
去掉头文件里的QtWidgets/前缀后,又出现头文件找不到的错误:
$ LC_ALL=C qmake -project; LC_ALL=C qmake; LC_ALL=C make g++ -c -pipe -O2 -Wall -Wextra -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I. -I. -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtGui -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I. -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -o main.o main.cpp main.cpp:1:10: fatal error: QApplication: No such file or directory 1 | #include <QApplication> | ^~~~~~~~~~~~~~ compilation terminated. make: *** [Makefile:364: main.o] Error 1
问题根源
Qt5把GUI组件拆分到了QtWidgets模块,而qmake -project自动生成的.pro文件默认只包含core和gui模块,没有包含widgets,导致:
- 链接时缺少QtWidgets库,找不到类的实现
- 编译时缺少QtWidgets的头文件路径,找不到简化写法的头文件
解决方法
1. 修改.pro文件
打开自动生成的项目.pro文件,添加widgets模块:
QT += widgets
修改后的.pro文件示例:
QT += core gui widgets TARGET = build TEMPLATE = app SOURCES += main.cpp
2. 调整头文件(可选)
添加QT += widgets后,两种头文件写法都可以正常工作:
- 保留原路径:
#include <QtWidgets/QApplication> - 简化写法:
#include <QApplication>(推荐,代码更简洁)
3. 重新编译
不需要重新生成项目文件,直接执行:
LC_ALL=C qmake; LC_ALL=C make
原理说明
添加QT += widgets后,qmake会自动:
- 将QtWidgets的头文件路径加入编译参数,解决头文件找不到的问题
- 将
libQt5Widgets.so加入链接参数,解决链接时的undefined reference错误
内容的提问来源于stack exchange,提问作者muggi




