How to build emacs using newer version of gtk3

emacs-pgtk has memory leak issue, see Huge memory usage due to emacs child-frame · Issue #7038 · hyprwm/Hyprland · GitHub

I want to use newer version of gtk3 package to deal with this problem. Here are my approaches (both uses overlay):

  emacs-overlay = inputs.emacs-overlay.overlay;
  
  modifications = final: prev: {
    emacs-pgtk = prev.emacs-pgtk.overrideAttrs(f: p: {
      buildInputs = (prev.lib.remove prev.gtk3 p.buildInputs) ++ [
        (prev.gtk3.overrideAttrs(f: p: {
          src = prev.fetchFromGitLab {
            domain = "gitlab.gnome.org";
            owner = "GNOME";
            repo = "gtk";
            rev = "6bb28fca797882a238b41fdaf88dfea8f6b2dfc5"; # 2024.11.16 gtk-3-24 branch
            hash = "sha256-k7G0a/W5LCw/Yto20CYwUZoVh6ebdYIji00JS3RCaQ8=";
          };
        }))
      ];
    });
  };

And my another try:

    emacs-pgtk = prev.emacs-pgtk.overrideAttrs(f: p: {
      buildInputs = with prev; [
        gettext
        gnutls
        (lib.getDev harfbuzz)
        
        libxml2
        ncurses

        gpm

        dbus

        libselinux

        gsettings-desktop-schemas

        glib-networking

        libgccjit
        zlib

        giflib
        (gtk3.overrideAttrs(f: p: {
          src = prev.fetchFromGitLab {
            domain = "gitlab.gnome.org";
            owner = "GNOME";
            repo = "gtk";
            rev = "6bb28fca797882a238b41fdaf88dfea8f6b2dfc5"; # 2024.11.16 gtk-3-24 branch
            hash = "sha256-k7G0a/W5LCw/Yto20CYwUZoVh6ebdYIji00JS3RCaQ8=";
          };
        }))
        xorg.libXpm
        libjpeg
        libpng
        librsvg
        libtiff

        sqlite

        systemd

        tree-sitter

        libwebp
      ];
    });

Note since I don’t want to build many packages so I don’t apply gtk3 overlay globally.

Both approach can build successfully, however, the memory leak still exist.

When I use nix-tree to debug the dependencies, it shows:

From the image you can see that there are two gtk3 package. One is the newer version, the nix-tree shows that its only parent is my emacs-pgtk package, and the other is the version in nixpkgs.

I don’t know why the version in nixpkgs still exist. Does someone know how to solve this issue?

Why not simply override the gtk3 input using .override?

2 Likes

Sorry for the late reply, I just tested the following code using .override:

      emacs-pgtk = prev.emacs-pgtk.override ({
        gtk3 = (prev.gtk3.overrideAttrs ({
          src = prev.fetchFromGitLab {
            domain = "gitlab.gnome.org";
            owner = "GNOME";
            repo = "gtk";
            rev = "6bb28fca797882a238b41fdaf88dfea8f6b2dfc5"; # 2024.11.16 gtk-3-24 branch
            hash = "sha256-k7G0a/W5LCw/Yto20CYwUZoVh6ebdYIji00JS3RCaQ8=";
          };
        }));
        });

A weird thing is that after building, there is only one gtk3, but this gtk3 is from nixpkgs, not my custom build gtk3.

I’ve also tried to replace prev.emacs-pgtk.override with prev.emacs30-pgtk.override, however, it doesn’t trigger build process for emacs (i.e. there is no new system generation)

This looks correct to me, something else must be amiss then.

As a sanity check, could you try substituting a throw for gtk3 or its src? If it gets thrown, it at least gets eval’d.

How exactly are you applying this overlay and how are you building emacs-pgtk from it in order to verify?

How are you determining which gtk3 is used?

1 Like

Thanks for your advice! I tried to throw at gtk.src level, and now find that my later modification of code result in

modification = {
  modification = {
    emacs-pgtk = {
    }
  }
}

shame (ノ ゜Д゜)ノ ︵ ┻━┻


How exactly are you applying this overlay and how are you building emacs-pgtk from it in order to verify?

The scheme I used to apply overlay is very similar to nix-starter-configs. So for this case, everything under modification are applied.

How are you determining which gtk3 is used?

nix-tree shows this at the bottom:


I’d like to have a dinner meanwhile wait the now triggered build process finish to see the result. Thank you!

After the build, now it again has two gtk3 dependencies:

I tested it, everytime I use corfu to show a completion in a childframe, the .Hyprland-wrapper process catch the memory leak, leading to a memory increase of ~17mb

I’m not quite sure what you mean by this?

I’m not familiar with that project.

What does it mean when you say “everything under modification is applied”? The snippet you pasted looks like it’s part of an overlay declaration for pkgs.

Hm, odd. Perhaps it’s being propagated from one of the buildInputs. You’d have to check each one’s nix-support directory.

I’m not quite sure how you’d override that however. It’d probably be best to create a new instance of pkgs for this where gtk3 is simply overlaid globally.

You may want to try this nuclear solution

{
  programs.emacs = {
    enable = true;
    package = with import pkgs.path {
      system = "x86_64-linux";
      overlays = [
        (final: prev: {
          gtk3 = prev.gtk3.overrideAttrs {
            src = final.fetchFromGitLab {
              domain = "gitlab.gnome.org";
              owner = "GNOME";
              repo = "gtk";
              rev =
                "6bb28fca797882a238b41fdaf88dfea8f6b2dfc5"; # 2024.11.16 gtk-3-24 branch
              hash = "sha256-k7G0a/W5LCw/Yto20CYwUZoVh6ebdYIji00JS3RCaQ8=";
            };
          };
        })
      ];
    };
      emacs30-pgtk; # or (emacsPackagesFor emacs30-pgtk).withPackages (epkgs: []);
  };
}

The main point is, though not advised, you can have:

let
  myPkgs = import pkgs.path {
    system = "x86_64-linux";
    overlays = [ ... ];
  };
in ...
1 Like