Using overlay to bump android-studio version

Hi,
I’ve started using Nix as my daily driver and have been loving it so far. However I’ve been struggling with locally updating android-studio to the latest. I have created a Pull Request to do it, but I want to bump it locally until it’s merged. I have tried to use an overlay but have failed to get the version to actually bump. Could someone give an example of how you would create an overlay to do what my PR would do?

Thanks in advanced!

Config in question:
flake.nix:

{
  description = "My Systems";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
    nixpkgs-master.url = "github:nixos/nixpkgs?ref=master";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    agenix = {
      url = "github:ryantm/agenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, nixpkgs-master, home-manager, agenix, ... } @ attrs:
    let
      system = "x86_64-linux";
      pkgs-master = (import nixpkgs-master {
        inherit system;
        config={allowUnfree = true;};
      });
      specialArgs = attrs // { inherit system pkgs-master ; };
    in {
    nixosConfigurations.edi = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/edi/configuration.nix
        ./common.nix
      ];
    };
    nixosConfigurations.joker = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/joker/configuration.nix
        ./common.nix
      ];
    };
    nixosConfigurations.edi-vm = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/edi-vm/configuration.nix
        ./common.nix
      ];
    };
  };
}

common.nix:


{ config, pkgs, pkgs-master, inputs, agenix, ... }:

{
  imports =
    [
      agenix.nixosModules.default
      ./jbassett.nix
    ];

  nix.settings = { experimental-features = "nix-command flakes"; };

  # Enable networking
  networking= {
    networkmanager.enable = true;
    firewall.trustedInterfaces = [
      config.services.tailscale.interfaceName
    ];
  };

  # Set your time zone.
  time.timeZone = "America/New_York";

  # Select internationalisation properties.
  i18n.defaultLocale = "en_US.UTF-8";

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "en_US.UTF-8";
    LC_IDENTIFICATION = "en_US.UTF-8";
    LC_MEASUREMENT = "en_US.UTF-8";
    LC_MONETARY = "en_US.UTF-8";
    LC_NAME = "en_US.UTF-8";
    LC_NUMERIC = "en_US.UTF-8";
    LC_PAPER = "en_US.UTF-8";
    LC_TELEPHONE = "en_US.UTF-8";
    LC_TIME = "en_US.UTF-8";
  };

  # Enable the X11 windowing system.
  # You can disable this if you're only using the Wayland session.
  services.xserver.enable = true;

  # Enable the KDE Plasma Desktop Environment.
  services.displayManager = {
    sddm = {
      # sudo cp ~/.config/kwinoutputconfig.json /var/lib/sddm/.config/kwinoutputconfig.json
      enable = true;
      wayland.enable = true;
      autoNumlock = true;
    };
  };
  services.desktopManager = {
    plasma6.enable = true;
  };

  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "us";
    variant = "";
  };

  # Enable CUPS to print documents.
  services.printing.enable = true;

  # Enable sound with pipewire.
  services.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    #jack.enable = true;

    # use the example session manager (no others are packaged yet so this is enabled by default,
    # no need to redefine it in your config for now)
    #media-session.enable = true;
  };

  services.openssh = {
    enable = true;
    settings.PasswordAuthentication = false;
    settings.KbdInteractiveAuthentication = false;
  };

  services.tailscale = {
    enable = true;
    useRoutingFeatures = "both";
  };

  programs ={
    firefox = {
      enable = true;
      nativeMessagingHosts.packages = [ pkgs.firefoxpwa ];
    };
    zsh.enable = true;
    steam.enable = true;
    nix-ld.enable = true;
  };

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
    ktailctl
    google-chrome
    firefoxpwa
    discord
    bitwarden-desktop
    slack
    vlc

    # CLI
    wget
    nvd
    awscli2
    v4l-utils
    ffmpeg
    kubectl
    kubernetes-helm
    git
    agenix.packages.${system}.default

    #IDEs / Dev
    jdk17
    jdk23
    pkgs-master.jetbrains.idea-ultimate
    pkgs-master.android-studio
  ];

  virtualisation.docker.enable = true;


  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "24.05"; # Did you read the comment?

}

It appears you forgot to post the actual overlay attempt.

Your NixOS config isn’t actually relevant here btw: overlays exist entirely within nixpkgs (pkgs). NixOS merely has a handy option to pass a set of overlays to it.


What I do is that I simply have a fork of nixpkgs that represents my nixpkgs state. To update, I simply pull but I’m free to also cherry-pick changes earlier than a channel would have them or even diverge from upstream (though that causes maintainability issues).

I don’t use flakes but I know it’s possible to apply patches to flake inputs. Compared to having your own fork, that’s limited in flexibility but, in simple cases where it works, it’s much easier to use.

I was hoping to get the proper way rather than my failed attempts.

I was hoping it was going to be as easy as just passing a new src attribute in the overlay rather than keeping my own version of the pkgs repo.

I would use the more general applyPatches mechanism instead of overlays.
https://wiki.nixos.org/wiki/Nixpkgs/Patching_Nixpkgs

Generically it’s not possible to do so with only a flake input.

