发生背景
为了让定义(widget/mainwindow.hpp
)和实现(widget/mainwindow.cpp
)在同一栏里,作死把他们全部放到QMake的HEADERS
变量里,然后报了莫名其妙的错……
错误信息
作者为了偷懒简化开发,使用Qt+Web混合开发,用到了QWebEngine
,被绑上了MSVC 2019。
MSVC很“友好”地把错误信息改成了中文:
main.obj:-1: error: LNK2019: 无法解析的外部符号 "public: __cdecl dm::MainWindow::MainWindow(class QWidget *)" (??0MainWindow@dm@@QEAA@PEAVQWidget@@@Z),函数 main 中引用了该符号
moc_mainwindow.obj:-1: error: LNK2001: 无法解析的外部符号 "public: __cdecl dm::MainWindow::MainWindow(class QWidget *)" (??0MainWindow@dm@@QEAA@PEAVQWidget@@@Z)
debug\dev-mini.exe:-1: error: LNK1120: 1 个无法解析的外部命令
相关代码
dev-mini.pro
:
QT += \
core \
gui \
widgets # \
# webenginecore \
# webenginewidgets
CONFIG += c++17
SOURCES += \
main.cpp
HEADERS += \
widget/mainwindow.hpp \
widget/mainwindow.cpp
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
widget/mainwindow.hpp
(缩减版):
#ifndef DM_WIDGET_MAINWINDOW
#define DM_WIDGET_MAINWINDOW
#include <QMainWindow>
#include <QSize>
namespace dm {
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
} // namespace dm
#endif // macro DM_WIDGET_MAINWINDOW
widget/mainwindow.cpp
(缩减版):
#include "mainwindow.hpp"
namespace dm {
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {}
MainWindow::~MainWindow() {}
} // namespace dm
解决方案
把dev-mini.pro
里的widget/mainwindow.cpp
移到SOURCES
里。
git diff结果:
@@ -6,11 +6,11 @@ QT += \
CONFIG += c++17
SOURCES += \
- main.cpp
+ main.cpp \
+ widget/mainwindow.cpp
HEADERS += \
- widget/mainwindow.hpp \
- widget/mainwindow.cpp
+ widget/mainwindow.hpp
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
发生原因
(推测)
玄学原因,改正后编译没问题,再改回错的居然也没问题了!这种幻象能持续2次编译。
用CMake编译时,查到了编译单元相关的。QMake应该也是差不多,实现只能作为Source File运行时生效一次,如果当作Header File处理就会多次运行。