您现在的位置是:首页 >技术杂谈 >C/C++笔记-使用Qt的UI文件时make流程网站首页技术杂谈
C/C++笔记-使用Qt的UI文件时make流程
首先创建如下项目:
QtWidgetMakfileDemo.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES +=
main.cpp
Widget.cpp
HEADERS +=
Widget.h
FORMS +=
Widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
main.cpp
#include "Widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
Widget.cpp
#include "Widget.h"
#include "ui_Widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
ui是空的。
此时运行命令qmake,然后再make,打印如下:
/opt/Qt5.5.1/5.5/gcc_64/bin/uic Widget.ui -o ui_Widget.h
g++ -c -pipe -O2 -std=c++0x -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I/opt/Qt5.5.1/5.5/gcc_64/include -I/opt/Qt5.5.1/5.5/gcc_64/include/QtWidgets -I/opt/Qt5.5.1/5.5/gcc_64/include/QtGui -I/opt/Qt5.5.1/5.5/gcc_64/include/QtCore -I. -I. -I/opt/Qt5.5.1/5.5/gcc_64/mkspecs/linux-g++ -o main.o main.cpp
g++ -c -pipe -O2 -std=c++0x -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I/opt/Qt5.5.1/5.5/gcc_64/include -I/opt/Qt5.5.1/5.5/gcc_64/include/QtWidgets -I/opt/Qt5.5.1/5.5/gcc_64/include/QtGui -I/opt/Qt5.5.1/5.5/gcc_64/include/QtCore -I. -I. -I/opt/Qt5.5.1/5.5/gcc_64/mkspecs/linux-g++ -o Widget.o Widget.cpp
/opt/Qt5.5.1/5.5/gcc_64/bin/moc -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I/opt/Qt5.5.1/5.5/gcc_64/mkspecs/linux-g++ -I/root/CffPro/QtWidgetMakefileDemo -I/opt/Qt5.5.1/5.5/gcc_64/include -I/opt/Qt5.5.1/5.5/gcc_64/include/QtWidgets -I/opt/Qt5.5.1/5.5/gcc_64/include/QtGui -I/opt/Qt5.5.1/5.5/gcc_64/include/QtCore Widget.h -o moc_Widget.cpp
g++ -c -pipe -O2 -std=c++0x -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I/opt/Qt5.5.1/5.5/gcc_64/include -I/opt/Qt5.5.1/5.5/gcc_64/include/QtWidgets -I/opt/Qt5.5.1/5.5/gcc_64/include/QtGui -I/opt/Qt5.5.1/5.5/gcc_64/include/QtCore -I. -I. -I/opt/Qt5.5.1/5.5/gcc_64/mkspecs/linux-g++ -o moc_Widget.o moc_Widget.cpp
g++ -Wl,-O1 -Wl,-rpath,/opt/Qt5.5.1/5.5/gcc_64 -Wl,-rpath,/opt/Qt5.5.1/5.5/gcc_64/lib -o QtWidgetMakefileDemo main.o Widget.o moc_Widget.o -L/opt/Qt5.5.1/5.5/gcc_64/lib -lQt5Widgets -L/usr/lib64 -lQt5Gui -lQt5Core -lGL -lpthread
整体逻辑是这样的:
①将ui文件生成对应的C++的.h文件;
②将.cpp编译成.o文件;
③将带有Q_OBJECT和继承了QObject的类生成对应的moc_xxx.cpp文件;
④编译moc文件,生成对应的.o文件;
⑤链接所有.o文件以及动态库,生成可执行程序;
下面来分析下每个步骤:
①
/opt/Qt5.5.1/5.5/gcc_64/bin/uic Widget.ui -o ui_Widget.h
各个参数分析:
调用uic程序,将ui文件生成对应的ui_widget.h文件;
②
g++ -c -pipe -O2 -std=c++0x -Wall -W
-D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
-I.
-I/opt/Qt5.5.1/5.5/gcc_64/include
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtWidgets
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtGui
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtCore
-I.
-I.
-I/opt/Qt5.5.1/5.5/gcc_64/mkspecs/linux-g++
-o main.o main.cpp
各个参数分析:
-c:生成文件;
-pipe:在不同的编译阶段使用管道替代临时文件;
-O2:optimization优化,比-O高一级的优化,编译优化,具体优化哪些内容,在此不说明;
-std=c++0x:指定c++版本;
-Wall:编译后显示所有告警;
-W:默认报警也要显示;
-D_REENTRANT:它会对部分函数重新定义它们的可安全重入的版本;
-fPIC:用于生成位置无关的代码(Position-Independent-Code);
-DQT_NO_DEBUG:这个没查到,但看名称差不多能猜到是QT不使用Debug;
-DQT_CORE_LIB:这个没查到,但看名称差不多能猜到是QT核心库;
-DQT_GUI_LIB:这个没查到,但看名称差不多能猜到是QT的图形GUI库;
-I:表示包含的include文件;
-o:表示编译成object文件。
③
g++ -c -pipe -O2 -std=c++0x -Wall -W
-D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
-I.
-I/opt/Qt5.5.1/5.5/gcc_64/include
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtWidgets
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtGui
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtCore
-I.
-I.
-I/opt/Qt5.5.1/5.5/gcc_64/mkspecs/linux-g++
-o Widget.o Widget.cpp
各个参数分析:
和②步一样。
④
/opt/Qt5.5.1/5.5/gcc_64/bin/moc -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
-I/opt/Qt5.5.1/5.5/gcc_64/mkspecs/linux-g++
-I/root/CffPro/QtWidgetMakefileDemo
-I/opt/Qt5.5.1/5.5/gcc_64/include
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtWidgets
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtGui
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtCore Widget.h
-o moc_Widget.cpp
各个参数分析:
和②步一样。
从中发现了个有意思的,以前都以为moc_xxx.cpp文件是通过对于的.h和.cpp使用moc联合生成的,现在发现他仅仅是使用对应的.h文件生成。具体moc_Wiget.cpp文件的内容在后面说明。
⑤
g++ -c -pipe -O2 -std=c++0x -Wall -W -D_REENTRANT
-fPIC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
-I.
-I/opt/Qt5.5.1/5.5/gcc_64/include
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtWidgets
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtGui
-I/opt/Qt5.5.1/5.5/gcc_64/include/QtCore
-I.
-I.
-I/opt/Qt5.5.1/5.5/gcc_64/mkspecs/linux-g++
-o moc_Widget.o moc_Widget.cpp
各个参数分析:
和②步一样。
这里就很明确的发现了,在编译阶段,使用了Q_OBJECT和继承了QObject的类会编译时会生成2个object文件,分别是原始object和带moc的object文件。
⑥
g++ -Wl,-O1 -Wl,-rpath,/opt/Qt5.5.1/5.5/gcc_64
-Wl,-rpath,/opt/Qt5.5.1/5.5/gcc_64/lib
-o QtWidgetMakefileDemo main.o Widget.o moc_Widget.o
-L/opt/Qt5.5.1/5.5/gcc_64/lib
-lQt5Widgets
-L/usr/lib64 -lQt5Gui -lQt5Core -lGL -lpthread
各个参数分析:
-Wl, -rpath:①用于编译时指定间接引用的库位置,作用同-Wl,-rpath-link;②用于运行时指定所有引用库的位置,作用同修改环境变量(LD_LIBRARY_PATH),并且库路径引用优先级高于LD_LIBRARY_PATH;
-L:Link链接路径;
-l:链接到哪个so文件。