Don't understand mesa and python overlays in my Flake

I wanted to create a simple project flake for a video with manim. This doesn’t work on my mac for multiple reasons:

  1. moderngl is marked broken on darwin. Nix says it depends on X11, but I think libGL is sufficient.
  2. mesa is marked broken on darwin, which is bad as libGL requires it as a substitute for libglvnd.
  3. screeninfo is also marked broken on darwin. This makes sense, it requires libX11.

I wanted to look at fixing this, and quickly found that the mesa issue is very recent, so I switched to 23.05, unstable has wait for upstream for mesa to be fixed. I then started creating an overlay for these issues, and ended up with this flake:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/23.05";

  outputs = { self, nixpkgs }:
    let
      supportedSystems =
        [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
      forAllSystems = nixpkgs.lib.genAttrs supportedSystems;

      overlay = (final: prev: {
        python3 = prev.python3.override {
          packageOverrides = self: super: {
            moderngl = super.moderngl.overrideAttrs (old: rec {
              buildInputs = [ prev.libGL ]; # Remove X11
              meta = old.meta // { platforms = prev.lib.platforms.all; };
            });
          };
        };
        manim = prev.manim.overrideAttrs (old: {
          propagatedBuildInputs = builtins.filter (x: x.pname != "screeninfo")
            old.propagatedBuildInputs;
        });
      });

      pkgs =
        forAllSystems (system: nixpkgs.legacyPackages.${system}.extend overlay);
    in {
      devShells = forAllSystems (system: {
        default = pkgs.${system}.mkShellNoCC {
          packages = with pkgs.${system}; [ manim ];
        };
      });
    };
}

Unfortunately, when I run nix develop, I still get an error that moderngl is not supported on my platform:

warning: Git tree '/Users/feuh/repos/manim-nix-intro' is dirty
error:
       … while calling the 'derivationStrict' builtin

         at //builtin/derivation.nix:9:12: (source not available)

       … while evaluating derivation 'nix-shell'
         whose name attribute is located at /nix/store/vhq11h949l5zycaw07acphv53ifq4p2c-source/pkgs/stdenv/generic/make-derivation.nix:303:7

       … while evaluating attribute 'nativeBuildInputs' of derivation 'nix-shell'

         at /nix/store/vhq11h949l5zycaw07acphv53ifq4p2c-source/pkgs/stdenv/generic/make-derivation.nix:347:7:

          346|       depsBuildBuild              = lib.elemAt (lib.elemAt dependencies 0) 0;
          347|       nativeBuildInputs           = lib.elemAt (lib.elemAt dependencies 0) 1;
             |       ^
          348|       depsBuildTarget             = lib.elemAt (lib.elemAt dependencies 0) 2;

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: Package ‘python3.10-moderngl-5.8.2’ in /nix/store/vhq11h949l5zycaw07acphv53ifq4p2c-source/pkgs/development/python-modules/moderngl/default.nix:39 is not available on the requested hostPlatform:
         hostPlatform.config = "aarch64-apple-darwin"
         package.meta.platforms = [
           "aarch64-linux"
           "armv5tel-linux"
           "armv6l-linux"
           "armv7a-linux"
           "armv7l-linux"
           "i686-linux"
           "loongarch64-linux"
           "m68k-linux"
           "microblaze-linux"
           "microblazeel-linux"
           "mipsel-linux"
           "mips64el-linux"
           "powerpc64-linux"
           "powerpc64le-linux"
           "riscv32-linux"
           "riscv64-linux"
           "s390-linux"
           "s390x-linux"
           "x86_64-linux"
         ]
         package.meta.badPlatforms = [ ]
       , refusing to evaluate.

       a) To temporarily allow packages that are unsupported for this system, you can use an environment variable
         [ ... etc. ...]

So somehow, the line

              meta = old.meta // { platforms = prev.lib.platforms.all; };

Doesn’t have the desired effect.

I tried the following:

  1. Remove old.meta // → no effect
  2. Use overridePythonAttrs instead of overrideAttrs → no effect
  3. Chaging the filter function to x: !builtins.elem x.pname ["screeninfo" "moderngl" "moderngl_window"] → allowed me to start the build, which has been running for over half an hour before I aborted it. Even if it works, the renderer will be broken as it relies on moderngl
  4. Replace prev.manim with (prev.manim.override { inherit (final) python3; }) in an attempt to force the packageOverrides to be used → no effect

I think I don’t really understand how overlays work, and everything else I try is just throwing stuff at the wall to see if anything sticks. Could someone give me a bit of a direction?

Ok so it seems this definition for the overlay “worked”, as in, it inserted moderngl into manim correctly.

      overlay = (final: prev: {
        glcontext = prev.python3Packages.glcontext.overrideAttrs (old: {
          buildInputs = [ prev.libGL ]; # Remove X11
          postPatch = ''
            substituteInPlace glcontext/egl.cpp \
              --replace '"libGL.so"' '"${prev.libGL}/lib/libGL.so"' \
              --replace '"libEGL.so"' '"${prev.libGL}/lib/libEGL.so"'
          '';
          meta = { platforms = prev.lib.platforms.all; };
        });
        moderngl = (prev.python3Packages.moderngl.override {
          inherit (final) glcontext;
        }).overrideAttrs (old: {
          buildInputs = [ prev.libGL ]; # Remove X11
          meta = { platforms = prev.lib.platforms.all; };
        });

        manim = prev.manim.overrideAttrs (old: {
          propagatedBuildInputs = (builtins.filter (x:
            !builtins.elem x.pname [
              "screeninfo"
              "moderngl"
              "moderngl_window"
            ]) old.propagatedBuildInputs) ++ (with final; [ moderngl ]);
        });
      });

This should still be refined, it’s very ugly that there’s now basically two instances of glcontext and moderngl in nixpkgs.

Also I’m getting build failures. But it’s a start and I think from here I can find a proper solution, maybe even one good enough for merging into nixpkgs. I would still appreciate tips about how to make this nicer, though.

Oh god there is so much broken here.

I could build glcontext and moderngl with the 23.05 nixpkgs now and had to add an overlay for screeninfo, too, but still manim doesn’t build because pyglet, a dependency of moderngl-window, requires many linux-specific libraries as it patches the find_library function. It also relies on Xinerama and other xorg specific stuff, which again leads back to the whole thing that mesa is broken on unstable.

Looking into it further, support for mesa on darwin was actually removed from nixpkgs a few months ago in part because there is an issue upstream that prevents the new versions from building.

So I can absolutely fix glcontext and moderngl, and probably moderngl_window and pyglet as well, but only in 23.05. For unstable and future releases, I’ll have to fix mesa on darwin first.

@yureka, you wrote the PR that sunset mesa on darwin. I would like to try and resurrect that, as I want to run software that requires it. Do you remember what specific issues you had when building? Were dependencies incompatible with the old mesa version?
@vcunat, @primeos, as the maintainers of the mesa package, do you have any reservations against this? I wouldn’t want to start working on this if the chance of it getting merged is low anyway.

I would be willing to add myself as the maintainer for mesa on darwin.

EDIT: Sorry, found the tracking issue. Will post there.

AFAIK the main problems relate to macOS deprecating OpenGL years ago already. But I’m not an Apple person…