Qt构建工具QBS之一 ——从一个简单的工程开始

在这篇文章中通过在一个简单的工程初步了解 Qbs 是怎么构建一个工程的, 涉及到的语言项有 Product, Application, CppApplication, Depends, FileTagger, Group. 涉及到的模块有 cpp 和 qbs 模块.

创建一个简单的工程

按下列步骤创建一个简单的工程, 本系列文章都将基于这个工程来做讲解实验.

  1. 打开 Qt Creator
  2. 单击菜单 [文件]->[新建文件或项目] 打开对话框
  3. 在左边项目下面选择 [Non-Qt Project], 中间选择 [Plain C++ Application], 单击按钮 [Choose…]
  4. 名称: 输入 QbsDemo, 单击按钮 [下一步]
  5. 构建系统选择 Qbs, [下一步]
  6. [下一步]
  7. [完成]
  8. 构建运行. 正常的情况应该会在控制台中输出 Hello World!

Product 及其派生出的 CppApplication 和 Application.

打开 QbsDemo.qbs 文件, 可以看到内容如下

import qbs

CppApplication {
    type: "application" // To suppress bundle generation on Mac
    consoleApplication: true
    files: "main.cpp"

    Group {     // Properties for the produced executable
        fileTagsFilter: product.type
        qbs.install: true
    }
}

对于非 Mac 平台上, 第 4 行的 type: "application" // To suppress bundle generation on Mac 是不需要的. 因为 CppApplication 派生自 Application, 而 Application 已经隐含了 type: "application" 了. 为了更清晰些, 删掉第4行, 构建运行, 可以验证没什么影响.

由上一篇文章我们已经知道 CppApplication 派生自 Application. 其等效于 Application, 加上对 “cpp” 模块的依赖.

将 QbsDemo.qbs 中的内容改成如下, 可以验证之(第 4 行加入了 cpp 模块依赖)

import qbs

Application {
    Depends { name: "cpp" }

    consoleApplication: true
    files: "main.cpp"

    Group {     // Properties for the produced executable
        fileTagsFilter: product.type
        qbs.install: true
    }
}

注: 可以先去掉第 4 行的 Depends { name: "cpp" }, 构建运行, 发现无法运行, 因为没有生成可执行程序.

同样再看派生了 Application 的 Product 项. 同样上面的代码可以改成(第 4 行指定了类型为 “application”)

import qbs

Product {    
    type: "application"
    Depends { name: "cpp" }

    consoleApplication: true
    files: "main.cpp"

    Group {     // Properties for the produced executable
        fileTagsFilter: product.type
        qbs.install: true
    }
}

注: 同样可以先去掉第 4 行的 type: "application", 构建后也无法运行

所以上一篇文章列出 30 个语言项, Product 及其派生的项可以看成一个, 剩下就 10 几个语言项了, 而一般能用到的就更少了. 所以 Qbs 也还是挺简单的.


属性

再看代码中 type: "application"consoleApplication: true 这样的键值对语句. 这是是相应语言项/模块的属性和属性值. 这里的几个属性都是 Product 的属性值, 其中:

  • type 指出了该 Product 是一个可执行程序. 常用的类型还有 dynamiclibrary(动态库), staticlibrary 静态库.
  • consoleApplication 指出了是否是一个控制台程序
  • files 则列出了源文件(不仅仅只是 C++头文件和源文件, 以后会看到)

以后会见到更多各种语言项/模块的属性, 完整的属性和属性用法说明参加相关语言项/模块的各自文档.


Depands 项

Depends 就是添加依赖模块, 通过 name 属性指定要引入模块的名称, 如上面的 “cpp” 模块是 Qbs 自带的预定义模块, 用来处理 C/C++, Objective-C/C++ 源码. 有点类似于 qmake 中 Qt += core gui, qmake 通过这样的方式添加了对 core, gui 模块的依赖.

目前对模块的理解, 只需有个大致的理解即可, 后面会通过学习自定义模块来进一步理解模块.


FileTagger 项

现在来先看一个上面代码未出现过的 FileTagger 项. 为什么先讲这个, 基于三个原因:

  1. 这个语言项很简单, 只有 2 个属性, 是所有语言项中属性最少
  2. 没有理解这个语言项, 影响其它好几个语言项的理解, 包括上面已经出现过的 Group 项
  3. 理解了这个语言项, 能或多或少对 Qbs 整个运行机制有点模糊的理解.

