在 Haskell Stack+Nix 项目中设置 XDG_RUNTIME_DIR

Setting XDG_RUNTIME_DIR in a Haskell Stack+Nix Project

问题

我正在 运行NixOS 上的一个 Haskell 项目(使用 stack),它使用了 XDG_RUNTIME_DIR(以防万一:它是一个 wayland 合成器项目运行s 使用 X11 后端)。当我的程序启动时:

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

当我 运行 nix-shell 在我的 Haskell 堆栈项目中时,我也得到

[nix-shell:~/my-project]$ echo $XDG_RUNTIME_DIR
/run/user/1000

所以我为什么会收到这个错误完全是个谜。

问题:解决这个问题的正确方法是什么?

上下文

以防万一 here 是关于 $XDG_RUNTIME_DIR 含义的一些信息:

There is a single base directory relative to which user-specific runtime files and other file objects should be placed. This directory is defined by the environment variable $XDG_RUNTIME_DI.

...

$XDG_RUNTIME_DIR defines the base directory relative to which user-specific non-essential runtime files and other file objects (such as sockets, named pipes, …) should be stored. The directory MUST be owned by the user, and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700.

...

If $XDG_RUNTIME_DIR is not set applications should fall back to a replacement directory with similar capabilities and print a warning message. Applications should use this directory for communication and synchronization purposes and should not place larger files in it, since it might reside in runtime memory and cannot necessarily be swapped out to disk.

我的程序中产生错误的特定 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;
  }
  //...
}

如您所见,Stack 中的 Nix 纯度功能并非适用于所有情况。某些程序只需要一些环境变量来与其环境交互,因此在纯模式下使用 Nix 集成没有意义。我的看法是,--nix-pure 通常只适用于编译,顺便说一句,它适用于一些简单的程序。

如果您喜欢冒险,可以尝试通过 shell.nix 显式传递环境变量,方法是将此行添加到 shell 推导中:

    XDG_RUNTIME_DIR = builtins.getEnv "XDG_RUNTIME_DIR"

但是,我不会打扰,只是用 --no-nix-pure 调用 stack exec