nixpkgs 中 WeeChat 的 override 定制机制:按插件裁剪闭包、注入 Python 库与启动脚本
【免费下载链接】nixpkgsNix Packages collection & NixOS项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgs
在 nixpkgs 中,WeeChat 默认会编译并打包所有可用插件,这会让它的 closure(依赖闭包)变得偏大。本文以 doc/packages/weechat.section.md 为主体,完整讲解 WeeChat 的override { configure }定制机制:如何通过availablePlugins精确选择插件以缩减闭包、如何用withPackages为 Python/Perl 插件额外注入第三方库、如何用init传递--run-command启动命令、如何用scripts声明 WeeChat 脚本,以及如何编写符合 nixpkgs 规范的 WeeChat 脚本 derivation(passthru.scripts与$out/share约定)。读完后你可以复制即用这些表达式,并在需要时深入脚本打包的底层约定。
一、为什么需要 override 定制:默认全量插件的代价
WeeChat 是一个终端 IRC/聊天客户端,功能依赖插件提供。在 nixpkgs 里,若不额外配置,它会把python、perl、ruby、guile、tcl、lua等所有可用插件都构建进去,导致安装时把整套解释器及相关依赖都拉进闭包,体积和构建耗时都上升。
官方文档给出的解法是通过包对象的override方法注入一个configure函数,覆盖其默认配置。这是 WeeChat 定制的核心入口——后续所有“选插件、加库、加命令、加脚本”的操作,都是在configure返回的 attrset 里完成的。
当前仓库中 WeeChat 是一个真实存在的包:例如 pkgs/by-name/we/weechat-matrix-rs/package.nix 将weechat作为buildInputs之一,并把矩阵插件库移动到$out/lib/weechat/plugins/matrix<sharedLibrary>,这正说明了 WeeChat 插件被放置在lib/weechat/plugins下的运行时布局,也从侧面印证了“按需裁剪插件”对控制闭包体积的实际意义。
二、按 availablePlugins 选择插件,缩减闭包体积
configure函数接收一个包含availablePlugins的参数集,availablePlugins是一个以插件名为键、以对应插件 derivation 为值的 attrset。通过plugins属性给出你实际需要的插件列表,即可只构建这些插件:
weechat.override { configure = ( { availablePlugins, ... }: { plugins = with availablePlugins; [ python perl ]; } ); }要点:
with availablePlugins; [ python perl ]等价于[ availablePlugins.python availablePlugins.perl ],用with让表达式更简洁。plugins是一个 derivation 列表,最终决定 WeeChat 构建时链接哪些插件。
文档明确说明:若configure返回的 attrset 中没有plugins属性,则会自动使用availablePlugins(即全部插件)。这意味着你只要提供一个不触及plugins的configure,WeeChat 就会退回“全量插件”的默认行为,行为与不定制一致。
当前可用的插件为:python、perl、ruby、guile、tcl和lua。从源码结构看,这些名字正是availablePluginsattrset 的键,按需取用即可。
三、用 withPackages 为 Python / Perl 插件注入额外库
python和perl插件支持“追加额外库”的能力。典型场景来自 doc/packages/weechat.section.md 描述的weechat-scripts生态:
inotify.py脚本需要 D-Bus 或 libnotify;fish.py脚本需要pycrypto。
要满足这些脚本的运行期依赖,使用插件的withPackages属性,把第三方 Python 包“包裹”进该插件 derivation:
weechat.override { configure = { availablePlugins, ... }: { plugins = with availablePlugins; [ (python.withPackages ( ps: with ps; [ pycrypto python-dbus ] )) ]; }; }其中python.withPackages (ps: ...)返回一个“带额外 Python 包”的新插件 derivation,参数ps就是可用的 Python 包集合,with ps; [ pycrypto python-dbus ]在其中挑选pycrypto与python-dbus。Perl 插件同理可用perl.withPackages(对应 Perl 模块集合)。
这一机制的本质是:插件自身就是一个可再 override 的对象,withPackages在插件层面追加解释器的运行依赖,而不影响主包的其它部分,从而把“插件需要哪些库”与“客户端主体”解耦。
四、保留全部默认插件的同时为部分插件追加库
上面的写法会“替换”整个plugins列表。如果你的需求是“保留全部默认插件,同时给python插件额外加上库”,文档给出了一种 attrset 覆盖技巧——先用//覆盖对应键,再用builtins.attrValues摊平回列表:
weechat.override { configure = { availablePlugins, ... }: { plugins = builtins.attrValues ( availablePlugins // { python = availablePlugins.python.withPackages ( ps: with ps; [ pycrypto python-dbus ] ); } ); }; }逐行理解:
availablePlugins // { python = ... }:以//(attrset 更新)的方式,仅把python键替换为“带额外库”的版本,其余键(perl、ruby等)保持原值。builtins.attrValues (...):把 attrset 的所有值摊平为列表,还原成plugins要求的 derivation 列表形态。
这样就实现了“全量插件 + 单插件增强”的折中方案,既控制住了python的依赖,又保留了其它插件的完整能力。
五、用 init 传递 --run-command 启动命令
WeeChat 支持通过--run-command在启动时执行默认命令。configure中的init属性就是用来承载这些命令的,init的值是一段字符串(''...''),里面写 WeeChat 的斜杠命令,例如设置变量、添加服务器:
weechat.override { configure = { availablePlugins, ... }: { init = '' /set foo bar /server add libera irc.libera.chat ''; }; }文档补充说明:这些命令等价于运行时执行weechat --run-command "your-commands"时传入的命令列表;在打包阶段写入init,则每次启动 WeeChat 都会自动带上这些配置,无需手动在终端敲命令。
六、用 scripts 声明启动时加载的 WeeChat 脚本
除了命令,你还可以指定一组在 WeeChat 启动时加载的脚本。文档强调这些脚本会在init中的命令之前加载,因此脚本负责安装/注册,而init里再针对这些脚本做配置项(/set plugins.var...)的设置:
weechat.override { configure = { availablePlugins, ... }: { scripts = with pkgs.weechatScripts; [ weechat-xmpp weechat-matrix-bridge wee-slack ]; init = '' /set plugins.var.python.jabber.key "val" ''; }; }要点:
scripts是一个 derivation 列表,这里从pkgs.weechatScripts这个“脚本子包”中挑选weechat-xmpp、weechat-matrix-bridge、wee-slack。- 加载顺序为:先加载
scripts中列出的脚本,再执行init中的命令。上例中init里设置 jabber 的 key,正是依赖 xmpp 脚本已经加载完成后的配置项路径。 - 从仓库结构看,
weechatScripts是 nixpkgs 中专门存放 WeeChat 脚本 derivation 的子包,weechat-matrix-rs(见 pkgs/by-name/we/weechat-matrix-rs/package.nix)这类依赖weechat的插件/脚本正是这一生态的组成部分。
七、编写 WeeChat 脚本 derivation 的约定:passthru.scripts 与 $out/share
当你需要打包一个不在weechatScripts子包中的 WeeChat 脚本时,需要遵循 nixpkgs 的脚本 derivation 约定。文档给出的要求是:
- derivation 必须提供一个
passthru.scripts属性,内容是“store 路径内所有脚本”的文件名列表; - 所有脚本必须最终落在
$out/share目录下。
一个示例 derivation 如下:
{ stdenv, fetchurl }: stdenv.mkDerivation { name = "exemplary-weechat-script"; src = fetchurl { url = "https://scripts.tld/your-scripts.tar.gz"; hash = "..."; }; passthru.scripts = [ "foo.py" "bar.lua" ]; installPhase = '' runHook preInstall mkdir $out/share cp foo.py $out/share cp bar.lua $out/share runHook postInstall ''; }要点解析:
passthru.scripts = [ "foo.py" "bar.lua" ]:声明本次 derivation 携带了哪些脚本文件,nixpkgs 的 WeeChat 脚本聚合逻辑会依据这个列表去识别与注册脚本。installPhase里mkdir $out/share后把脚本复制到$out/share,满足“所有脚本都必须在$out/share”的约定;runHook preInstall/runHook postInstall是 stdenv 的标准 hook 调用,保证安装阶段前后的通用逻辑不被绕过。- 由于脚本最终位于
$out/share且文件名与passthru.scripts对应,WeeChat 运行时才能正确发现并加载它们。
这条约定解释了为何文档中scripts属性可以直接接受一个 derivation:nixpkgs 依赖passthru.scripts+$out/share这两个信号,把任意符合约定的 derivation 识别成一组可被 WeeChat 加载的脚本。
八、定制机制小结与适用前提
把 doc/packages/weechat.section.md 的内容串起来,WeeChat 的定制完全围绕override { configure }展开,configure返回的 attrset 里三类关键属性各司其职:
plugins:决定构建/链接哪些插件(缺省时自动使用全部availablePlugins);python/perl插件可再用withPackages追加解释器依赖。init:一段 WeeChat 斜杠命令字符串,等价于启动时的--run-command。scripts:启动时先于init加载的 WeeChat 脚本 derivation 列表,脚本需满足passthru.scripts与$out/share约定。
适用前提与限制:
- 上述表达式都依赖 nixpkgs 中 WeeChat 包暴露
override { configure }接口,且availablePlugins的键为python、perl、ruby、guile、tcl、lua。若上游接口或可用插件集合发生变化,应以当前仓库实际包定义为准。 withPackages仅对python与perl插件有意义(对应解释器的包集合),其余插件按文档描述不涉及该机制。- 脚本加载顺序(先
scripts后init)决定了“脚本负责安装、init负责设置配置项”的分工,编写脚本相关init命令时应以此顺序为前提。
通过本文的四个可复制表达式(选插件、加库、保留全量插件、传启动命令)与一个脚本 derivation 模板,你可以在 nixpkgs 里把 WeeChat 配置成既精简又满足脚本依赖的定制版本,并在需要时按仓库约定自行打包新的 WeeChat 脚本。
【免费下载链接】nixpkgsNix Packages collection & NixOS项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考