FileTagger 的两个属性: patterns 和 fileTags, 前者指定了匹配模式, 后者为文件标记名.

先不对 FileTagger 作更详细的讲解, 我们先来做几个实验, 做实验之前想几个问题:

  • Qbs 为什么会认为 main.cpp 是 C++ 源代码, 而不是一个资源文件之类的?
  • 是因为它的扩展名 .cpp 吗?
  • 把它的扩展名改成别的, 还能成功构建出 Hello World程序吗?
  • 如果不能构建出来, 那么在扩展名已改的情况下, 如何让 Qbs 依然认为这个文件是 C++ 源代码呢?

现在把 main.cpp 的文件名改成 main.src, 将 QbsDemo.qbs 中的内容修改成:

import qbs

Product {    
    type: "application"
    Depends { name: "cpp" }

    consoleApplication: true
    files: "main.src"

    Group {     // Properties for the produced executable
        fileTagsFilter: product.type
        qbs.install: true
    }
}

如上, 修改的地方在第 8 行, main.cpp 改成了 main.src了.

构建运行, 发现没有生产可执行程序.

现在请出 FileTagger, 将上面代码修改成:

import qbs

Product {    
    type: "application"
    Depends { name: "cpp" }

    consoleApplication: true
    files: "main.src"

    FileTagger {
        patterns: "main.src"
        fileTags: "cpp"
    }

    Group {     // Properties for the produced executable
        fileTagsFilter: product.type
        qbs.install: true
    }
}

构建运行, Hello World又出来了.

再将 mian.src 文件名改成 main1.src, QbsDemo.qbs 文件中的 files: “main.src” 改成 files: “main1.src”, 注意: 这里 patterns: “main.src” 暂时不改.

构建运行, 不行, 将 patterns: “main.src” 改成 patterns: “main1.src” 则又可以了.

还有一种解决方案则是将改成 patterns: “*.src”, 也就是匹配模式支持通配符, 用来表示所有扩展名为 src 的文件都将视为 C++ 源文件.

fileTags: “cpp” 这里的fileTags为什么是 “cpp”, 可以是别的吗? 答案是一般情况是不行的. 因为这是由 Depends { name: “cpp” } 引入的 cpp 模块决定的(注意是由这个模块决定的, 和 name: “cpp” 中的那个 cpp 是没什么直接联系的). 我们打开 Qbs 自带的文件 CppModule.qbs (cpp 模块就是在这个文件中定义的), 看看 cpp 这个标记名是怎么定义的:

FileTagger {
    patterns: ["*.C", "*.cpp", "*.cxx", "*.c++", "*.cc"]
    fileTags: ["cpp"]
}

和我们刚才定义的形式有点不一样, 我们没这个 [], 说明这两个属性是一个列表, 只有一个值时这个[]可以省略.

这里我们可以看出 cpp 模块认为扩展名为 C/cpp/cxx/c++/cc 的文件是 C++ 源码.

Group 项

Group 项是将一组在某些行为上是一样的文件组合成一组. 比如某些将安装到同一目录下的文件, 某些 Windows 平台上需要的文件, 某些 Linux 平台上需要的文件.

注意: Group 分组的对象是文件, 如果 Group 项内没有指定有效文件, 那么这个 Group 是会被忽略的.

Group 项指定文件可以用 files 属性或 fileTagsFilter 属性, 这两个属性是互斥的, 只能用其一.

files: 指定文件列表, 如同 Product 项中的 files.

fileTagsFilter: 指定文件标记名, 通过标记名来匹配文件. 标记名就是上文那样使用 FileTagger 定义出来的.

回到 QbsDemo.qbs 中 Group 项

Group {     // Properties for the produced executable
    fileTagsFilter: product.type
    qbs.install: true
}

这里的 Group 指定文件的方式就是用文件标记名, product.type 就是 Product 项的 type 的属性值, 在这里等效于 fileTagsFilter: “application”. 另外说一句, Product 内的任何一个子项都可以使用 product.属性名 的方式访问 Product 项的属性值.

