【Qt】Qt 构建系统详解:qmake 入门到项目实战

Qt 构建系统详解:qmake 入门到项目实战

本文将系统介绍 Qt 构建工具 qmake 的用法,并通过一个完整的项目结构示例,帮助你掌握 .pro 文件编写、子项目管理、模块依赖等核心技能。


🧭 一、什么是 qmake?

qmake 是 Qt 提供的跨平台构建系统工具,它能将 .pro 文件(项目描述)转换为对应平台的构建脚本,如 Makefile 或 Visual Studio 工程文件。

✅ 主要作用:

  • 自动生成构建脚本,简化项目编译流程
  • 跨平台(支持 Windows / Linux / macOS)
  • 适用于中小型 Qt 项目,快速上手

🔁 常见使用流程:

qmake myapp.pro      # 生成 Makefile
make                 # 或 mingw32-make / nmake

📘 二、.pro 文件基础语法

1. 基本结构

在这里插入图片描述

TEMPLATE = app            # 类型:app 或 lib
TARGET = myapp            # 输出文件名
QT += core gui            # 使用的 Qt 模块
CONFIG += c++11           # 编译配置
SOURCES += main.cpp       # 源码文件
HEADERS += mainwindow.h
FORMS += mainwindow.ui    # UI 文件
RESOURCES += resources.qrc

2. 常用变量

变量名含义
QT指定使用的 Qt 模块(如 core, gui
CONFIG构建配置,如 debug, release, c++11
SOURCES源文件列表
HEADERS头文件列表
FORMSQt Designer 设计的 .ui 文件
RESOURCESQt 资源文件 .qrc
INCLUDEPATH额外的头文件搜索路径
LIBS链接外部库,如 -L-l
DEFINES添加宏定义

3. 条件语句(平台判断)

unix {
    LIBS += -lm
}
win32 {
    CONFIG += console
}

🧩 三、子项目管理(SUBDIRS)

大型项目通常包含多个模块,比如主程序和自定义库。我们可以使用 subdirs 模板组织它们。


🛠️ 四、完整项目结构实战

📁 项目结构

MyProject/
├── MyProject.pro        # 顶层项目文件
├── mylib/               # 自定义库
│   ├── mylib.pro
│   ├── mylib.h
│   └── mylib.cpp
└── mainapp/             # 主程序
    ├── mainapp.pro
    ├── main.cpp
    ├── mainwindow.h
    ├── mainwindow.cpp
    └── mainwindow.ui

🧷 1. 顶层文件 MyProject.pro

TEMPLATE = subdirs
SUBDIRS += mylib mainapp

mainapp.depends = mylib   # 指定构建顺序

🧷 2. mylib/mylib.pro(静态库)

TEMPLATE = lib
CONFIG += staticlib
TARGET = mylib

HEADERS += mylib.h
SOURCES += mylib.cpp

mylib.h

#ifndef MYLIB_H
#define MYLIB_H

#include <QString>

class MyLib
{
public:
    static QString getMessage();
};

#endif // MYLIB_H

mylib.cpp

#include "mylib.h"

QString MyLib::getMessage()
{
    return "Hello from MyLib!";
}

🧷 3. mainapp/mainapp.pro(主程序)

TEMPLATE = app
QT += core gui widgets
CONFIG += c++11
TARGET = mainapp

SOURCES += main.cpp \
           mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui

INCLUDEPATH += ../mylib
LIBS += -L../mylib -lmylib

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow w;
    w.show();
    return app.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class QLabel;

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    QLabel *label;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include <QLabel>
#include "mylib.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    label = new QLabel(MyLib::getMessage(), this);
    setCentralWidget(label);
}

MainWindow::~MainWindow() {}

mainwindow.ui

你可以使用 Qt Designer 可视化编辑此文件,也可以先跳过(不影响构建)。


🔨 五、构建步骤(命令行)

在项目根目录执行:

qmake MyProject.pro
make                 # Windows 可用 mingw32-make 或 nmake

🎯 六、qmake 与 CMake 对比

特性qmakeCMake(Qt 6 推荐)
学习曲线简单较复杂
项目规模适合中小型项目更适合大型项目
官方支持Qt 5 推荐使用Qt 6 起默认使用 CMake
功能扩展性限制多一些更强(模块化、测试集成等)

✅ 总结

  • qmake 是 Qt 提供的构建系统,简洁、易上手,是管理 Qt 项目的传统利器。
  • 熟练使用 .pro 文件可以大大提升项目维护效率。
  • 对于大型项目,建议使用 subdirs 管理模块。
  • Qt 6 官方已推荐使用 CMake,新项目可考虑迁移。

📎 附加建议

  • 可以借助 Qt Creator 编辑 .pro 文件并一键构建,开发体验更佳。
  • 如果你正在使用 CMake,也可以对照迁移这套结构,后续我也可以提供 CMake 版本的实现。

