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

news2025/5/14 0:02:29

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 可以相同,也可以不同
建议做法建议保持一致,利于组织与维护

🎯 小技巧

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2375002.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Zabbix Proxy分布式监控实战:从安装到配置全解析》

注意&#xff1a;实验所需的zabbix服务器的搭建可参考博客 zabbix 的docker安装_docker安装zabbix-CSDN博客 1.1 实验介绍 1.1.1 实验目的 本实验旨在搭建一个基于Zabbix的监控系统&#xff0c;通过安装和配置Zabbix Proxy、MySQL数据库以及Zabbix Agent&#xff0c;实现分…

华为配置篇-RSTP/MSTP实验

MSTP 一、简介二、常用命令总结三、实验 一、简介 RSTP&#xff08;快速生成树协议&#xff09;​ RSTP&#xff08;Rapid Spanning Tree Protocol&#xff09;是 STP 的改进版本&#xff0c;基于 ​​IEEE 802.1w 标准​​&#xff0c;核心目标是解决传统 STP 收敛速度慢的问…

git如何将本地 dev 分支与远程 dev 分支同步

要让本地 dev 分支与远程 dev 分支完全同步&#xff08;丢弃本地多余的提交记录&#xff09;&#xff0c;可以按照以下步骤操作&#xff1a; 1. ​​获取远程最新状态​ git fetch origin dev # 拉取远程 dev 分支的最新提交&#xff0c;但不会修改本地代码 IDEA中点击fetc…

Unity基础学习(九)输入系统全解析:鼠标、键盘与轴控制

目录 一、Input类 1. 鼠标输入 2. 键盘输入 3. 默认轴输入 &#xff08;1&#xff09; 基础参数 &#xff08;2&#xff09;按键绑定参数 &#xff08;3&#xff09;输入响应参数 &#xff08;4&#xff09;输入类型与设备参数 &#xff08;5&#xff09;不同类型轴的参…

QT:获取软件界面窗口的尺寸大小2025.5.8

在Windows系统中&#xff0c;获取软件界面窗口的尺寸大小可以通过多种方法实现&#xff0c;以下是基于不同场景的详细解决方案&#xff1a; 方法1&#xff1a;使用Windows API获取窗口尺寸 适用于获取外部应用程序窗口的尺寸&#xff08;如记事本、计算器等&#xff09;。 步…

【ML-Agents】ML-Agents示例项目导入unity报错解决

最近在跑ML-Agents的示例代码&#xff0c;无奈往unity中导入项目后&#xff0c;就出现报错。本文简要描述了各个报错的解决方法。 文章目录 一、error CS0234: The type or namespace name InputSystem does not exist in the namespace UnityEngine (are you missing an assem…

Transformer Decoder-Only 参数量计算

Transformer 的 Decoder-Only 架构&#xff08;如 GPT 系列模型&#xff09;是当前大语言模型的主流架构&#xff0c;其参数量主要由以下几个部分组成&#xff1a; 嵌入层&#xff08;Embedding Layer&#xff09;自注意力层&#xff08;Self-Attention Layers&#xff09;前馈…

uni-app 中的条件编译与跨端兼容

uni-app 为了实现一套代码编译到多个平台&#xff08;包括小程序&#xff0c;App&#xff0c;H5 等&#xff09;&#xff0c;引入了条件编译机制。 通过条件编译&#xff0c;我们可以针对不同的平台编写特定的代码&#xff0c;从而实现跨端兼容。 一、条件编译的作用 平台差异…

Unity接入SDK之修改Unity启动页面

原理就是在Android Studio新建Activity继承UnityPlayerActivity&#xff0c;然后再Unity中修改启动页面。 一&#xff0c;Android Studio篇 首先新建一个项目&#xff0c; 新建完成之后基于新建的项目新建一个module&#xff0c;选择为Android Library类型 新建的Library再目…

yarn workspace使用指南

作用 Yarn workspace 是 Yarn 包管理工具中的一个功能&#xff0c;主要用于管理多包项目&#xff08;monorepo&#xff09;。它的主要作用如下&#xff1a; 支持多包结构&#xff1a;允许在一个仓库中管理多个独立的包或项目。项目间依赖管理&#xff1a;方便地在不同包之间添…