qbs.install: true 表明这些文件是用于安装的. qbs 是一个模块, 在每个产品中, 都会隐含这个模块的依赖. 这个模块包含了一些常用的基本属性. 那么文件安装到哪呢? 安装到 qbs.installDir 指定的位置, 这里没有指定则默认安装到构建目录下的 install-root 目录下. 更多关于 qbs 模块的信息, 可以参考文档中关于 qbs 模块的说明.

可以去 install-root 目录下找找, 应该有一个 QbsDemo.exe.

现在假如我们需要把 C++ 源文件也安装过去(这只是个实验, 现实中这么做应该没什么太大的意义), 我们可以这么做:

import qbs

Product {
    type: "application"
    Depends { name: "cpp" }

    consoleApplication: true
    files: "main1.src"

    FileTagger {
        patterns: "*.src"
        fileTags: "cpp"
    }

    Group {     // Properties for the produced executable
        fileTagsFilter: [product.type[0], "cpp"] // product.type
        qbs.install: true
    }
}

如上, 我们在fileTagsFilter, 又加入了一个标记名 “cpp”, 注意: type后面那个[0], 因为 product.type 实际是一个列表. 也可以写成 fileTagsFilter: product.type.concat(“cpp”).

构建后, 去 install-root 目录下除了 QbsDemo.exe 外, 应该还有一个 main1.src.

一个小练习:

创建一个工程, 其有两个 C++ 源文件, 一个为 main1.cpp, 一个为 main2.cpp, 下面两者环境选一个即可

  1. 分别生成一个32位程序和一个64位程序, 如果检查到环境为 x86 架构使用 main1.cpp 输出 Hello X86, 如果是 x64 架构使用 mian2.cpp 输出 Hello X64. (这个环境需要装32bit和64bit两个Qt)
  2. 根据平台, 如果是 Windows 平台使用 main1.cpp 输出 Hello Windows, 如果是 Linux 平台使用 main2.cpp 输出 Hello Linux. (这个环境需要两个操作系统)

使用 Group 来实现怎么来选择对应的源文件, 两个环境根据自身哪个方便来选择, 也可以自己设计个实验做.

结尾

这篇文章初步认识了 QBS, 其实很 qmake 的 pro 文件差不多, 也都是由 Qt Creator 自动生成的, 对于使用惯了 qmake 的人来说, 可能里面的东西不多, 但是还是有种不熟悉的感觉. 其实你到后面, 你会发现, 从某种角度来说 QBS 比 qmake 更简单.

比如, qmake 的 pro 文件中有 HEADERS 来指定头文件, SOURCES 来指定 C++ 源文件, FORMS 指定 ui 文件, RESOURCES 指定 qrc 文件, RC_FILE 指定微软的资源文件. 麻烦不? 这个在 QBS 中就简单多了, files 一个属性全包. 全自动分类. 而且 QBS 也是支持直接在 IDE 中删除添加文件的, 怕需要手动写人不用担心了.

也许有人文, 都是自动添加的为什么你就说 QBS 更简单呢? 反正不用手写. 其实很多情况手写是避免不了的, 比如上面提到的那个练习.

下一篇文章, 会通过一个比较实用的例子, 也更能展现 QBS 强大的地方.

最后把工程恢复到原始状态, 为下一篇文章做准备.
即把 main1.src 重命名回 main.cpp, QbsDemo.qbs 恢复为:

import qbs

CppApplication {
    type: "application" // To suppress bundle generation on Mac
    consoleApplication: true
    files: "main.cpp"

    Group {     // Properties for the produced executable
        fileTagsFilter: product.type
        qbs.install: true
    }
}