For nixpkgs we have applyPatches as mentioned above, at least. But IMO the usecase presented in the wiki is a bit silly, an override would make more sense for just bumping a single package’s version.

Since OP’s usecase is exactly the same - just use an override!
https://nixos.org/manual/nixpkgs/unstable/#sec-pkg-overrideAttrs

And @JBassett if you are stuck, post full code and full errors, no paraphrasing.

1 Like

Here are several attempts that all build without errors but don’t produce a system with the updated android-studio package. In both instances it appears the overlay is working because I can reference pkgs-master.android-studio-local but neither one actually changes the version.

  1. Attempt One
    flake.nix:
{
  description = "My Systems";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
    nixpkgs-master.url = "github:nixos/nixpkgs?ref=master";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    agenix = {
      url = "github:ryantm/agenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, nixpkgs-master, home-manager, agenix, ... } @ attrs:
    let
      system = "x86_64-linux";
      pkgs-master = (import nixpkgs-master {
        inherit system;
        config={allowUnfree = true;};
        overlays = [
          (self: super: {
            android-studio-local = super.android-studio.overrideAttrs (old:
            let
              version = "2024.2.2.13";
              sha256Hash = "sha256-t/4e1KeVm9rKeo/VdGHbv5ogXrI8whjtgo7YjouZjLU=";
              filename = "android-studio-${version}-linux.tar.gz";
            in {
              src = super.fetchurl {
                url = "https://dl.google.com/dl/android/studio/ide-zips/${version}/${filename}";
                sha256 = sha256Hash;
              };
            });
          })
        ];
      });
      specialArgs = attrs // { inherit system pkgs-master ; };
    in {
    nixosConfigurations.edi = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/edi/configuration.nix
        ./common.nix
      ];
    };
    nixosConfigurations.joker = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/joker/configuration.nix
        ./common.nix
      ];
    };
    nixosConfigurations.edi-vm = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/edi-vm/configuration.nix
        ./common.nix
      ];
    };
  };
}

common.nix:


{ config, pkgs, pkgs-master, inputs, agenix, ... }:

{
  imports =
    [
      agenix.nixosModules.default
      ./jbassett.nix
    ];

  nix.settings = { experimental-features = "nix-command flakes"; };

  # Enable networking
  networking= {
    networkmanager.enable = true;
    firewall.trustedInterfaces = [
      config.services.tailscale.interfaceName
    ];
  };

  # Set your time zone.
  time.timeZone = "America/New_York";

  # Select internationalisation properties.
  i18n.defaultLocale = "en_US.UTF-8";

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "en_US.UTF-8";
    LC_IDENTIFICATION = "en_US.UTF-8";
    LC_MEASUREMENT = "en_US.UTF-8";
    LC_MONETARY = "en_US.UTF-8";
    LC_NAME = "en_US.UTF-8";
    LC_NUMERIC = "en_US.UTF-8";
    LC_PAPER = "en_US.UTF-8";
    LC_TELEPHONE = "en_US.UTF-8";
    LC_TIME = "en_US.UTF-8";
  };

  # Enable the X11 windowing system.
  # You can disable this if you're only using the Wayland session.
  services.xserver.enable = true;

  # Enable the KDE Plasma Desktop Environment.
  services.displayManager = {
    sddm = {
      # sudo cp ~/.config/kwinoutputconfig.json /var/lib/sddm/.config/kwinoutputconfig.json
      enable = true;
      wayland.enable = true;
      autoNumlock = true;
    };
  };
  services.desktopManager = {
    plasma6.enable = true;
  };

  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "us";
    variant = "";
  };

  # Enable CUPS to print documents.
  services.printing.enable = true;

  # Enable sound with pipewire.
  services.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    #jack.enable = true;

    # use the example session manager (no others are packaged yet so this is enabled by default,
    # no need to redefine it in your config for now)
    #media-session.enable = true;
  };

  services.openssh = {
    enable = true;
    settings.PasswordAuthentication = false;
    settings.KbdInteractiveAuthentication = false;
  };

  services.tailscale = {
    enable = true;
    useRoutingFeatures = "both";
  };

  programs ={
    firefox = {
      enable = true;
      nativeMessagingHosts.packages = [ pkgs.firefoxpwa ];
    };
    zsh.enable = true;
    steam.enable = true;
    nix-ld.enable = true;
  };

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
    ktailctl
    google-chrome
    firefoxpwa
    discord
    bitwarden-desktop
    slack
    vlc

    # CLI
    wget
    nvd
    awscli2
    v4l-utils
    ffmpeg
    kubectl
    kubernetes-helm
    git
    agenix.packages.${system}.default

    #IDEs / Dev
    jdk17
    jdk23
    pkgs-master.jetbrains.idea-ultimate
    pkgs-master.android-studio-local
  ];

  virtualisation.docker.enable = true;


  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "24.05"; # Did you read the comment?

}
  1. Attempt Two
    flake.nix:
{
  description = "My Systems";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
    nixpkgs-master.url = "github:nixos/nixpkgs?ref=master";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    agenix = {
      url = "github:ryantm/agenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, nixpkgs-master, home-manager, agenix, ... } @ attrs:
    let
      system = "x86_64-linux";
      pkgs-master = (import nixpkgs-master {
        inherit system;
        config={allowUnfree = true;};
        overlays = [
          (self: super: {
            android-studio-local = super.android-studio.overrideAttrs (old: {
              version = "2024.2.2.13";
              sha256Hash = "sha256-t/4e1KeVm9rKeo/VdGHbv5ogXrI8whjtgo7YjouZjLU=";
            });
          })
        ];
      });
      specialArgs = attrs // { inherit system pkgs-master ; };
    in {
    nixosConfigurations.edi = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/edi/configuration.nix
        ./common.nix
      ];
    };
    nixosConfigurations.joker = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/joker/configuration.nix
        ./common.nix
      ];
    };
    nixosConfigurations.edi-vm = nixpkgs.lib.nixosSystem {
      specialArgs = specialArgs;
      modules = [
        home-manager.nixosModules.home-manager
        ./hosts/edi-vm/configuration.nix
        ./common.nix
      ];
    };
  };
}

