GLib 2.58 的新闻

今年九月,GLib 将发布 2.58 版本。在过去的两个开发周期中,有一些变化,最显著的是 Meson 构建的改进,这反过来提高了 GLib 在 Windows、macOS 和 Android 等平台上的可移植性。现在是时候总结一下 GLib 的当前状态,并强调一些将影响基于 GLib 的代码的更改。

  • Meson – 感谢 Nirbheek Chauhan 和 Xavier Claessens 的持续工作,Meson 构建一直在不断改进,以至于我们可以开始将其作为默认的构建系统。该计划——如邮件列表所述——是使用 Meson 发布 GLib 2.58,同时将 Autotools 构建保留在树中并可在发布存档中使用;然后,我们将在下一个开发周期中删除 Autotools 构建,并发布不带 Autotools 支持的 GLib 2.60。非常欢迎 Linux 发行商在其构建器中开始测试 Meson 构建;我们已经将 Meson 构建作为我们的CI流程的一部分运行了一段时间,但更多的曝光将带来我们错过的最终回归;此外,如果使用与 GCC/Clang/MSVC 不同的工具链的人们开始尝试 Meson 构建并报告错误,那将是极好的。同时,如果您在 macOS 和 Windows 上使用 GLib,我们已经建议您切换到 Meson 来构建 GLib,因为它比 Autotools 更容易且更好地与这些平台集成。
  • 可靠性和可移植性 – GLib 与 GNOME 的其余部分一起切换到了 GitLab,这意味着能够在GNOME Continuous 构建之外运行持续集成。现在,我们在每次提交和合并请求时都运行CI在多个工具链、多个构建系统和多个平台上,这大大降低了构建失败的可能性。我们还提高了测试套件中的代码覆盖率。当然,我们总能做得更好;例如,我们没有CImacOS 和 Solaris 系列操作系统的运行器,如果能有更多 *BSD 系列的运行器将非常受欢迎。如果您有空闲的机器和可以捐赠的一些带宽,我们已发出帮助请求
  • *BSD 上的文件监控 – 关于 *BSD 系列,GIO 中用于文件监控的 kqueue 后端已由 Martin Pieuchot 和 Ting-Wei Lan 完全改造;新代码更简单、更健壮,并且通过了所有测试。
  • 使用 posix_spawn() 进行高效的进程启动 — 感谢 Daniel Drake,如果平台的 C 库支持,GLib 现在可以在特定情况下使用 posix_spawn();与手动调用 fork() + exec() 相比,这允许在内核中命中快速路径;这些快速路径在内存受限的平台上运行时尤其有利。
  • 引用计数类型和分配 — GLib 在其许多类型中使用引用计数作为内存管理和垃圾回收机制,但缺乏公共 API 来允许其他人在其自己的数据结构中实现相同的语义;这导致大量的复制粘贴和重新实现,并且通常导致诸如饱和和线程安全方面的未定义行为。GLib 2.58 具有 grefcountgatomicrefcount 类型,以及它们的 API,以减少这种重复。此外,借鉴 Rust 等其他语言,GLib 提供了一种通过添加一个底层 API 在内存分配上添加引用计数语义的方法,该 API 允许您分配没有引用计数字段的结构,并自动向其添加引用计数语义。
  • 弃用 – 在上一个开发周期中,一些软弃用已成为真正的弃用。
      • g_type_class_add_private() 在我们引入实例私有数据宏五年后最终被弃用;如果您仍然在类初始化中使用该函数,请切换到 G_DEFINE_TYPE_WITH_PRIVATEG_ADD_PRIVATE
      • g_main_context_wait() 已正式弃用,但您应该已经看到有关其使用的运行时警告。
      • GLib 提供的 GTest harness gtester 已被弃用;如果您正在使用 Autotools,则应该使用TAPAutomake 附带的 harness。

