Patches for x265 on SerenityOS
【免费下载链接】serenityThe Serenity Operating System 🐞项目地址: https://gitcode.com/GitHub_Trending/se/serenity
0001-Replace-alloca-with-__builtin_alloca.patch
Replace alloca() with __builtin_alloca()
这份 ReadMe 遵循 SerenityOS Ports 体系的约定:以 `# Patches for <port> on SerenityOS` 开头,为每个 `.patch` 文件生成一个 `## <文件名>` 小节,并附上补丁的提交主题与提交说明。实际上,这个文件并非手工维护,而是由 `.port_include.sh` 中的 `do_generate_patch_readme` 函数自动生成的——它用 `git mailinfo` 从每个补丁中提取 `Subject:` 与提交正文,过滤 `Co-Authored-By` 行后写入 ReadMe(见 [Ports/.port_include.sh](https://link.gitcode.com/i/cb76f5a58a84e81b0b1aeb81ded2eec2) 中 `do_generate_patch_readme`)。这意味着:**ReadMe 的每一行内容都直接来源于补丁文件的提交元数据**,是补丁意图最权威的摘要。 而补丁本身,即 [0001-Replace-alloca-with-__builtin_alloca.patch](https://link.gitcode.com/i/698ef8ef1cd2375c573c5e214abdfef8),才是真正的技术载体。 ## 三、补丁深度拆解:diff 逐行解读 `0001-Replace-alloca-with-__builtin_alloca.patch` 的提交元数据表明:From: Linus Groh mail@linusgroh.de Date: Mon, 4 Aug 2025 23:58:38 +0100 Subject: [PATCH] Replace alloca() with __builtin_alloca()
补丁只改动一个文件 `source/x265cli.cpp`,共 2 处插入、2 处删除。第一处也是核心改动位于 `x265cli.cpp` 第 1138 行附近: ```diff rewind(zoneFile); - char **args = (char**)alloca(256 * sizeof(char *)); + char **args = (char**)__builtin_alloca(256 * sizeof(char *)); param->rc.zones = x265_zone_alloc(param->rc.zonefileCount, 1);;从上下文可以推断,这段代码位于 x265 命令行工具解析rate-control zonefile(码率控制分区文件)的逻辑中:先rewind(zoneFile)将文件指针复位,再用alloca在栈上分配一个可容纳 256 个char*指针的临时数组,随后调用x265_zone_alloc为param->rc.zones分配分区数据。这里使用栈上分配而非堆分配,是为了避免高频解析场景下的堆开销,同时函数退出后自动释放,无需手动管理。
第二处改动是文件末尾的换行修复:
#ifdef __cplusplus } -#endif \ No newline at end of file +#endif即给x265cli.cpp末尾补上缺失的换行符。这通常是为了满足编译器的-Wnewline-eof风格告警或工具的格式要求。
四、为什么必须替换:SerenityOS LibC 的 alloca 实现
补丁的动机要从 SerenityOS 的 C 标准库说起。Userland/Libraries/LibC/alloca.h 的全文只有一行核心定义:
#define alloca __builtin_alloca也就是说,SerenityOS 的 LibC不提供alloca()的函数实现,而是直接将宏映射到 GCC/Clang 的编译器内建函数__builtin_alloca。这样做的好处是:
alloca本质上是"在栈帧上按需分配可变大小空间"的操作,编译器内建函数才能生成正确的栈指针调整指令,并在函数返回时一并回收;- 避免在 libc 中维护一份易受攻击的汇编实现(历史上 alloca 是实现与安全 bug 的高发区);
- 宏展开发生在预处理阶段,不会引入额外的符号依赖。
对于 x265 这类第三方项目,其源码中直接调用alloca(),在链接阶段会因找不到alloca符号而失败(部分环境也可能因未包含<alloca.h>而编译失败)。因此移植时最直接的修复就是在调用点把alloca改写为编译器内建形式__builtin_alloca,这正是本补丁的做法。由于__builtin_alloca是 GCC/Clang 都支持的内建函数,该改动在上游工具链下同样合法,具备很好的可回推性(upstreamable)。
值得强调的是,这一改动也印证了 SerenityOS 全项目的编码取向:在 Userland/Libraries/LibC/cxxabi.cpp、Userland/Libraries/LibC/dirent.cpp 等 LibC 内部实现中,动态内存一律走malloc/realloc或专用分配器,栈上可变分配则统一交由编译器内建处理。
五、补丁如何被应用:Ports 的 patch 流水线
理解了补丁内容,再看它如何进入构建流程。Ports/.port_include.sh 中的patch_internal函数负责自动应用补丁:
patch_internal() { if [ -n "${IN_SERENITY_PORT_DEV:-}" ]; then return fi # patch if it was not yet patched (applying patches multiple times doesn't work!) if [ -d "${PORT_META_DIR}/patches" ]; then for filepath in "${PORT_META_DIR}"/patches/*.patch; do filename=$(basename $filepath) if [ -f "$workdir"/.${filename}_applied ]; then continue fi if [ -e "${workdir}/.git" ]; then run git am --keep-cr --keep-non-patch "${filepath}" else run patch -p"$patchlevel" < "$filepath" run touch .${filename}_applied fi done fi ... }其工作机制可以总结为三点:
- 幂等保护:每次成功应用某个补丁后,会在工作目录创建
.${filename}_applied标记文件(例如.0001-Replace-alloca-with-__builtin_alloca.patch_applied),下次构建时跳过已应用的补丁,避免重复打补丁导致冲突; - 两种应用方式:若解压后的源码目录是 git 仓库(如在
dev模式下),用git am以提交形式应用;否则用patch -p"$patchlevel"直接应用,patchlevel默认值为 1(见 Ports/README.md 中对patchlevel的说明),对应本补丁中的a/source/x265cli.cpp/b/source/x265cli.cpp前缀剥离规则; - 执行顺序:
./package.sh无参数时的默认流程为installdepends → fetch → patch → configure → build → install(见 Ports/README.md 的 Options 一节),补丁应用发生在 configure 之前,确保 CMake 配置与编译看到的是修补后的源码。
六、同类佐证:alloca 适配是跨端口的通用模式
x265 并非唯一需要处理 alloca 的端口。搜索 Ports 目录可以发现,SerenityOS 移植第三方软件时对 alloca 的处理存在两条成熟路径,与本补丁互为印证:
路径一:调用点替换为__builtin_alloca(与 x265 相同)
Ports/OpenJDK/patches/0005-hotspot-Update-non-BSD-native-modules-for-Serenity.patch 中为 HotSpot 的非 BSD 原生模块补充了宏:
#define alloca(p) __builtin_alloca(p)OpenJDK 体量庞大,难以逐点替换,因此采用"集中定义宏"的方式达到与 x265 补丁相同的效果。
路径二:补齐<alloca.h>头文件包含
Ports/figlet/patches/0002-Add-missing-alloca.h-include.patch 则为 figlet 增加了#include <alloca.h>。由于 SerenityOS 的 LibC 提供alloca.h(见 Userland/Libraries/LibC/Headers.cmake 中登记的alloca.h),包含该头文件即可获得#define alloca __builtin_alloca宏,无需改写调用点。
三种策略(逐点替换、集中宏定义、补头文件)殊途同归,最终都落到同一事实:SerenityOS 上 alloca 的唯一合法入口是__builtin_alloca。
七、构建与安装 x265:完整操作流程
基于以上分析,在具备 SerenityOS 构建环境的前提下,安装 x265 端口的完整流程如下:
# 前提:已构建 SerenityOS 且处于 Serenity 构建环境(含 SERENITY_BUILD_DIR 等变量) cd Ports/x265 # 一键完成:installdepends -> fetch -> patch -> configure -> build -> install ./package.sh # 仅执行打补丁步骤(应用 patches/*.patch),便于单独验证补丁 ./package.sh patch # 单独构建或安装 ./package.sh build ./package.sh install # 进入开发模式:在 git 仓库形式的源码中交互调试,退出后自动重新生成补丁与 ReadMe ./package.sh dev【免费下载链接】serenityThe Serenity Operating System 🐞项目地址: https://gitcode.com/GitHub_Trending/se/serenity
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考