NixOS 下 Emacs 声明式管理第三方库配置的坑

用的 NixOS, 使用 emacs-overlay

之前和现在的配置:

diff --git a/home/modules/applications/misc/emacs.nix b/home/modules/applications/misc/emacs.nix
index 4360950e23..7e581a2b49 100644
--- a/home/modules/applications/misc/emacs.nix
+++ b/home/modules/applications/misc/emacs.nix
@@ -13,10 +13,11 @@
 
   config = lib.mkIf cfg.enable {
     home.packages = with pkgs; [
-      emacs-pgtk
+      ((emacsPackagesFor emacs-pgtk).emacsWithPackages (epkgs: with epkgs; [
+        jinx
+        mu4e
+      ]))
       emacs-lsp-booster
-      emacsPackages.jinx
-      emacsPackages.mu4e
       sqlite # ekg needs it
 
       # wakatime # wakatime plugin needs it (it calls wakatime-cli)

之前一直有 compatSymbols function definition is void 的问题,我用的是 把 compat 加入 native-comp 的禁止名单中解决的,所以一直以为是 内置的compat 库在最新的 master 分支上存在问题:

今天我查了下 emacs bug archive, 纳闷为什么还没有人提这个 bug, 便检查了下配置,发现是版本不对应的问题,就进行了修改。想到坛友也可能遇到这个问题,遂分享。


我还以为加了Emacs Overlay 之后第三方 Emacs 库中的 Emacs 依赖也会随之更改,没想到不会 :sweat:

1 个赞

熟悉的 emacsPackagesFor emacs-pgtk

不过你都既然这样用了,像我一样就只用 nixpkgs 不导入 emacs-overlay 了

我猜 emacs-overlay 的主要目的是通过 elisp 安装 melpa package ,提供 emacs-git 和 emacs-unstable

我在macOS上遇到过,某些包通过nix 声明式安装会导致找不到autoloads,例如 diff-hl,不知道有没有大佬遇到过,有没有解决方法(纯萌新,就喜欢瞎折腾 :rofl:),感谢任何建议

你提的 autoloads 是指 emacs 下找不到依赖的 bin 程序吗?

如果是这样,检查 emacs 里 exec-path 变量的值与 shell 里是否有差异。

通过图形环境启动的 emacs 不一定会去读 .bashrc 里的 PATH 配置。

我用 emacs-overlay 主要是为了能体验到最新版本的 emacs。emacs-overlay 提供了挺多包的: emacs-overlay/overlays/emacs.nix at dfbc53025ea2527fbf2aca46be92cf725360f4a9 · nix-community/emacs-overlay · GitHub

我用 Nix 安装 Emacs,但是基本不用 Nix 管理 Emacs package,原因是:

  • Nix 的只读特性使得我遇到上游 bug 时想微调一个 package 变得很困难。
  • 新增/升级/删除一个包需要重新构建 Nix profile,相对来说比较麻烦。
  • 版本可控性没有那么自由。

只有 gn-mode-from-source 这种找不到对应 git 仓库也不在 Melpa 上的包我才会用 Nix 管理。

如果楼主不那么追求 Nix 一统全局,不妨考虑一下,没必要给自己增加很多额外的麻烦。

1 个赞

我也基本不用 Nix 管理 Emacs 包,除了几个像jinx, mu4e这种包,他们需要编译一些C文件。如果引用了第三方库的头文件,在nix环境下编译就比较麻烦了,需要修改环境变量LD_LIBRARY_PATH来让 ld linker 能够找到文件,或者用 patchelf 来把第三方库打包进可执行文件中。而 jinx 就用到了 enchant 库。对于这种包,在 nix 环境下,还是用nixpkgs的版本比较好。

Jinx, Vterm 这种我也是优先自己写 default.nix 来打包,其实并不复杂,你可以直接抄 Nixpkgs 里面的源码

1 个赞

给一个参考:

我是直接将他们加到 home.packages 下,这样可以在 ~/.nix-profiles/share/emacs/site-lisp 目录下找到。然后 Emacs 端加入配置:

这段代码用于处理 NIX_PROFILES 环境变量,并添加相关路径到 load-path。逻辑基本是从 site-start.el(如果你是 Nix 安装的 Emacs,这个文件里应该有一些 Nix 相关的处理逻辑)里面抄的。

2 个赞

这样做感觉有点复杂了,还是 nixpkgs 的方法方便。<3

1 个赞

最近开始玩 nixos。

之前一直没有上手玩 nixos 的主要原因就是担心无 FHS 会导致这些要编译的包用不了,得专门在 nix 里装包。而我又不想把我的配置割裂,希望用 emacs 统一管理我的包,不想把 emacs 包委托给别的工具管理。

结果上手了以后我才发现 vterm 直接用 straight 装就可以了啊。甚至 pdftools 也是如此,就是平平无奇的直接用 straight 就装上了。不需要任何在 nix 端的配置,不需要用 nix 装这些包,也不需要写任何的 nix lang,就是在 systemPackage 里把 emacs 加进去就完事了。

1 个赞

这个挺意外的,编译 vterm 需要安装 libvterm 和 cmake,没有的话理论上没法儿自动编译🤔

这些有 C/C++ 库依赖的 Emacs 包都有专门打包的。感觉 Nix 和 Emacs 用户重合度挺高的,所以 Nix 的 Emacs 基础设施其实做的很不错。

cmake肯定要装的,不装没发编包不是。libvterm不用下;它会自己去下载源码从头编译。

然后我看了下 pdf-tools 是因为作者在makefile里写了 nix-shell 编译的脚本。但是它也没有任何的 hack的技巧,就是 patchelf 改 LDPATH 之类的都不需要。就是在 nixshell 里把 poppeler 之类的依赖装了然后包就直接编译通过了。

装完之后 ldd 这些编好的 so 看了下,都 link 到 /nix/store里去了。