如何用 ASAN 编译并运行 Hyprland 以捕获内存错误 asan.log?
【免费下载链接】HyprlandHyprland is an independent, highly customizable, dynamic tiling Wayland compositor that doesn't sacrifice on its looks.项目地址: https://gitcode.com/GitHub_Trending/hy/Hyprland
如果你的 Hyprland 崩溃,普通日志往往不够定位内存错误(如越界写、use-after-free)。Hyprland 仓库自带一条完整的 ASan 构建路径:Makefile 中的asan目标会把 wayland 服务器库用 AddressSanitizer 本地编译并静态链入 Hyprland,再直接从 TTY 启动 Hyprland;崩溃时 ASan 报告被写入asan.log.<PID>文件,按 docs/ISSUE_GUIDELINES.md 的说法,这个文件就是你可以附上 issue 的崩溃报告。本文覆盖从构建到取出报告的完整操作。
ASan 构建在仓库中是如何生效的
先理解这条路径的构成,后面执行时才知道每一步在做什么:
- CMakeLists.txt 中,只有当
CMAKE_BUILD_TYPE为Debug且WITH_ASAN打开时,才会对hyprland_lib链接asan并加上-fsanitize=address。也就是说 ASan 构建必须基于 Debug 构建,asan目标的 cmake 命令正是Debug+-DWITH_ASAN:STRING=True。 - scripts/hyprlandStaticAsan.diff 在 ASan 分支上额外把本地构建的
libwayland-server.a和libffi链入hyprland_lib。这是asan目标先用 meson 以-Db_sanitize=address编译 wayland 的原因:让 wayland 服务器库本身也带 ASan 插桩,避免未插桩的共享库干扰检测。
所以make asan不是简单的“换个 flag 重编译”,而是一条包含第三方库本地构建的流水线。
执行前的准备
asan目标会实际执行以下动作,执行前先确认你知道这些影响:
- 只在 TTY 中运行。目标开头就打印
!!WARNING!! Only run this in the TTY.,并且通过pidof Hyprland检查,如果当前已有 Hyprland 实例在运行,目标直接exit 1拒绝执行。所以先在桌面外(tty1 之类)操作,并确认没有 Hyprland 进程。 - 它会删除仓库根目录下已有的
./wayland目录(rm -rf ./wayland),然后从网络git clone --recursivewayland 源码并本地编译。 - 它会用
patch -p1应用 scripts/hyprlandStaticAsan.diff,即修改你本地工作区的CMakeLists.txt(加入链接本地 wayland 静态库与libffi的两行)。如果之后要恢复干净的工作区,自行处理这个改动。 - 目标中途有一个交互提示:
If you want to apply a patch, input its path (leave empty for none):,输入要应用的补丁文件路径,直接回车表示不打补丁。 - 命令链中实际用到的工具是
git、patch、meson、ninja、cmake,这些需要可用;运行步骤还会用到你的 Hyprland 配置文件,目标默认指定~/.config/hypr/hyprland.lua。
运行 make asan
在仓库根目录执行:
make asan该目标的完整流程(摘自 Makefile)依次是:
rm -rf ./wayland # 交互提示:输入补丁路径或留空 git clone --recursive https://gitlab.freedesktop.org/wayland/wayland cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd .. cp ./wayland/build/src/libwayland-server.a . patch -p1 < ./scripts/hyprlandStaticAsan.diff cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DWITH_ASAN:STRING=True -DUSE_TRACY:STRING=False -DUSE_TRACY_GPU:STRING=False -S . -B ./build cmake --build ./build --config Debug --target allwayland 库编译完成后打印Wayland done,Hyprland 编译完成后打印Hyprland done。目标最后一步会立即启动 Hyprland 本身:
ASAN_OPTIONS="detect_odr_violation=0,log_path=asan.log" HYPRLAND_NO_CRASHREPORTER=1 ./build/Hyprland -c ~/.config/hypr/hyprland.lua各部分的用途:
log_path=asan.log:让 ASan 把报告写到asan.log.<PID>而不是 stdout;detect_odr_violation=0:关闭 ODR 违规检测;HYPRLAND_NO_CRASHREPORTER=1:该环境变量置位后 Hyprland 不启用自己的 crash reporter(参见 src/Compositor.cpp),避免和 ASan 报告互相干扰;-c ~/.config/hypr/hyprland.lua:明确指定配置文件。注意 docs/ISSUE_GUIDELINES.md 提到 debug 构建默认使用的配置是hyprlandd.lua,而这里用-c显式指定了hyprland.lua,如果你想用自己的配置,改这个参数即可。
启动后 Hyprland 会接管当前 TTY,目标命令不会返回,直到这个 Hyprland 会话结束。
复现崩溃并取出 asan.log
按 docs/ISSUE_GUIDELINES.md 的“Obtaining the debug Hyprland coredump”一节:
- 复现导致崩溃的操作。Hyprland 应当立即关闭。
- 到启动 Hyprland 时所在的目录找名为
asan.log.XXXXX的文件,XXXXX是崩溃那个 Hyprland 实例的 PID。make asan从仓库根目录启动,报告就落在仓库根目录;指南里推荐的手动方式是先cd ~再启动,报告就落在~。 - 这个
asan.log.<PID>文件就是你要的 ASan 报告(指南称之为 debug coredump),可以直接附上 issue。
如果不想走make asan的整条流水线,指南也给了手动启动形式:在 TTY 中用ASAN_OPTIONS="log_path=asan.log" ~/path/to/Hyprland启动——注意这只对已按 ASan 构建的 Hyprland 二进制有意义,否则ASAN_OPTIONS不会生效。构建步骤本身仍按上面的 cmake 参数完成:Debug构建类型加-DWITH_ASAN:STRING=True。
限制与边界
- 只能在 TTY 中做这件事;已有 Hyprland 实例在跑时
make asan会拒绝执行。 - ASan 只作用于 Debug 构建(CMakeLists.txt),Release 构建加
WITH_ASAN不生效。 asan目标会修改本地工作区(应用hyprlandStaticAsan.diff到CMakeLists.txt)并在根目录克隆wayland,完成后如需干净的构建状态,自行还原这些改动。- 该路径产出的报告用于复现崩溃与 issue 提交;报告里记什么、怎么解读,以 ASan 输出内容本身为准,仓库文档未做进一步说明。
【免费下载链接】HyprlandHyprland is an independent, highly customizable, dynamic tiling Wayland compositor that doesn't sacrifice on its looks.项目地址: https://gitcode.com/GitHub_Trending/hy/Hyprland
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考