devenv icon indicating copy to clipboard operation
devenv copied to clipboard

Wrapping `devenv shell` in a FHS environment?

Open shymega opened this issue 1 year ago • 9 comments

Hi!

I'm working on a Rust Steam Play tool, and I'm trying to wrap devenv shell in an FHS environment, for Proton. It doesn't run otherwise.

I've tried using pkgs and inputsFrom to get this working, to no avail.

Is it possible to wrap devenv into a FHS environment?

Thanks.

shymega avatar Aug 20 '24 15:08 shymega

~~Actually, I think I've found the issue. It was my Nix derivation.~~

Regardless, using devenv as a shell wrapped in FHS might be useful. Is it worth opening a feature request for?

EDIT: I've fixed the Nix derivation, but running cargo build inside devenv, then running the executable fails. No idea if this is normal behaviour.

shymega avatar Aug 20 '24 15:08 shymega

I don't think anyone has really tried this.

You can override shell and replace the default mkShell implementation with buildFHSEnv.

{ pkgs, lib, config, inputs, ... }:

{
  env.HELLO = "WORLD";

  packages = [
    pkgs.hello
  ];

  shell = lib.mkForce (pkgs.buildFHSEnv {
    name = "devenv-shell";
    targetPkgs = _: config.packages;
    runScript = "bash";
    profile = ''
      ${lib.optionalString config.devenv.debug "set -x"}
      ${config.enterShell}
    '' + lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: ''
      export ${name}=${value}
    '') config.env);
  }).env;
}

This seems to work as expected:

which hello
/usr/bin/hello

But direnv fails to launch this shell, so the question is what else does this break.

Another approach would be to wrap just the binary in a buildFHSEnv. Maybe there's a way to leverage scripts for this?

sandydoo avatar Aug 23 '24 09:08 sandydoo

Yeah, I get the following error from direnv - do you as well?

Would it be a good idea to open a feature request?

direnv: loading ~/projects/git.shymega.org.uk/DeckCheatz/DeckCheatz/.envrc
direnv: loading https://raw.githubusercontent.com/cachix/devenv/95f329d49a8a5289d31e0982652f7058a189bfca/direnvrc (sha256-d+8cBpDfDBj41inrADaJt+bDWhOktwslgoP5YiGJ1v0=)
direnv: using devenv
direnv: .envrc changed, reloading
• Using Cachix: devenv
[1/0/7 built] building python3.11-aiohttp-3.9.3 (buildPhase): cython -3 -o aiohttp/_websocket.c aiohttp/_websocket.pyx -I aiohttp -Werrodirenv: ([/nix/store/ic11r65mm23k23jf6k1bcnvxwssl4sk7-direnv-2.34.0/bin/direnv export zsh]) is taking a while to execute. Use CTRL-C to give up.
direnv: updated devenv shell cache
pre-commit-hooks.nix: updating /home/dzrodriguez/projects/git.shymega.org.uk/DeckCheatz/DeckCheatz repo
pre-commit installed at .git/hooks/pre-commit
✨ devenv 1.0.8 is newer than devenv input in devenv.lock. Run `devenv update` to sync.
mkdir: cannot create directory ‘’: No such file or directory
/etc/profile: line 154: export: `-C': not a valid identifier
/etc/profile: line 154: export: `link-arg=-fuse-ld=mold': not a valid identifier
/etc/profile: line 156: export: `-C': not a valid identifier
/etc/profile: line 156: export: `link-arg=-fuse-ld=mold': not a valid identifier
✨ devenv 1.0.8 is newer than devenv input in devenv.lock. Run `devenv update` to sync.
bash: export: `-C': not a valid identifier
bash: export: `link-arg=-fuse-ld=mold': not a valid identifier
bash: export: `-C': not a valid identifier
bash: export: `link-arg=-fuse-ld=mold': not a valid identifier

shymega avatar Aug 23 '24 09:08 shymega

I got:

/home/sandydoo/.cache/direnv/cas/77ef1c0690df0c18f8d629eb003689b7e6c35a13a4b70b258283f9622189d6fd:1997: DISPLAY: unbound variable
direnv: error exit status 1

Would it be a good idea to open a feature request?

You can keep this issue open as well.

@domenkozar and I briefly discussed this and we're unlikely to want to implement and maintain this because of the lack of support on macOS. Maybe we can come up with docs on how to work around this, either using the above shell override or by providing instructions on how to wrap specific binaries.

sandydoo avatar Aug 23 '24 11:08 sandydoo

I'd also like to be able to do that. I have a project with pre-commit configured (through .pre-commit-config.yaml). Every hook works fine except the ruff hook, because of the linker.

Switching to devenv's pre-commit system is not an option, because my colleagues don't use nix (yet ;-) ).

