Development
CSS 中的标点悬挂及其现状
什么是标点悬挂
标点悬挂 (Hanging punctuation) 是一种排版微调技术。当一行文字以标点开头或结尾时,标点可以「悬出」段落的对齐边界, 使正文文字的视觉边缘保持整齐。虽然差别细微,但在大段文字的排版中, 这种整齐的边缘能在一定程度上提升阅读体验。
阅读全文…写给未来的blog:关于引用、结构、导航与 AI
早年,车东 提出过一个愿景:「让互联网:良好引用,良好结构,良好导航」, 这句话一直让我印象深刻。一直以来,对互联网内容的彼此可以有效引用、结构清晰、可以被(人类和机器) 理解和持续访问而不是被时间与系统更新湮灭,是我和许多 blog 作者的理想。在我自己的 blog 中, 我也一直在尝试实现这三个目标。
阅读全文…Hugo blog 主题模板重构
借着 Vibe Coding 的东风,我为 blog 重新设计了一套模板,希望解决一些此前用的基于 ink 模板中存在的一些问题,并彻底清理掉一些历史包袱。
这件事还要从 Search Console 的 Core Web Vitals 报告说起。报告显示,旧主题使用的 Noto Serif SC 网页字体加载缓慢, 并在渲染过程中导致了显著的累积布局偏移(CLS)问题。
在调整网站 CSS 的过程中,我逐渐意识到原有主题模板存在不少结构性问题;与其零碎修补,倒不如直接推倒重来。 我的想法是,首先用 Hugo 新建一个最新版的最小模板,然后逐渐在上面添加我需要的功能,于是我列了一个需求 wishlist 清单:
阅读全文…git submodule 与 subtree 的异同
前几天有小伙伴在整理某个代码仓库的时候,希望把仓库里的代码和数据分离以便于管理。 由于他使用的是 git,所以很快大语言模型便引导他用上了包括 filter-repo 在内的一系列禁术, 其间就有了一段关于是应该使用 git submodule 还是 git subtree 的讨论。
先说我的结论,对于绝大多数人,特别是已经动了重写历史这种念头的人来说, 理想的选择是 git submodule。
阅读全文…C++ 中的 main 定义
新的 C++ 标准中 不允许给 main 指定 linkage-specification 了。
当然,考虑到原本 main() 也是 C 运行环境在开始运行程序的时候调用的, 而 C 运行环境自然也预期 C linkage,即不按照 C++ 的习惯对符号根据参数增加名字前缀, 因此大部分编译器在遇到 C++ 程序定义全局 main() 的时候也会按照习惯采取 C linkage 方式去翻译。这一规则首先被 GCC 采纳,随后 LLVM 也跟进了。
阅读全文…FreeBSD 14.0-RELEASE 发布了
上周末抽时间把服务器升级到了 FreeBSD 14.0-RELEASE。
软件的发布中存在许多的工序,大致上,在 releng/ 分支上的代码树会正式命名为 -RELEASE,
同时由一位 Release Engineer 开始最终的 build(对应的文件会发布到 FTP 上,
并在 网站 上提供链接),并在适当的时候将 releng/ 分支上的代码
tag 成 release。此后, Security Team 需要将 Release Engineer 签名的 -RELEASE
放到 freebsd-update builder 上再次 build、签名,并生成二进制更新所需的文件。
由于安装用的 ISO 映像文件都比较大,传统上将这些映像文件分发到全球的镜像站点上需要一些时间。 现时,云服务提供商往往还有自己的 QA 步骤,因此最终宣布 -RELEASE 的时间往往会比 FTP 上出现的时间晚上一周左右。技术上这段时间这个 build 依然只是一个发布候选版本(Release Candidate), 因此普通用户不应使用这些版本,因为在这一周的时间如果遇到一些突发状况的话可能会需要将这个版本撤回 (例如原本应发布为 FreeBSD 4.6.1 的 FreeBSD 4.6.2 就是这样的情况)。
阅读全文…记录一下当年把 FreeBSD 中 zlib 砍到只剩一份的过程
软件项目中,实现同一功能的源代码只保留一份是一项十分重要的最佳实践,这种做法可以带来许多显而易见的好处:
- 简化依赖关系管理。 对于 C/C++ 项目来说,如果同一个函数库有不同的版本,意味着必须设法确保其中不包含同一符号的多个变体。
- 减少技术债的积累。 只保留一个版本意味着参与项目的所有开发者都使用最新版本的库,或是从一个接近最新版本的库升级到最新版本,这要比把技术债留给后人去解决要容易许多。尽管升级时需要考虑的问题会更多一些,但这也意味着更好的一致性。只留一份版本意味着在升级时必须通盘考虑全局的影响,配合持续集成测试的使用,这也会带来更好的代码品质,并让整个团队能够更快地进行迭代。
- 节省各类存储占用。
- 改善整体安全性。问题只需在一处进行修正。
2009年的时候 kmacy@ 做了 一些初步的工作,但后续没有继续推进。 这之后 我 考虑重新把这个事给做掉,但苦于平时比较忙因此未能如愿。最终, Yoshihiro Ota 完成了大部分的工作。
阅读全文…C main() 的 exit() 和 return
这里讨论一个犀利而无用的细节问题。事情的缘起是有人在 GitHub 上提了一个 pull request 要求把许多程序的
main() 的终结部分从 exit(X) 改为 return X;,我反对了这一变动。
值得注意的是,在实践上,从 main 中 return 和调用 exit(3) 几乎等效的(此处还是有细微差别,
后面将会讨论),原因是 C 运行环境库的启动部分(这部分会在连接过程中嵌入到可执行文件中,
FreeBSD 的实现中,这部分位于 lib/libc/csu/libc_start1.c
的 __libc_start1:
| |
FreeBSD 14 确定延期
原定4月25日开始的code slush和KBI冻结并未发生,主要的原因是 OpenSSL 3.0 还未合并, 以及 OpenZFS 近期的一些可靠性问题。
其中,OpenSSL 3.0 由于对 API 的改动比较大,因此会导致一些 port 无法正常工作 (PR 258413)。 近期已经有一批 port 标记为与 OpenSSL 3.x 不兼容, 不过修掉这些可能会需要不少时间。
阅读全文…用 poudriere 完成包管理
由于使用的 port 的编译选项与官方的往往不一致(例如我非常讨厌 gnutls、avahi 这两个包,此外有时我希望使用一个和官方不太一样的 OpenLDAP 版本, 或者采用不同的编译选项等等),我之前一直是 portmaster(8) 的用户。 portmaster 是 Doug Barton 早年用 shell 脚本写的一个 portupgrade(1) 的替代品,和后者相比,它不需要使用数据库,并且充分利用了 shell 的任务管理功能实现了尽可能利用 CPU 的计算能力,我个人也从这个脚本中学到了不少 shell 脚本的技巧。
不过,使用 portmaster 需要在每一台机器上都有一份 ports tree,并且由于直接操作的是本地的生产环境, 因此对于比较基础的库,如 gettext 之类,或是在升级操作系统时, 由于升级时间较久导致出现问题的可能性相对要大一些。 另一方面,使用 port 来管理第三方软件意味着需要把联编过程中的所有依赖软件包全都都装到生产环境中, 有时这是非常不经济的,例如大部分时候运行环境并不需要完整的跨平台 LLVM,等等,而使用 port 安装的话, 每一个系统中都需要整体重新联编一遍。
我之前已经用过很长时间的 poudriere 了。 这是一款现代化的联编系统,它充分利用了 FreeBSD 的一系列特性,包括 ZFS 快照/克隆、 tmpfs、 jail 等等,支持交叉编译。除此之外它还支持使用 ccache 来减少重复编译,等等。 不过,线上的机器出于习惯^H^H懒惰导致的惯性一直还是在沿用之前采用 portmaster 来进行更新。
阅读全文…