Plywood:一种新的跨平台开源C++框架

2020-05-26 13:22:57

在过去的一小段时间里-好吧,很长一段时间-我一直在用C++开发一个自定义游戏引擎。今天,我将该游戏引擎的一部分作为开放源码框架发布。它被称为胶合板框架。

请注意,胶合板本身并不是游戏引擎!它是一个使用C++构建各种软件的框架。

例如,Plywood的文档是在C++解析器的帮助下生成的,由Markdown解析器格式化,并在全部使用Plywood编写的自定义Web服务器上运行。

集成第三方库在C++中可能是一件痛苦的事情,但Plywood的目标是简化它。下面是一个简短的胶合板程序,它使用cairo和Libavcodec将矢量动画渲染为视频文件:

这些示例的源代码包含在Plywood存储库中,所有内容都在Windows、Linux和MacOS上构建和运行。

当然,胶合板也是我的(专有)游戏引擎的基础,我称之为Arc80引擎。这就是胶合板首先出现的原因。我还没有发布一个使用Arc80引擎的完整游戏,但我已经用它制作了一些原型。稍后会详细介绍这一点!

大多数开源C++项目都是打算集成到其他应用程序中的库。胶合板正好相反:它为您提供了一个可以集成源代码和库的工作区。单个胶合板工作空间可以包含多个应用程序-网络服务器、游戏引擎、命令行工具。胶合板简化了它们之间构建和共享代码的任务。

胶合板在幕后使用CMake,但您不必编写任何CMake脚本。与任何基于CMake的项目一样,胶合板工作区具有与源代码分开的目标和构建文件夹的概念,但它在此基础上添加了其他几个概念,如模块、根目标和外部提供程序。(注意:不要将胶合板模块与C++20模块混淆;它们是不同的东西。)

一个胶合板工作区外部包构建文件夹根目标repos源代码模块外部提供者解释胶合板工作区,以及它是如何与CMake交互的,这确实值得一提,但它帮助实现的是模块性。

Arc80是一个模块化游戏引擎,多亏了胶合板工作区,可以使用Arc80引擎模块快速构建小型应用程序。例如,当我为喷气式发动机开发火焰效果时,我创建了一个只包含火焰效果的小型测试应用程序。这个测试应用程序允许我专注于功能本身,并使效果与游戏的其余部分解耦。

还需要做更多的工作,以使这一过程更加方便用户。例如,要定义新模块,您当前必须使用我尚未记录的API编写C++函数。简单的配置文件会更好。这是我计划做的下一件事,因为胶合板已经发布了。

我想了很久Arc80引擎的开源部分,这就是导致上面提到的repos想法的原因。单个胶合板工作区可以组合来自不同Git存储库的模块。当谈到开源胶合板时,问题是将一堆模块从专有的arc80repo迁移到公共的胶合板repo。

截至今天,胶合板回收器配备了39个内置模块。这些模块提供平台抽象、矢量数学、JSON解析、音频和图像处理等功能。当然,所有模块都是可选的,因此如果您认为某个特定模块不适合您的需要,则不必使用它。这是一个简图,显示了胶合板repo中包含的一些模块(在底部)和我目前保密的模块(在顶部)。箭头表示依赖关系:

平台运行时反映塔架烹饪数学图像web CPP编解码器构建音频libavcodec cairo libsass plytool WebCooker WebServer UI会话图形物理视图图像GPU音频资产Bank FreeType SDL游戏RemoteCooker arc80胶合板(不包含)(包含)最重要的模块是标有星号的模块:运行时。我最初将Turf用于跨平台线程和内存管理,然后逐渐添加了容器、I/O、文件系统API和合理的Unicode支持。运行时模块就是结果。它还公开了标准C或C++运行时库中不可用的内容,如将I/O重定向到子进程和监视目录的更改。API可以在这里和那里进行一些改进,但是我已经更喜欢它而不是标准库了。

我本想开放更多的Arc80引擎源代码,特别是与图形和音频处理相关的模块,但这些模块还没有准备好进入黄金时间。我将来可能会把它们开源,但这首先取决于胶合板是否成功。

在我看来,运行时反射是标准C++中缺少的最大特性。此功能启用了整个类别的泛型编程,否则这是不可能的。我在本博客的前两篇文章中写过运行时反射。Plywood附带了一个内置的反射系统,该系统基于那些帖子中描述的方法,但在上面增加了一个代码生成步骤。

简而言之,Plywood的反射系统在运行时公开有关程序数据结构的元数据。例如,在Plywood的Web文档模块中定义了名为Contents的数据结构:

[{";Title";:";Home";,";link目标";:";/";,";子项";:[]},{";Title";:";快速入门";,";link目标";:";/docs/QuickStart";,";子项"。:[{";Title";:";Building the Documentation";,";link Destination";:";/docs/QuickStart/BuildDocs";,";Children";:[]}]},.。

通过将Array<;content>;的元数据传递给通用JSON加载函数来加载数据。不需要编写特定于类型的加载代码。

目前,要实现这一点,您需要在编译项目之前在命令提示符下运行plytool codegen。(我计划最终将此命令合并到构建过程中,但前提是对其进行优化,使其以增量方式运行。)。该命令扫描所有可用的源代码模块,使用自定义C++解析器提取所有类型声明,并生成元数据所需的一些附加源代码。

胶合板是我个人很长时间以来一直想要的框架,老实说,它让C++更像我想使用的编程语言。我希望它对其他人也能起到同样的作用。但仍有文档要写,特性要润色,错误要压扁。

如果您认为胶合板在正确的轨道上,并希望看到它不断改进,请支持它在Patreon上的正在进行的开发:

如果Plywood吸引了足够多的Patreon支持者,我将很乐意写一系列博客文章,解释它是如何工作的,以及它是如何利用特定的C++特性的。

如果您是一个从事相对较新的、跨平台的C++项目的团队,我认为将该项目建立在胶合板上已经是可行的。您必须密切关注Plywood开发,并且必须直接从文档尚未完成的源代码中寻找一些答案(任何项目都是如此)。但是考虑到我已经在这个框架上投入了大约4000小时的工作,与您自己构建类似的框架相比,您将会有一个显著的领先优势。

胶合板有很多未来可以扩展的功能:

可以对Plywood的内置C++解析器进行扩展,使其适用于其他应用程序。它目前可以识别声明,但不能识别表达式;目前跳过了函数体。这一功能将是一项艰巨的任务。

网络服务器可以改进。它甚至还没有使用线程池。对Web服务器的任何改进都可能使Plywood更适合其他后端服务。

可以消除胶合板对标准C++运行时的依赖,在某些平台上,对标准C运行时也是如此。这样做可以减少构建时间,并产生更小的可执行文件。

可以让PlyTool直接调用C++编译器,而不需要CMake首先生成中间生成系统。

这取决于其他人认为有用的东西,所以我很想听听你的想法。这些改进中有哪些是值得追求的?你认为有什么方法可以简化胶合板的东西吗?有什么问题吗,或者更多的是评论而不是问题?我将在闪亮的新胶合板不和谐服务器上闲逛,所以请随时加入我们的讨论!否则,你可以直接联系我。