Improving an emscripten/yarn dev shell flake

I have two questions about how to make a dev shell, that’s already working, a little bit better.

I setup a the-nix-way template flake with the mkShell in order to setup a build environment for a non-nix project, that’s using yarn and emscripten. It’s quite simple:

{
  description = "A Nix-flake-based Node.js development environment";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";

  outputs = { self, nixpkgs }:
    let
      overlays = [
        (final: prev: rec {
          nodejs = prev.nodejs-18_x;
          pnpm = prev.nodePackages.pnpm;
          yarn = (prev.yarn.override { inherit nodejs; });
        })
      ];
      supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
      forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
        pkgs = import nixpkgs { inherit overlays system; config.allowUnfree = true; };
      });
    in
    {
      devShells = forEachSupportedSystem
        ({ pkgs }: {
          default = pkgs.mkShell
            {
              packages = with pkgs; [ node2nix nodejs pnpm yarn emscripten python310 steam-run ];
              shellHook = ''
                if [ ! -d $(pwd)/.emscripten_cache ]; then
                  cp -R ${pkgs.emscripten}/share/emscripten/cache/ $(pwd)/.emscripten_cache
                  chmod u+rwX -R $(pwd)/.emscripten_cache
                  export EM_CACHE=$(pwd)/.emscripten_cache
                fi
              '';
            };
        });
    };
}

The first question is related to the shellHook. This seems to be related to a known “fixed” issue. A similar problem was originally described here, although wasn’t fixed for shell environments. The patch only seems to fix the cases when using specific emscripten packages.

Is this the type of thing I should send a PR against the emscripten package to define the shellHook there? I’m guessing if it was that simple, it would’ve been done as part of the 172207 PR, but not really sure. Figured I’d ask here first.

My second question is around steam-run usage. I end up having to run yarn compile to build the project, which will fail because it eventually runs a locally built non-nixified-binary via npx. I package steam-run in the flake so that I can simply do steam-run yarn compile to get around this, but I’m curious if there is some cleaner way so that one can just run the intended build commands without the steam-run prefix?

Thanks.

I didn’t think about the shellHook only because of not thinking about it — at first glance I see no reason why this wouldn’t work, though it might be good to create some kind of test case to ensure that this stays functional on multiple systems! I think I’ve just been doing this manually on my project because in some reason I assumed it would always have to be user-specified.

To be clear, though, the reason for this writable cache is to serve this exact process, so I appreciate the improvement!

Great thanks. I’ll take a look at sending a PR and setting up some kind of test. Will be a good opportunity to understand how Nix testing works.

I’ve finally had a bit of time to look into doing this, but admittedly I’m way out of my depth still so mostly just swimming in new info.

I’m curious if it is actually possible to have a shellHook from another package trigger just from marking it as a package dependency in a mkShell call, or do you have to specify it as a buildInput in order for it to trigger?

Another question is, given emscripten is currently just a default.nix file with a single call to stdenv.mkDerivation, I’m not entirely sure how to best restructure it to include a shellHook for mkShell use specifically? I didn’t see any obvious examples of this being done elsewhere in nixpkgs, although I imagine I’m just missing something.

Will keep slowly reading up on things, but any insights welcome.

@fidgetingbits Thanks for posting this template flake – it has been very helpful for me. I ran into one issue with it, though: it only works the first time I run nix develop; on subsequent runs, it doesn’t.

The problem is that the export EM_CACHE is inside of the if statement. After I moved it outside, then it worked fine every time I ran nix develop.

2 Likes