我正在NixOS上运行Haskell项目(使用stack
),该项目利用了XDG_RUNTIME_DIR
(以防万一:这是一个运行X11后端的Wayland合成器项目)。当我的程序启动时:
stack exec my-compositor-project-exe # nix is enabled by default
我得到一个错误:
error: XDG_RUNTIME_DIR not set in the environment
但是如果我使用--no-nix-pure
,我不会收到错误消息:
stack --no-nix-pure exec my-compositor-project-exe
# ... no error ...
但这真的是解决此错误的最佳方法吗?
请注意,当我在NixOS终端中运行echo $XDG_RUNTIME_DIR
时,会得到
echo $XDG_RUNTIME_DIR
/run/user/1000
当我在Haskell堆栈项目中运行nix-shell
时,我也会得到
[nix-shell:~/my-project]$ echo $XDG_RUNTIME_DIR
/run/user/1000
所以我完全收到此错误是一个谜。
问题:解决此问题的正确方法是什么?
在重要的情况下,here是有关$XDG_RUNTIME_DIR
含义的一些信息:
只有一个基本目录,应将相对于该基本目录的用户特定的运行时文件和其他文件对象放置在该目录中。此目录由环境变量$ XDG_RUNTIME_DI定义。
...
$ XDG_RUNTIME_DIR定义了基本目录,相对于该基本目录,应存储用户特定的非必需运行时文件和其他文件对象(例如套接字,命名管道等)。该目录必须归用户所有,并且他必须是唯一拥有对该目录的读写权限的目录。其Unix访问模式必须为0700。
...
如果未设置$ XDG_RUNTIME_DIR,则应用程序应回退到具有类似功能的替换目录并打印警告消息。应用程序应将此目录用于通讯和同步目的,并且不应在其中放置较大的文件,因为它可能驻留在运行时内存中,不一定能换出到磁盘。
程序中产生错误的特定FFI调用是对wl_display_add_socket
(wayland函数)的调用,该调用位于其主体顶部:
WL_EXPORT int
wl_display_add_socket(struct wl_display *display, const char *name)
{
runtime_dir = getenv("XDG_RUNTIME_DIR");
if (!runtime_dir) {
wl_log("error: XDG_RUNTIME_DIR not set in the environment\n");
/* to prevent programs reporting
* "failed to add socket: Success" */
errno = ENOENT;
return -1;
}
//...
}
答案 0 :(得分:1)
您已经注意到,Stack中的Nix纯度功能并非对所有功能都有效。某些程序与它们的环境进行交互只需要一些环境变量,因此在纯模式下使用Nix集成是没有意义的。我的看法是,--nix-pure
通常仅适合于编译,并且顺便适用于某些简单程序。
如果您喜欢冒险,可以尝试在shell.nix
中显式传递环境变量,方法是将以下行添加到shell派生中:
XDG_RUNTIME_DIR = builtins.getEnv "XDG_RUNTIME_DIR"
但是,我不会打扰,只用stack exec
叫--no-nix-pure
。