VUE el-select下拉框动态设置禁用,删除后恢复可选择

场景&#xff1a;点击新增添加按钮&#xff0c;列表table会新增一条包含下拉菜单的数据&#xff0c;如果其中任何一个下拉框选择了某个值&#xff0c;那么新增的下拉菜单的选项中该值是禁用状态&#xff0c;只能选择其他未被选中过的值。点击删除按钮后&#xff0c;已禁用的选项…

FPGA----基于ALINX提供的debian实现TCF

引言:接上问,我们使用自制的image.ub和boot.bin以及ALINX提供的debian8根文件系统,构建了petalinux,但是经测试,该文件系统无法启用TCF服务,即无法与Xilinx SDK建立连接,那么我们应该如何解决? FPGA----基于ZYNQ 7020实现定制化的EPICS通信系统-CSDN博客文章浏览阅读4…

木马查杀篇—Opcode提取

【前言】 介绍Opcode的提取方法&#xff0c;并探讨多种机器学习算法在Webshell检测中的应用&#xff0c;理解如何在实际项目中应用Opcode进行高效的Webshell检测。 Ⅰ 基本概念 Opcode&#xff1a;计算机指令的一部分&#xff0c;也叫字节码&#xff0c;一个php文件可以抽取出…

国产化Excel处理控件Spire.XLS系列教程:如何通过 C# 删除 Excel 工作表中的筛选器

在 Excel 文件中&#xff0c;筛选器&#xff08;Filter&#xff09;是一个常用的数据处理工具&#xff0c;可以帮助用户快速按条件筛选数据行。但在数据整理完成、导出、共享或打印之前&#xff0c;往往需要 删除 Excel 工作表中的筛选器&#xff0c;移除列标题中的下拉筛选按钮…

[sklearn] 特征工程

一.字典数据抽取 def dictvec():"""字典数据抽取:return: None"""# 实例化# sparse改为True,输出的是每个不为零位置的坐标&#xff0c;稀疏矩阵可以节省存储空间dict DictVectorizer(sparseFalse) #矩阵中存在大量的0&#xff0c;sparse存储只…

CI/CD与DevOps流程流程简述(提供思路)

一 CI/CD流程详解&#xff1a;代码集成、测试与发布部署 引言 在软件开发的世界里&#xff0c;CI/CD&#xff08;持续集成/持续交付&#xff09;就像是一套精密的流水线&#xff0c;确保代码从开发到上线的整个过程高效、稳定。我作为一名资深的软件工程师&#xff0c;接下来…

S7-1500——零基础入门1、工业编程基本概念

工业编程基本概念 一,数制与基本数据类型二,数字量信号三,模拟量信号一,数制与基本数据类型 本节主要内容 类别内容主题数制与基本数据类型数制讲解十进制、十六进制、二进制及其进位规则;基数、位权概念数据类型介绍PLC 使用的数据类型:未序列数据类型(bit、byte、wor…

六、快速启动框架:SpringBoot3实战

六、快速启动框架&#xff1a;SpringBoot3实战 目录 一、SpringBoot3介绍 1.1 SpringBoot3简介1.2 系统要求1.3 快速入门1.4 入门总结 二、SpringBoot3配置文件 2.1 统一配置管理概述2.2 属性配置文件使用2.3 YAML配置文件使用2.4 批量配置文件注入2.5 多环境配置和使用 三、…

万兴PDF-PDFelement v11.4.13.3417

万兴PDF专家(Wondershare PDFelement)是一款国产PDF文档全方位解决方案.万兴PDF编辑器软件万兴PDF中文版,专注于PDF的创建,编辑,转换,签名,压缩,合并,比较等功能.万兴PDF专业版PDF编辑软件,以简约风格及强大的功能在国外名声大噪,除了传统功能外,还提供OCR扫描,表格识别,创建笔…

机器学习-无量纲化与特征降维(一)

一.无量纲化-预处理 无量纲&#xff0c;即没有单位的数据 无量纲化包括"归一化"和"标准化"&#xff0c;这样做有什么用呢&#xff1f;假设用欧式距离计算一个公司员工之间的差距&#xff0c;有身高&#xff08;m&#xff09;、体重&#xff08;kg&#x…