I have experimenting with nix-ld but without full success (running ruff directly in the commandline using the absolute path in ~/.cache/precommit works fine, but for some reasons it fails with error -11 when executing it through pre-commit run or through the hook).

My idea would have been to fix that using a FHS env.

autra avatar Sep 29 '24 13:09 autra

I hope FHS could be supported, cause its tedious to setup those lsp, and python conda also depend on fhs env and there are some dependencies requirements I meet before just cant resolve by poetry.

deng232 avatar Nov 10 '24 00:11 deng232

I think, if macOS is the blocker, could we add a conditional to the shell side of things that checks the pkgs.system attribute, and enables/disables based on this?

shymega avatar Dec 07 '24 21:12 shymega

Alright then let's get it in, as long as it errors out with a clear message that macOS isn't supported and what are the alternatives.

domenkozar avatar Dec 09 '24 11:12 domenkozar

SGTM.

Can you link the PR here if it does created?

shymega avatar Dec 24 '24 19:12 shymega

Hello, I hope it's ok for me to share my experience here.

I've been trying to create a development environment for my Bazel project in NixOS. I've tried to use devenv for this because it looked like a good way to make my environment reproducible and easily shareable with other people using other OS. But I keep getting a lot of errors like the following:

Could not start dynamically linked executable: external/rules_doxygen~~doxygen_extension~doxygen/linux/doxygen
NixOS cannot run dynamically linked executables intended for generic
linux environments out of the box. For more information, see:
https://nix.dev/permalink/stub-ld

I think it's relevant for this issue since I assume that if I could somehow tell devenv to use a FHS env for this particular project that I'm working on then my problems would be gone.

If you could add this type of feature it would be great.

PS: it could be that I'm unaware of an existing fix for my problem. In that case, please forgive me and if it's not too much trouble I would appreciate it very much if you could create an example for a bazel-based project in the guide/tutorial/examples.

calmette54 avatar Apr 04 '25 04:04 calmette54

Alright then let's get it in, as long as it errors out with a clear message that macOS isn't supported and what are the alternatives.

I wonder. Would you not also want an option to make the error optional?

I imagine one of the main goals here would be to make building and compilation work out the box on a NixOS system. i.e. If I enter a directory, I can build and run a project without any manual configuration.

In my case, I got here because I wanted to develop C# .NET code on Avalonia (UI Toolkit). This is something I do at work every week (and also Open Source). Running Avalonia binaries requires a FHS environment to load some system dependencies like fontconfig, x11, etc. as .NET's own package management will pull in unpatched native binaries during the build process.

The caveat is, on macOS (and most non-NixOS setups) the equivalent of those dependencies would already be pre-installed as part of the OS. Therefore chances are things would just work out of the box in that context; and throwing an error would be undesirable; even if it's not purely the nix way of declaring every dependency.

Sewer56 avatar Aug 19 '25 20:08 Sewer56

I got mine working like this

{
  pkgs,
  lib,
  config,
  inputs,
  ...
}:
let
  pkgs-unstable = import inputs.nixpkgs-unstable { system = pkgs.stdenv.system; };
  base = pkgs-unstable.appimageTools.defaultFhsEnvArgs;
  fhs = pkgs-unstable.buildFHSEnv (
    base
    // {
      name = "fhs";
      targetPkgs =
        pkgs:
        (base.targetPkgs pkgs)
        ++ (with pkgs; [
          pkg-config
          ncurses
          linuxHeaders
          gcc
        ]);
      profile = "export FHS=1";
      runScript = "bash";
    }
  );
in
{
  env.GREET = "devenv";

  packages = [
    pkgs-unstable.linuxHeaders
    fhs
  ];
  languages.python.enable = true;
  languages.python.package = pkgs-unstable.python310;
  languages.javascript.enable = true;
  languages.javascript.package = pkgs-unstable.nodejs_22;

  enterShell = ''
    fhs -c '
      fish -C "
        which python;
        which node;
        python --version;
        node --version
      " && exit
    '
    exit
  '';

}

youyoumu avatar Sep 13 '25 13:09 youyoumu

Would be cool to turn that into a module so you can do:

{
  fhs.myfhs.packages = [ ... ];
}

And then

$ devenv shell - myfhs -c  echo hello

domenkozar avatar Oct 31 '25 22:10 domenkozar

Yeah, I get the following error from direnv - do you as well?

I don't think FHS envs are compatible with direnv's model. For a normal nix-shell, it runs something like nix-shell --run "direnv dump", and the loads the resulting environment variables into your shell. But (buildFHSEnv (...)).env has a shellHook that will cause nix-shell to execute a bwrap command. This involves a bunch of setup beyond just editing environment variables, so I'm afriad its incompatible with direnv's load/unload model.

spencerpogo avatar Nov 05 '25 19:11 spencerpogo