common.nix:


{ config, pkgs, pkgs-master, inputs, agenix, ... }:

{
  imports =
    [
      agenix.nixosModules.default
      ./jbassett.nix
    ];

  nix.settings = { experimental-features = "nix-command flakes"; };

  # Enable networking
  networking= {
    networkmanager.enable = true;
    firewall.trustedInterfaces = [
      config.services.tailscale.interfaceName
    ];
  };

  # Set your time zone.
  time.timeZone = "America/New_York";

  # Select internationalisation properties.
  i18n.defaultLocale = "en_US.UTF-8";

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "en_US.UTF-8";
    LC_IDENTIFICATION = "en_US.UTF-8";
    LC_MEASUREMENT = "en_US.UTF-8";
    LC_MONETARY = "en_US.UTF-8";
    LC_NAME = "en_US.UTF-8";
    LC_NUMERIC = "en_US.UTF-8";
    LC_PAPER = "en_US.UTF-8";
    LC_TELEPHONE = "en_US.UTF-8";
    LC_TIME = "en_US.UTF-8";
  };

  # Enable the X11 windowing system.
  # You can disable this if you're only using the Wayland session.
  services.xserver.enable = true;

  # Enable the KDE Plasma Desktop Environment.
  services.displayManager = {
    sddm = {
      # sudo cp ~/.config/kwinoutputconfig.json /var/lib/sddm/.config/kwinoutputconfig.json
      enable = true;
      wayland.enable = true;
      autoNumlock = true;
    };
  };
  services.desktopManager = {
    plasma6.enable = true;
  };

  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "us";
    variant = "";
  };

  # Enable CUPS to print documents.
  services.printing.enable = true;

  # Enable sound with pipewire.
  services.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    #jack.enable = true;

    # use the example session manager (no others are packaged yet so this is enabled by default,
    # no need to redefine it in your config for now)
    #media-session.enable = true;
  };

  services.openssh = {
    enable = true;
    settings.PasswordAuthentication = false;
    settings.KbdInteractiveAuthentication = false;
  };

  services.tailscale = {
    enable = true;
    useRoutingFeatures = "both";
  };

  programs ={
    firefox = {
      enable = true;
      nativeMessagingHosts.packages = [ pkgs.firefoxpwa ];
    };
    zsh.enable = true;
    steam.enable = true;
    nix-ld.enable = true;
  };

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
    ktailctl
    google-chrome
    firefoxpwa
    discord
    bitwarden-desktop
    slack
    vlc

    # CLI
    wget
    nvd
    awscli2
    v4l-utils
    ffmpeg
    kubectl
    kubernetes-helm
    git
    agenix.packages.${system}.default

    #IDEs / Dev
    jdk17
    jdk23
    pkgs-master.jetbrains.idea-ultimate
    pkgs-master.android-studio-local
  ];

  virtualisation.docker.enable = true;


  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "24.05"; # Did you read the comment?

}

Attempt two couldn’t work because the attributes you set don’t really have any effect.

Attempt one looks like it should work but, as always with overrideAttrs, you need to take a close look at how the original derivation works because it only deals with the mkDerivation call’s details.

In this case the derivation is quite complex involving multiple wrappers and the thing you’re overriding the attributes of is such a wrapper that doesn’t use src anywhere which is why overriding it has no effect.
Touching this derivation from the outside via overrides looks extremely non-trivial even to me, so it’s no wonder you failed.

The function which generates these derivations from a set of source arguments is super generic though and if you had access to it, you could just call it with whatever arguments you like and produce a working android-studio.

What’s missing is that this function isn’t exposed anywhere for you to access from the “outside”. It’d be trivial to expose it in the same attrset that exposes the finished android-studio packages via a simple inherit mkStudio;; would you like to send a patch?

There’s also a way to slightly re-engineer this such that version, hash etc. become part of the .override interface which would be even neater but that’d be a bit more advanced.

1 Like

I took a stab at it but I’m not sure how to actually call the inherited mkStudio function, so I’m not sure how to verify it still. If you want to create the patch with testing instructions I would be more than happy to help.