📘提问环节

❓TEMPLATE = subdirs 什么意思?

TEMPLATE = subdirs 是 Qt 的构建工具 qmake 中的一种特殊模板,表示:

这个 .pro 文件不是一个可执行程序或库,而是一个“项目集合”,用于组织和管理多个子项目(子模块)的构建。


🧩 它的用途是什么?

当你要管理多个 .pro 项目(比如主程序 + 自定义库),就可以用一个 subdirs 类型的 .pro 文件统一管理它们的构建顺序和依赖关系。


📁 举个例子

项目结构:

MyProject/
├── MyProject.pro        ← 这是 subdirs 项目
├── mylib/
│   └── mylib.pro
└── mainapp/
    └── mainapp.pro

MyProject.pro 内容:

TEMPLATE = subdirs       # 告诉 qmake:这是一个子项目集合
SUBDIRS += mylib mainapp # 包含两个子项目

mainapp.depends = mylib  # 设置依赖顺序(先构建 mylib,再构建 mainapp)

🧠 工作机制

  • qmake MyProject.pro 会读取所有列出的子项目并为它们分别生成 Makefile。
  • 构建时会 自动递归编译每一个子项目
  • 通过 xxx.depends = yyy 设置依赖顺序(例如主程序依赖库)。

✅ 常见 TEMPLATE 类型对比

TEMPLATE 类型用途
app构建一个可执行程序
lib构建一个静态或动态库(.a/.so/.lib/.dll)
subdirs管理多个 .pro 项目的集合

📌 总结

  • TEMPLATE = subdirs 通常出现在项目的顶层,用于组织多个子项目。
  • 它本身不包含代码,只是构建配置的集合。
  • 与 CMake 中的 add_subdirectory() 有相似之处。

❓为什么顶层 .pro 文件中 没有 TARGET

这是一个非常关键且容易混淆的问题,下面我来系统解释,因为:

当你使用 TEMPLATE = subdirs 时,顶层 .pro 文件本身不是一个编译目标,不会生成可执行文件或库文件,因此不需要也不能设置 TARGET


✅ 解释:

  • TEMPLATE = subdirs 表示:这个 .pro 文件只是一个项目容器,用来组织和管理子项目的构建流程。
  • 它的职责是告诉 qmake:我要构建哪些子项目,它们的依赖关系是什么。
  • 子项目才是真正参与构建(生成目标文件)的单元。

🧱 对比不同 TEMPLATE

TEMPLATE 类型是否需要 TARGET说明
app✅ 是表示要生成一个可执行文件,需要指定名称
lib✅ 是表示要生成一个静态库或动态库
subdirs❌ 否不生成实际构建产物,仅组织子项目

📁 示例补充

# MyProject.pro
TEMPLATE = subdirs
SUBDIRS += mylib mainapp
mainapp.depends = mylib

你看到这里没有:

TARGET = ...

原因是:MyProject.pro 不是一个“要编译的项目”,而是“告诉 qmake 去编译哪些项目”


✅ 小结

  • subdirs 类型的 .pro 文件不需要 TARGET
  • 它只是一个组织者,控制构建顺序和包含的模块。
  • 只有真正的可执行程序或库项目,才需要指定 TARGET

❓子项目中为啥TARGET的名称要和文件夹同名?

这是一个非常好的问题,涉及到 qmake 中的 TARGET 变量含义模块组织逻辑,我们来仔细说明:


TARGET 的本质含义

.pro 文件中:

TARGET = something

表示 生成的可执行文件名或库文件名,不直接等于目录名。


🔎 示例对比说明

设想我们有如下结构:

MyProject/
├── mylib/
│   ├── mylib.pro   ← 这里 TARGET = mylib
├── mainapp/
│   ├── mainapp.pro ← 这里 TARGET = mainapp

虽然子项目文件夹分别叫做 mylibmainapp,但你可以自由设置 TARGET 为任何你想要的名字,比如:

# mylib.pro
TARGET = my_custom_library_name

# mainapp.pro
TARGET = awesome_gui_app

构建完成后:

  • 在 Linux:会生成 libmy_custom_library_name.a(静态库)和 awesome_gui_app(可执行文件)
  • 在 Windows:生成 my_custom_library_name.libawesome_gui_app.exe

🤔 那为什么很多人让 TARGET = 文件夹名

这是因为:

  • 文件夹名和 TARGET 保持一致可以 减少认知负担
  • 例如 mylib/TARGET = mylib,容易管理产物、日志和代码
  • 并非语法规定,而是 一种约定俗成的习惯

📌 总结

含义
TARGET表示“构建产物的名称”(可执行文件或库名)
子目录名TARGET 可以相同,也可以不同
建议做法建议保持一致,利于组织与维护

🎯 小技巧

查看帮助文档的时候,需要添加啥,文档中也会给出详细内容。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code bean

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值