在本周期中,由于 Philip Withnall 的不懈努力,GLib 中有很多贡献;他在审查补丁、分类错误以及在项目开发过程中实施更改方面发挥了重要作用。切换到 GitLab 也改进了贡献流程,有更多的开发人员打开了合并请求。

  • 2.54.0..c182cd68:来自 143 位开发人员的 968 个变更集,高于 2.53 开发周期中的 412 个变更集和 68 位开发人员。
  • 总共添加了 31851 行代码,删除了 27976 行代码(差值:+3875
变更集最多的开发人员
Philip Withnall 303 31.3%
Xavier Claessens 79 8.2%
Emmanuele Bassi 69 7.1%
Christoph Reiter 42 4.3%
Ting-Wei Lan 21 2.2%
Chun-wei Fan 21 2.2%
Nirbheek Chauhan 21 2.2%
Ondrej Holy 20 2.1%
Руслан Ижбулатов 20 2.1%
Mikhail Zabaluev 20 2.1%
Simon McVittie 15 1.5%
Matthias Clasen 14 1.4%
Christian Hergert 13 1.3%
Iñigo Martínez 12 1.2%
Bastien Nocera 10 1.0%
Rafal Luzynski 9 0.9%
Michael Catanzaro 9 0.9%
Will Thompson 8 0.8%
Allison Lortie 8 0.8%
Daniel Boles 8 0.8%

请务必使用 GLib 2.57.2 测试您的代码,这是迈向 2.58.0 稳定版本的下一个开发快照。

日志记录及更多

不久前,GLib 获得了一个新的“结构化日志记录”工具。同时,它还获得了将日志写入 systemd 日志的支持。显然,GLib 中的日志记录变得更加复杂,并且可能会有些令人困惑。

本文试图澄清一些事情。

结构化或非结构化

传统的 GLib 日志记录工具是 g_message()g_debug() 等宏,它们最终调用 g_log() 函数,然后使用通过 g_log_set_handler() 设置的日志处理程序来执行实际写入。您可以将您喜欢的任何信息放入日志中,但它必须全部格式化为单个字符串,即消息。

g_debug ("You have %d eggs", 12 + 2);

g_log (G_LOG_DOMAIN,
       G_LOG_LEVEL_DEBUG,
       "You have %d eggs", 12 + 2);

使用新的结构化日志记录工具,您可以调用 g_log_structured(),然后使用日志写入器函数来执行写入。到目前为止,这与较旧的日志记录工具非常相似。结构化日志的优点是您可以将多个字段放入日志中,而无需将其全部格式化为字符串。相反,您传递一个日志字段数组,它们是键值对。

g_log_structured (G_LOG_DOMAIN,
                  G_LOG_LEVEL_DEBUG,
                  "CODE_FILE", "mysource.c",
                  "CODE_LINE", 312,
                  "MESSSAGE_ID", "06d4df59e6c24647bfe69d2c27ef0b4e",
                  "MESSAGE", "You have %d eggs", 12 + 2);

这里的 CODE_FILECODE_LINEMESSAGE_ID 只是“标准”字段的示例。您也可以发明自己的字段。请注意,您仍然可以使用 printf 样式的格式化来处理 MESSAGE 字段。

因此,GLib 现在有两个单独的日志记录工具。为了使事情更有趣,我们允许您重定向 g_message()g_debug() 等包装宏,以在底层使用 g_log_structured() 而不是 g_log()。为此,请在包含 glib.h 之前定义 G_LOG_USE_STRUCTURED 宏。

为什么这很有用?一方面,它省去了您替换所有 g_debug() 的麻烦,并且仍然允许您利用结构化日志记录的一些优势 – 以这种方式使用时,传统的宏会为日志域、代码文件和行以及其他一些字段使用单独的字段,这有助于在生成的日志中进行过滤和搜索,尤其是在使用 systemd 日志时。

另一个优点是,您可以使用单个后端(即日志写入器函数)来控制旧的和新的日志记录调用的最终位置。

我的日志都去哪儿了?

结构化日志记录通常与 systemd 日志相关联。因此,人们期望 g_log_structured() 的输出会进入日志,这并不奇怪。这对于服务或当您例如从桌面图标启动应用程序时非常有用。但是,如果您从终端运行它,您可能希望在那里直接看到其输出。

为了满足这些相互竞争的需求,GLib 默认的日志写入器函数试图变得智能。如果它检测到 stderr 被重定向到 journald 套接字,则它会将其结构化输出写入日志。否则,它会格式化一条消息并将其写入 stderr

GNOME Shell 和 DBus 都会在启动应用程序或服务时安排将 stderr 重定向到日志。一种将 stderr 显式重定向到日志的方法是在 systemd-cat 下运行您的应用程序。

systemd-cat my-app-that-logs

如果您确定希望日志始终进入日志,则可以告诉 GLib 使用执行此操作的日志写入器。

g_log_set_writer_func (g_log_writer_journald, NULL, NULL)

超越默认值

即使 GLib 默认提供的日志写入器函数应该满足许多需求,您可能仍然需要编写自己的日志写入器函数。在这种情况下,GLib 有许多有用的函数可以帮助您,例如 g_log_writer_format_fields()g_log_writer_is_journald()g_log_writer_supports_color()

快乐日志记录!

参考

  • Philipps 关于结构化日志记录的演讲
  • GLib 日志记录文档
  • Systemd 日志文档

GLib 2.19.6 不稳定版本发布

这是 GLib 2.20 之前的第六个开发版本。
此版本修复了 7 个错误

  • 通用
    • 新增用于打印 goffset 数据的格式宏:G_OFFSET_FORMAT
  • GIO
    • 添加 GFilter{Input,Output}Stream::close-base-stream 属性,用于确定在过滤器流最终确定时是否关闭基本流。
    • g_data_input_stream_read_line 和 …_read_until 现在有了异步变体。

阅读原始公告了解更多信息和下载。

GLib 2.19.1 不稳定版本发布

这是 GLib 2.20 之前的第二个开发版本。

从 GLib 2.19.0 到 GLib 2.19.1 的更改概述

  • g_icon_to_string, g_icon_new_for_string:GIcon 序列化支持
  • G_FILE_ATTRIBUTE_PREVIEW_ICON:用于预览图像的新文件属性
  • g_app_info_get_commandline:用于获取完整命令行的新函数
  • g_mount_shadow, g_mount_unshadow, g_mount_is_shadowed:新增
  • 用于“隐藏”挂载的函数(即,当它们已经有不同的表示形式(如书签)时,将其从 UI 中隐藏)。

此版本修复了 42 个错误

阅读原始公告了解更多信息和下载。

GLib 2.19.0 不稳定版本发布

这是 GLib 2.20 之前的第一个开发版本。

从 GLib 2.18.1 到 GLib 2.19.0 的更改概述

  • 重写 GHashTable 以使用带二次探测的开放寻址,而不是链接。这有可能显著减少内存碎片,同时由于更好的局部性和不需要为节点调用 alloc/free 函数而略快一些。基准测试表明,它总体上使用的内存也更少。
  • 使 g_poll 可用作公共 API
  • 用于断言 GError 已设置或未设置的新宏 g_assert_error 和 g_assert_no_error
  • g_cancellable_make_pollfd:用于为可取消项创建 GPollFD 的新方法
  • g_app_info_can_delete, g_app_info_delete, g_app_info_reset_type_associations:用于清理应用程序信息和内容类型的新函数
  • 启动应用程序时,尽可能传递 fuse file:// uri,并让 gio 将此类 uri 转换回 gio uri。

此版本修复了 33 个错误

阅读原始公告了解更多信息和下载。