Help with avoiding 50gb worth of rebuils

Hi all, I have a chromebook, which I run nixos on. Due to the many quirks of running linux on a chomebook, alsa needs some further configuration, see chromebook-ucm-conf.

For a while, overriding alsa-ucm-conf like this worked just fine, however, since alsa-ucm-conf updated from version 1.2.9, I’ve had a hard time adjusting the override in a way that makes it, so I don’t have to rebuild a million packages.

Chrultrabook(the community that works to get traditional linux distros running on chromebooks) has some instructions to fix audio on nixos, which I tried implementing as follows:

  environment = {
    systemPackages = with pkgs; [ alsa-ucm-conf maliit-keyboard ];
    sessionVariables = {
      ALSA_CONFIG_UCM2 = "${pkgs.alsa-ucm-conf}/share/alsa/ucm2";
    };
  };

  nixpkgs.overlays = with pkgs;
    [
      (final: prev: {
        alsa-ucm-conf = prev.alsa-ucm-conf.overrideAttrs (old: {
          wttsrc = (fetchFromGitHub {
            owner = "WeirdTreeThing";
            repo = "chromebook-ucm-conf";
            rev = "792a6d5ef0d70ac1f0b4861f3d29da4fe9acaed1";
            hash = "sha256-Ae/k9vA5lWiomSa6WCfp+ROqEij11FPwlHAIG6L19JI=";
          });
          installPhase = ''
            runHook preInstall

            mkdir -p $out/share/alsa
            cp -r ucm ucm2 $out/share/alsa

            mkdir -p $out/share/alsa/ucm2/conf.d
            cp -r $wttsrc/{hdmi,dmic}-common $wttsrc/cml/* $out/share/alsa/ucm2/conf.d

            runHook postInstall
          '';
        });
      })
    ];

The problem is that when I rebuild my system with these changes, nix wants to rebuild a lot of packages, totalling to nearly 50 gigs worth. So I attempted instead to create and install the following package, exporting the correct sessionVariable:

{ lib, stdenv, fetchurl, alsa-ucm-conf }:

stdenv.mkDerivation {
  pname = "alsa-ucm-cml-conf";
  version = "2024-03-07";

  src = fetchurl {
    url =
      "https://github.com/WeirdTreeThing/chromebook-ucm-conf/archive/792a6d5ef0d70ac1f0b4861f3d29da4fe9acaed1.tar.gz";
    hash = "sha256-Ae/k9vA5lWiomSa6WCfp+ROqEij11FPwlHAIG6L19JI=";
  };

  dontBuild = true;

  preInstall = ''
    mkdir -p $out/share/alsa/ucm2/conf.d
    find ${alsa-ucm-conf}/share/alsa/ucm2 -mindepth 1 -maxdepth 1 \( -type f -o -type d \) -exec ln -s {} "$out/share/alsa/ucm2/" \;
    find ${alsa-ucm-conf}/share/alsa/ucm2/conf.d -mindepth 1 -maxdepth 1 \( -type f -o -type d \) -exec ln -s {} "$out/share/alsa/ucm2/conf.d/" \;
  '';
  installPhase = ''
    runHook preInstall
    cp -r hdmi-common dmic-common cml $out/share/alsa/ucm2/conf.d
    runHook postInstall
  '';

  meta = with lib; {
    homepage = "https://github.com/WeirdTreeThing/chromebook-ucm-conf";
    description = "Alsa UCM configuration for cml chromebook devices";
    license = licenses.bsd3;
    platforms = platforms.linux;
  };
}

But that didn’t seem to work, I think I need to override alsa-ucm-conf instead. Is there a way I can override it without having to rebuild all these packages, or am I out of luck?

Any help would be greatly appreciated.

1 Like

I wonder if that with pkgs in the overlay is the culprit? I wonder if it’s bringing in things to scope you don’t want it to.

It’s because you’re overriding alsa-ucm-conf globally, which virtually everything depends on.

Try something like:

  environment = let
    chromebook-ucm-conf = pkgs.alsa-ucm-conf.overrideAttrs ....
  in {
    sessionVariables = {
      ALSA_CONFIG_UCM2 = "${chromebook-ucm-conf}/share/alsa/ucm2";
    };
  };

I had a similar issue a while back and I did something similar:

  environment.sessionVariables.ALSA_CONFIG_UCM2 = let
    # Updated version with https://github.com/alsa-project/alsa-ucm-conf/issues/123 bugfix.
    alsa-ucm-conf = pkgs.fetchFromGitHub {
      owner  = "alsa-project";
      repo   = "alsa-ucm-conf";
      rev    = "7dda1e21fff6163abfd681380b054f514b3b43bc";
      sha256 = "15zlb25dd6v1vdc21mkld75d1q661xhnljk2yfpz25pkjwq7lq9v";
    };
  in "${alsa-ucm-conf}/ucm2";
2 Likes

Otherwise, it might be possible to use the system that allows you to use a system-wide library different from the one used in packages without recompiling… I forgot the name of the nixos parameter to change, but for sure there is one ^^

@rjpc

I wonder if that with pkgs in the overlay is the culprit? I wonder if it’s bringing in things to scope you don’t want it to.

Doesn’t seem to be the case.

@vs49688

This is what I ended up trying:

      cml-ucm-conf = pkgs.alsa-ucm-conf.overrideAttrs {
        wttsrc = pkgs.fetchurl {
          url =
            "https://github.com/WeirdTreeThing/chromebook-ucm-conf/archive/2b2f3a7c993fd38a24aa81394e29ee530b890658.tar.gz";
          hash = "sha256-WeLkxWB174Hwb11xnIxsvRm5NpM528IVEYH4K32pLwg=";
        };
        unpackPhase = ''
          runHook preUnpack
          tar xf "$src"
          tar xf "$wttsrc"
          runHook postUnpack
        '';
        installPhase = ''
          runHook preInstall
          mkdir -p $out/share/alsa
          cp -r alsa-ucm*/{ucm,ucm2} $out/share/alsa
          cp -r chromebook-ucm*/common $out/share/alsa/ucm2/common
          cp -r chromebook-ucm*/codecs $out/share/alsa/ucm2/codecs
          cp -r chromebook-ucm*/platforms $out/share/alsa/ucm2/platforms
          cp -r chromebook-ucm*/sof-rt5682 $out/share/alsa/ucm2/conf.d/sof-rt5682
          cp -r chromebook-ucm*/sof-cs42l42 $out/share/alsa/ucm2/conf.d/sof-cs42l42
          cp -r chromebook-ucm*/cml/* $out/share/alsa/ucm2/conf.d
          runHook postInstall
        '';
      };
    in "${cml-ucm-conf}/share/alsa/ucm2";

It builds fine, but unfortunately doesn’t fix my audio as it should.

@tobiasBora

Otherwise, it might be possible to use the system that allows you to use a system-wide library different from the one used in packages without recompiling… I forgot the name of the nixos parameter to change, but for sure there is one ^^

That’s exactly what I’ve been looking for, but my google skills have failed me.

What’s the context here? Which option does this set?

My bad, I realise now that context is missing:

environment = {
    systemPackages = with pkgs; [ maliit-keyboard ];
    sessionVariables.ALSA_CONFIG_UCM2 = let
      cml-ucm-conf = pkgs.alsa-ucm-conf.overrideAttrs {
        wttsrc = pkgs.fetchurl {
          url =
            "https://github.com/WeirdTreeThing/chromebook-ucm-conf/archive/2b2f3a7c993fd38a24aa81394e29ee530b890658.tar.gz";
          hash = "sha256-WeLkxWB174Hwb11xnIxsvRm5NpM528IVEYH4K32pLwg=";
        };
        unpackPhase = ''
          runHook preUnpack
          tar xf "$src"
          tar xf "$wttsrc"
          runHook postUnpack
        '';
        installPhase = ''
          runHook preInstall
          mkdir -p $out/share/alsa
          cp -r alsa-ucm*/{ucm,ucm2} $out/share/alsa
          cp -r chromebook-ucm*/common $out/share/alsa/ucm2/common
          cp -r chromebook-ucm*/codecs $out/share/alsa/ucm2/codecs
          cp -r chromebook-ucm*/platforms $out/share/alsa/ucm2/platforms
          cp -r chromebook-ucm*/sof-rt5682 $out/share/alsa/ucm2/conf.d/sof-rt5682
          cp -r chromebook-ucm*/sof-cs42l42 $out/share/alsa/ucm2/conf.d/sof-cs42l42
          cp -r chromebook-ucm*/cml/* $out/share/alsa/ucm2/conf.d
          runHook postInstall
        '';
      };
    in "${cml-ucm-conf}/share/alsa/ucm2";
  };

Though I’ve gotten to a point where I think the problem isn’t actaully getting the ucm config, but I’m probably missing whatever else this script here does.

What I meant is system.replaceRuntimeDependencies.

1 Like

So, with this I build fewer packges, but still too many for my little underpowered chromebook. This is what my config is looking like now (relevant sections only):

{ config, pkgs, lib, ... }:

let
  cml-ucm-conf = pkgs.alsa-ucm-conf.overrideAttrs {
    wttsrc = pkgs.fetchurl {
      url =
        "https://github.com/WeirdTreeThing/chromebook-ucm-conf/archive/2b2f3a7c993fd38a24aa81394e29ee530b890658.tar.gz";
      hash = "sha256-WeLkxWB174Hwb11xnIxsvRm5NpM528IVEYH4K32pLwg=";
    };
    unpackPhase = ''
      runHook preUnpack
      tar xf "$src"
      tar xf "$wttsrc"
      runHook postUnpack
    '';
    installPhase = ''
      runHook preInstall
      mkdir -p $out/share/alsa
      cp -r alsa-ucm*/{ucm,ucm2} $out/share/alsa
      cp -r chromebook-ucm*/{common,codecs,platforms} $out/share/alsa/ucm2
      cp -r chromebook-ucm*/{sof-rt5682,sof-cs42l42} $out/share/alsa/ucm2/conf.d
      cp -r chromebook-ucm*/cml/* $out/share/alsa/ucm2/conf.d
      runHook postInstall
    '';
  };
in {
  boot = {
    kernelParams = [ "nosgx" "i915.fastboot=1" "mem_sleep_default=deep" ];
    extraModprobeConfig = ''
      options snd-intel-dspcfg dsp_driver=3
    '';
  };

  environment = {
    systemPackages = with pkgs; [ maliit-keyboard ];
    sessionVariables.ALSA_CONFIG_UCM2 = "${cml-ucm-conf}/share/alsa/ucm2";
  };

  system.replaceRuntimeDependencies = [({
    original = pkgs.alsa-ucm-conf;
    replacement = cml-ucm-conf;
  })];
}

And it only builds if I pass --impure :frowning:

I just let the build run to its end, it wasn’t so bad, actually. But unfortunately, the ucm conf changes weren’t picked up. Now I am sure that the issue is whatever this script does that I don’t. But I’m really not sure what I’m missing.

I know knowthing about alsa, but I just got the surprise to see that running sudo alsactl init solved my microphone issue (need sound.enable = true; to persist on reboot) maybe you also need to run something similar…

This is marked as the solution but it’s very unclear what the solution actually is. If someone got audio to work can you please send the NixOS config for it? I’m trying to get audio to work on a adl Chromebook btw.

I created config based off of your configuration and I modified it to use a different commit and use adl audio and IT WORKED! It looks like it didn’t compile anything extra. Thanks very much to the people in this thread (in addition to WTT of course). This is /etc/nixos/audio.nix:

{ config, pkgs, lib, ... }:


let
  cml-ucm-conf = pkgs.alsa-ucm-conf.overrideAttrs {
    wttsrc = pkgs.fetchurl {
      url =
        "https://github.com/WeirdTreeThing/chromebook-ucm-conf/archive/1328e46bfca6db2c609df9c68d37bb418e6fe279.tar.gz";
      hash = "sha256-eTP++vdS7cKtc8Mq4qCzzKtTRM/gsLme4PLkN0ZWveo=";
    };
    unpackPhase = ''
      runHook preUnpack
      tar xf "$src"
      tar xf "$wttsrc"
      runHook postUnpack
    '';
    installPhase = ''
      runHook preInstall
      mkdir -p $out/share/alsa
      cp -r alsa-ucm*/{ucm,ucm2} $out/share/alsa
      cp -r chromebook-ucm*/common $out/share/alsa/ucm2
      cp -r chromebook-ucm*/adl/* $out/share/alsa/ucm2/conf.d
      runHook postInstall
    '';
  };
in
{
  boot = {
    extraModprobeConfig = ''
      options snd-intel-dspcfg dsp_driver=3
    '';
  };

  environment = {
    systemPackages = with pkgs; [
      maliit-keyboard
      sof-firmware
    ];
    sessionVariables.ALSA_CONFIG_UCM2 = "${cml-ucm-conf}/share/alsa/ucm2";
  };

  system.replaceRuntimeDependencies = [
    ({
      original = pkgs.alsa-ucm-conf;
      replacement = cml-ucm-conf;
    })
  ];
}

and this is /etc/nixos/configuration.nix:

# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

{
  imports =
    [
      # Include the results of the hardware scan.
      ./hardware-configuration.nix
      ./audio.nix
    ];

  # Bootloader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  networking.hostName = "nixos"; # Define your hostname.
  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.

  # Configure network proxy if necessary
  # networking.proxy.default = "http://user:password@proxy:port/";
  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";

  # Enable networking
  networking.networkmanager.enable = true;

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

  # 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.
  services.xserver.enable = true;

  # Enable the KDE Plasma Desktop Environment.
  services.xserver.displayManager.sddm.enable = true;
  #services.xserver.desktopManager.plasma5.enable = true;
  # KDE Plasma 6 is now available on unstable
  services.desktopManager.plasma6.enable = true;
  services.xserver.displayManager.sddm.wayland.enable = true;

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

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

  # Enable sound with pipewire.
  sound.enable = true;
  hardware.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;
  };
  hardware.bluetooth = {
    enable = true;
    powerOnBoot = true;
  };

  # Enable touchpad support (enabled default in most desktopManager).
  # services.xserver.libinput.enable = true;

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.test = {
    isNormalUser = true;
    description = "Test";
    extraGroups = [ "networkmanager" "wheel" ];
    packages = with pkgs; [
      firefox
      kate
      #  thunderbird
    ];
  };

  # Enable automatic login for the user.
  services.xserver.displayManager.autoLogin.enable = true;
  services.xserver.displayManager.autoLogin.user = "test";

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

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
    nano # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
    wget
    git
    curl
    vscode
    nixpkgs-fmt
  ];

  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  # networking.firewall.enable = false;

  # 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 = "23.11"; # Did you read the comment?

}

one thing to note is that I’m using an older commit of the WTT ucm conf. The reason why is because currently the latest version doesn’t work properly with my Chromebook (redrix). We can use the latest WTT ucm conf, which has merged all of the SOF configs into one, so that SOF doesn’t need generation-specific configs anymore.

Another thing I will be trying is replacing the fetchUrl with fetch from GitHub.

1 Like

I marked that as the answer, because it technically answer my question. With it, I avoid the 50 gigs worth of rebuilds. Unfortunately, it didn’t fix my audio issue. Your changes, however, did help me to fix my audio. It looks like this particular commit also works for my machine, thank you so much!

2 Likes

Just in case someone else still has issues, my setup works without the need to create an overlay or replace the package. I declare the ALSA_CONFIG_UCM2 environment variable and use the latest chromebook-ucm-conf commit:

  alsa-ucm-conf-chromebook =
    with pkgs;
    alsa-ucm-conf.overrideAttrs {
      wttsrc = fetchFromGitHub {
        owner = "WeirdTreeThing";
        repo = "chromebook-ucm-conf";
        rev = "b6ce2a7";
        hash = "sha256-QRUKHd3RQmg1tnZU8KCW0AmDtfw/daOJ/H3XU5qWTCc=";
      };
      postInstall = ''
        echo "v0.4.1" > $out/chromebook.patched

        # Asus Chromebook CX1400 (GALTIC)
        #   ❯ aplay -l
        #   card 0: sofrt5682 [sof-rt5682], device 0: Headphones (*) []
        #   ....
        cp -R $wttsrc/sof-rt5682 $out/share/alsa/ucm2/conf.d
        cp -R $wttsrc/common/* $out/share/alsa/ucm2/common
        cp -R $wttsrc/codecs/* $out/share/alsa/ucm2/codecs
        cp -R $wttsrc/platforms/* $out/share/alsa/ucm2/platforms
      '';
    };

and

  environment = {
    systemPackages = with pkgs; [
      alsa-ucm-conf
      sof-firmware
    ];
    sessionVariables = {
      ALSA_CONFIG_UCM2 = "${alsa-ucm-conf-chromebook}/share/alsa/ucm2";
    };
  };

You only need to adjust what to copy from the ucm-config repo (in my case, I have an Asus CX1400 that has a sof-rt5682 card).

I did this on Jinlon and everything worked EXCEPT for the Headphone mic.

EDIT: The headphone mic not working is actually a bug with the WeirdTreeThing repo, and not the NixOS config.

Also, there’s no harm in including cp -R $wttsrc/sof-cs42l42 $out/share/alsa/ucm2/conf.d. This should theoretically make the NixOS configuration work on all SOF chromebooks.