Thunar custom build with flags and plugins

I want to have thunar with flags and plugins overridden.

As of v24.11, plugins can be added to Thunar using programs.thunar.plugins when enabled with programs.thunar.enable. (NixOS Search)

But the build flags or package option are not exposed in the derivation used with programs.thunar (nixpkgs/nixos/modules/programs/thunar.nix at 666e1b3f09c267afd66addebe80fb05a5ef2b554 · NixOS/nixpkgs · GitHub)

The build flags are present in the thunar package (nixpkgs/pkgs/desktops/xfce/core/thunar/default.nix at 666e1b3f09c267afd66addebe80fb05a5ef2b554 · NixOS/nixpkgs · GitHub) and have to be overridden there.

To add flags, this is what I updated in the programs.thunar derivation

--- a/thunar.nix
+++ b/thunar.nix
@@ -6,8 +6,8 @@
 }:
 
 let
-  cfg = config.programs.thunar;
 
+  cfg = config.programs.thunar-with-flags;
 in
 {
   meta = {
@@ -15,7 +15,7 @@ in
   };
 
   options = {
-    programs.thunar = {
+    programs.thunar-with-flags = {
       enable = lib.mkEnableOption "Thunar, the Xfce file manager";
 
       plugins = lib.mkOption {
@@ -25,13 +25,25 @@ in
         example = lib.literalExpression "with pkgs.xfce; [ thunar-archive-plugin thunar-volman ]";
       };
 
+      configureFlags = lib.mkOption {
+        default = [ ];
+        type = lib.types.listOf lib.types.str;
+        description = "List of flags to pass to the Thunar build.";
+        example = lib.literalExpression ''
+          [ "--disable-wallpaper-plugin" ]
+        '';
+      };
     };
   };
 
   config = lib.mkIf cfg.enable (
     let
-      package = pkgs.xfce.thunar.override { thunarPlugins = cfg.plugins; };
-
+      packageWithPlugins = pkgs.xfce.thunar.override {
+        thunarPlugins = cfg.plugins;
+      };
+      package = packageWithPlugins.overrideAttrs (oldAttrs: {
+        configureFlags = (oldAttrs.configureFlags or [ ]) ++ cfg.configureFlags;
+      });
     in
     {
       environment.systemPackages = [

and updated my configuration.nix accordingly

  programs.thunar-with-flags = {
    enable = true;
    plugins = with pkgs.xfce; [
      thunar-archive-plugin
    ];
    configureFlags = [ "--disable-wallpaper-plugin" ];
  };

Sadly this doesn’t work. In the build, plugins are there, but thunar is not built against given flags.

But the strange behavior is if I do not try to override with plugins, it is built against the proper flags, and ofcourse plugins are not there.

--- b/thunar.nix
+++ c/thunar.nix
@@ -38,9 +38,7 @@ in
 
   config = lib.mkIf cfg.enable (
     let
-      packageWithPlugins = pkgs.xfce.thunar.override {
-        thunarPlugins = cfg.plugins;
-      };
+      packageWithPlugins = pkgs.xfce.thunar;
       package = packageWithPlugins.overrideAttrs (oldAttrs: {
         configureFlags = (oldAttrs.configureFlags or [ ]) ++ cfg.configureFlags;
       });

I want to build with both plugins and flags overridden, but can’t understand the behavior.

How I’m getting to know if the build flag is correct or not?

I pass the flag --disable-wallpaper-plugin using the above mentioned custom derivation, it is supposed to disable the context menu option “Set as wallpaper” for image files inside thunar. If the option is absent, build flags are working fine.

How I’m getting to know if plugins are there?

I use thunar-archive-plugin which adds a context menu to extract compressed file. If it is present plugins are working fine. (Also I can see a package thunar-archive-plugin and thunar-with-plugins being added in nix log)

It looks like this is because the package uses a wrapper when any plugins are provided: nixpkgs/pkgs/desktops/xfce/core/thunar/default.nix at 666e1b3f09c267afd66addebe80fb05a5ef2b554 · NixOS/nixpkgs · GitHub

This means that when you pass plugins, the package you get back is not thunar itself, but rather this wrapper. Trying to set flags then results in the flags going to the wrapper. nixpkgs/pkgs/desktops/xfce/core/thunar/wrapper.nix at 666e1b3f09c267afd66addebe80fb05a5ef2b554 · NixOS/nixpkgs · GitHub

From what I could understand, the wrapper.nix is just a postBuild script, wrapping the thunar package output binary built with the default.nix derivation. No building is done in the wrap step. Compilation with required flags is already finished before this step.

When you do .override the thing that is returned is no longer Thunar itself, it is the wrapper. So .overrideAttrs is being applied to the wrapper, not Thunar.

1 Like

So .overrideAttrs is being applied to the wrapper, not Thunar.

That makes sense, also explains the symptom of intermediate error where it said there is no configureFlags in the oldAttrs (which i happened to ignore and substitute it with [ ]).

Thanks a lot for clarification!

Any idea how do I propagate the flag inside if I do not wish to make a thunar package derivation myself? (mainly to avoid manually upgrade the package with its source and rely on the maintainers)

Don’t try to propagate it, just apply the .overrideAttrs first before doing the .override.

Although the thunar package expression itself is written strangely, as it’s essentially returning completely different types of packages depending on the expression args; I’d expect it to use the FOO and FOO-unwrapped pattern which allows overriding either expression in a way that’s consistent with other similar expressions in nixpkgs.

Even with the suggested change, my custom build flags are not used when plugins are given.

    let
      thunarWithFlags = pkgs.xfce.thunar.overrideAttrs (oldAttrs: {
        configureFlags = (oldAttrs.configureFlags or []) ++ cfg.configureFlags;
      });

      package = thunarWithFlags.override {
        thunarPlugins = cfg.plugins;
      };
    in
{ ... }

Infact, as I expressed above, if (oldAttrs.configureFlags or []) is replaced with (oldAttrs.configureFlags), this code fails when plugins are given, and works absolutely fine when plugins are not used. Possibly indication that attrs is still being applied to wrapper when plugins are given and not on thunar itself.

The additional or [] should not be required in the first place because it exists in default.nix of thunar, and is only absent when wrapper is being used.

1 Like

Yeah, I stand corrected, seems the order of application doesn’t matter, .override will come first. That’s unfortunate and indicates the package should probably be refactored into two separate packages as I mentioned.

Though if you don’t want to modify nixpkgs, this is a little cursed, but you could apply the wrapper yourself:

(pkgs.callPackage "${builtins.dirOf pkgs.xfce.thunar.meta.position}/wrapper.nix" {
  thunarPlugins = [pkgs.xfce.thunar-archive-plugin];
  thunar = pkgs.xfce.thunar.overrideAttrs (o: {
    configureFlags = o.configureFlags ++ [ "--disable-wallpaper-plugin" ];
  });
})

(I opted to use callPackage instead of providing the attributes of pkgs manually.)

1 Like

Awesome, calling the wrapper manually worked.

let
  thunarWithFlags = pkgs.xfce.thunar.overrideAttrs (o: {
    configureFlags = o.configureFlags ++ cfg.configureFlags;
  });
  package = pkgs.callPackage "${builtins.dirOf pkgs.xfce.thunar.meta.position}/wrapper.nix" {
    thunarPlugins = cfg.plugins;
    thunar = thunarWithFlags;
  };
in
{ ... }

A bit hacky though, but at least gets the job done without having to make package derivation myself.