I am running a Haskell project on NixOS (using stack
) that makes use of XDG_RUNTIME_DIR
(in case it matters: it's a wayland compositor project that runs with an X11 backend). When my program launches:
stack exec my-compositor-project-exe # nix is enabled by default
I get an error:
error: XDG_RUNTIME_DIR not set in the environment
However if I run with --no-nix-pure
, I don't get an error:
stack --no-nix-pure exec my-compositor-project-exe
# ... no error ...
But is that really the best way to fix this error?
Note that when I run echo $XDG_RUNTIME_DIR
in a NixOS terminal I get
echo $XDG_RUNTIME_DIR
/run/user/1000
and when I run nix-shell
within my Haskell stack project I also get
[nix-shell:~/my-project]$ echo $XDG_RUNTIME_DIR
/run/user/1000
so it's quite a mystery why I get this error at all.
Question: What is the proper way to solve this problem?
In case it matters here is some information about about what $XDG_RUNTIME_DIR
means:
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.
The specific FFI call in my program which yields the error is a call to wl_display_add_socket
(wayland function) which has at the top of its body:
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;
}
//...
}
The Nix purity feature in Stack doesn't work for everything, as you have noticed. Some environment variables are simply required for certain programs to interact with their environment, so it doesn't make sense to use the Nix integration in pure mode. The way I see it, is that --nix-pure
is generally only suitable for compilation and incidentally works for some simple programs.
If you feel adventurous, you could try to explicitly pass environment variables through your shell.nix
, by adding this line to your shell derivation:
XDG_RUNTIME_DIR = builtins.getEnv "XDG_RUNTIME_DIR"
However, I wouldn't bother and just call stack exec
with --no-nix-pure
.