You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

使用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文件默认只包含coregui模块,没有包含widgets,导致:

  1. 链接时缺少QtWidgets库,找不到类的实现
  2. 编译时缺少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

火山引擎 最新活动