转载请加上原文链接, 并保证文章的完整性. 鉴于自己的能力可能有表达失当或者错误的地方, 希望大家包含. 如您能提出意见或建议, 本人不甚感激. li_wey AT 163.com

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Qt是一款跨平台的C++应用程序开发框架,Qt提供了一套完整的工具集合来编译和构建应用程序。下面是一些常见的Qt6源码编译工具集合: 1. C++编译器:Qt6的源码是用C++编写的,因此需要使用C++编译器来将源码编译成可执行的二进制文件。常见的C++编译器有GCC、Clang和MSVC等。 2. qmake:qmake是Qt的默认构建系统工具。它能够根据项目文件(.pro)生成Makefile,并提供了一些便捷的方式来编译、链接和部署应用程序。 3. cmake:cmake是另外一种流行的跨平台构建系统工具Qt6支持使用cmake作为替代qmake的构建工具。cmake可以生成适用于不同操作系统和编译器的构建文件。 4. ninja:ninja是一个快速且轻量级的构建工具,被广泛用于Qt的源码编译。它能够更高效地并行处理编译任务,并生成可执行文件。 5. Qt Creator:Qt Creator是一款集成开发环境(IDE),专门用于Qt应用程序的开发。它集成了Qt的编译工具,并提供了可视化的界面来管理项目、编辑代码和调试应用程序。 6. Qt Installer Framework:如果需要将编译好的Qt应用程序打包成安装包,则可以使用Qt Installer Framework。它提供了一套用于构建安装程序的工具和界面,可以方便地进行应用程序的部署和分发。 以上是一些常见的Qt6源码编译工具集合,根据实际需要和开发环境的要求,可以选择合适的工具来完成Qt应用程序的编译和构建。 ### 回答2: Qt是一款流行的跨平台C++应用程序开发框架,Qt 6 是其最新版本。为了编译Qt 6的源码,我们需要使用一系列的工具集合。 首先,我们需要确保我们的系统上安装了C++编译器。常见的C++编译器有GCC、Clang和MSVC。根据不同的平台和操作系统,我们可以选择适合的编译器。确保编译器安装正确并可以通过命令行调用。 其次,为了构建Qt 6源码,我们需要使用一个建构工具Qt提供了一个名为qmake的构建工具。qmake是一个用于构建Qt工程工具,它可以自动生成相应的构建脚本(Makefile或其他)来编译和链接我们的代码。在Qt 6中,qmake已经被一个新的构建系统qbs替代,但我们仍然可以使用qmake来编译Qt 6的源码。确保安装了Qt工具包并可以通过命令行调用qmake。 另外,为了成功编译Qt 6源码,我们需要安装一些依赖项。Qt 6有一些核心的依赖项,如OpenGL、DBus和SQLite。我们需要确保这些依赖项已经正确地安装在系统上,并配置好相应的开发环境变量。 最后,Qt提供了一个名为Qt Creator的集成开发环境(IDE),它是一个方便的工具,可以帮助我们管理和编译Qt工程。虽然Qt Creator并不是编译Qt 6源码所必需的,但它提供了许多便利的功能,如代码自动完成、调试工具等。如果我们习惯使用IDE来开发Qt应用程序,建议安装并使用Qt Creator。 总之,编译Qt 6的源码需要使用C++编译器、构建工具(如qmake),确保安装了必要的依赖项,并可以使用Qt Creator作为开发环境。这些工具的正确配置和使用可以帮助我们成功地构建和编译Qt 6应用程序。 ### 回答3: Qt 6 是一个跨平台的应用程序开发框架,它提供了许多工具来帮助开发者编译和构建他们的项目。以下是一些常用的 Qt 6 源码编译工具集合: 1. CMake:Qt 6 的源码使用 CMake 构建系统管理,CMake 是一个跨平台的开源构建工具。使用 CMake,开发者可以配置源码编译过程中的各种参数,包括编译器选项、库依赖项等等。 2. Qt Creator:Qt 6 提供了 Qt Creator 集成开发环境,它是一个功能强大的跨平台 IDE,专为 Qt 应用程序开发而设计。Qt Creator 提供了丰富的源码编辑、调试和构建工具,使开发者能够方便地编译和调试他们的项目。 3. qmake:qmake 是一个用于构建 Qt 项目的命令行工具。在 Qt 6 中,开发者可以使用 qmake 创建项目文件(.pro)来描述项目的构建过程,然后使用 qmake 工具生成相应的构建文件,例如 Makefile 或 Visual Studio 解决方案。通过运行生成的构建文件,开发者可以编译和构建他们的项目。 4. Ninja:Ninja 是一个轻量级的构建系统,能够更快地构建大型项目。Qt 6 提供了对 Ninja 的支持,开发者可以使用 Ninja 替代 Make 构建项目,以提高构建速度。 这些工具提供了便捷的编译和构建环境,使开发者能够轻松地编译和构建 Qt 6 的源码。无论是使用命令行工具还是集成开发环境,开发者都可以根据自己的需求选择适合自己的工具来编译和构建他们的项目。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值