CXX-Qt 由 crates/ 目录下的多个 crate 组成。
本页概述了每个 crate 的目标以及它与其他 crate 的区别。
-
⭐ cxx-qt - 主角
-
👷 cxx-qt-build - 建筑工人
-
💚 cxx-qt-gen - CXX-Qt 的核心
-
📖 cxx-qt-lib - “标准”库
-
📚 cxx-qt-lib-extras - 书架
-
💻 cxx-qt-macro - cxx-qt-gen 的前端
-
🦾 qt-build-utils - 使用 Qt 构建
-
🤝 cxx-qt-cmake - 与 CMake 的交接
⭐ cxx-qt - 主角
CXX-Qt 的主 crate。
它作为用户实际应该与之交互的 crate。用户在其下游 crate 中需要命名的任何内容都应通过此 crate 访问。最重要的是,这包括从 cxx-qt-macro crate 重新导出的 #[cxx_qt::bridge] 宏。此外,桥接扩展后引用的任何代码都位于 cxx-qt 中。
限制:cxx-qt crate 本身仅限于实现 CXX 的超集。这意味着它的目标是为 CXX 添加额外的 Qt 特定功能,即支持 Qt 的元对象系统,包括 QObject、QEnum、属性、信号、槽等。
CXX-Qt 旨在允许你包装 Qt API 并创建你自己的 Qt 兼容类型。它并不旨在实际包装 Qt API。除了实现此目标所需的少数非常基本的类型外,实际包装 Qt API 的工作被委托给 cxx-qt-lib 和 cxx-qt-lib-extras。
这也应该允许 cxx-qt-lib 和 cxx-qt-lib-extras 在不使用 cxx-qt crate 本身的情况下使用,这就是为什么它们被明确分开的原因。
👷 cxx-qt-build - 建筑工人
cxx-qt-build 提供了用户可访问的 API,用于使用 CXX-Qt 构建应用程序。
具体来说,这意味着扩展和编译每个桥接的 C++ 代码。
此外,它需要将 Qt 集成到 Cargo 和 CMake 中。对于 Cargo,它使用 Cargo 的构建脚本功能来指示链接等。对于 CMake,它将所需的工件暴露到一个已知的目录和结构中,以便 CMake 可以拾取它们。cxx-qt-cmake 仓库包含拾取工件的 CMake 代码。
对 Qt 构建工具的访问实际上已经作为一个单独的 crate 提供:qt-build-utils,cxx-qt-build 在内部使用它。
💚 cxx-qt-gen - CXX-Qt 的核心
此 crate 包含 CXX-Qt 的“主要功能”。
它封装了位于 CXX-Qt 核心的转译器。如 cxx-qt crate 部分所述,CXX-Qt 的目标主要是作为 CXX 的扩展,允许用户表达 Qt 特定的构造。
cxx-qt-gen 实现了必要的转译器,将 #[cxx_qt::bridge] 转译为 #[cxx::bridge] 以及相关的 Rust 和 C++ 代码。
然后,此转译器通过 cxx-qt-macro 由 #[cxx_qt::bridge] 宏使用,并由 cxx-qt-build 用于 C++ 代码生成。
⚠️ `cxx-qt-gen` 不应直接使用,而应通过 `cxx-qt` 和 `cxx-qt-build` 使用。
因此,`cxx-qt-gen` 本身是 semver-exempt(不受语义版本控制约束)的!
TODO:在单独的页面中添加 `cxx-qt-gen` 阶段和架构的文档。
📖 cxx-qt-lib - “标准”库
cxx-qt-lib 对于 cxx-qt 来说,就像 Rust 的 std 库对于 rustc 一样。
它包括对最重要 Qt 类型的高质量包装。这些通常以普通的 #[cxx::bridge] 实现,只有少数类型需要 #[cxx_qt::bridge]。
在 CXX-Qt 的开发过程中,我们很快意识到,手工编写高质量的 Qt API 绑定是最佳选择。特别是对于应该在 Rust 中作为平凡类型可用的类型。然而,这常常带来了维护工作量的问题。
Qt 有一个巨大的 API 表面。因此,我们很早就决定,包装整个 Qt API 超出了范围。这正是为什么我们将 CXX-Qt 的重点放在赋予用户能力上。我们希望用户能够通过创建自己的绑定快速访问他们需要的任何部分 API。
然而,如果没有至少一些基本类型,这是非常困难的。cxx-qt-lib 旨在填补这一空白。它的目标是提供足够的类型和 API,为新绑定提供基础。
额外的类型可以添加到一个单独的、维护较少的 crate 中(即:cxx-qt-lib-extras)。
这引出了 cxx-qt-lib 中包含类型的具体策略:
cxx-qt-lib 包含策略
-
默认情况下,将你认为可能有用的任何内容添加到 cxx-qt-lib-extras。
-
只有在以下情况下,才将类型直接添加到 cxx-qt-lib:
-
难以优化包装(即应该是平凡的/模板等)。
-
在 Qt 代码库中经常用作参数/返回值。
-
然后,如果/当发现某个类型被定期使用时,我们总是可以将类型从 -lib-extras 提升到 -lib。
📚 cxx-qt-lib-extras - 书架
如 cxx-qt-lib 库中所述,我们不打算维护整个 Qt API 的包装。然而,仍然有一个地方可以让社区分享和收集他们包装的 Qt API 绑定,这将非常有用。
这正是 cxx-qt-lib-extras 的用途!详细信息在 #766 中概述。
这里的入门门槛非常低。我们将接受几乎任何 PR,只要:
✅ 它包装了 Qt API 的一部分
✅ 编译通过
✅ 没有明显的其他问题
然而,我们不会花费太多(如果有的话)时间来实际维护这些绑定!
具体来说,这意味着:
⚠️ cxx-qt-lib-extras 是 semver-exempt(不受语义版本控制约束)的!
具体来说,如果某个绑定导致问题,我们可能会简单地将其从 crate 中删除。
⚠️ 绑定可能不完整或未记录!
⚠️ 可能存在内存安全错误和其他问题!
基本上:这里有龙 🐉 - 使用风险自负。
鼓励分叉 cxx-qt-lib-extras 以创建你可以依赖的稳定内容。简单地将 crate 中的单个文件复制到你自己的 crate 中也是使用 -lib-extras 的合理方式。
我们只要求你将你自己的包装和修复贡献回 -lib-extras,以便更广泛的生态系统可以受益。
💻 cxx-qt-macro - cxx-qt-gen 的前端
由于 Cargo 中的技术原因,过程宏需要是一种特殊类型的 crate。
cxx-qt-macro 包装了桥接宏,然后由 cxx-qt crate 重新导出。
🦾 qt-build-utils - 使用 Qt 构建
此 crate 包装了 Qt 的自定义构建工具,如 moc。
它主要由 cxx-qt-build 使用。但由于它可能对 Qt 生态系统中的其他 crate 也有用,我们决定将其拆分为自己的 crate。
🤝 cxx-qt-cmake - 与 CMake 的交接
虽然这不是一个 crate,而是一个单独的“项目”,因为它位于另一个仓库中。cxx-qt-cmake 只包含封装 cxx-qt-build 工件与 CMake 集成的 CMake 代码片段。
它位于一个单独的仓库中,因为这样可以加快 CMake 的 FetchContent 的使用速度,因为用户不必下载整个 CXX-Qt。