Blog...

Add my RSS feed!


Back


Idiot installs Etterna on NixOS

25 September 2024

If it works, it works


I'm going to preface this by saying that I've only been using NixOS for about a month so I don't know what I'm doing and there's probably a much better way to do this.


I was really surprised to find that Etterna isn't in nixpkgs, despite it being the largest linux software repository. Before switching to Nix I was using Arch, and Etterna is in the AUR so it was as easy as one command to install it.


It seems that not many people have attempted to install Etterna on NixOS, probably for a good reason. This process was very long and annoying and I'm mainly writing this to save anyone else who might try this a few hours and a headache.


This is the module I'm using to compile and install Etterna to the nix store (etterna.nix):


{ stdenv, lib, fetchFromGitHub, cmake, nasm

, gtk2, glib, ffmpeg_4, alsa-lib, libmad, libogg, libvorbis

, glew, libpulseaudio, udev, openssl, doxygen, pkg-config

, libX11, libGLU, libGL, libXpm, libXext, libXxf86vm

}:


stdenv.mkDerivation {

 pname = "etterna";

 version = "0.73-dev";


 src = fetchFromGitHub {

  owner = "etternagame";

  repo = "etterna";

  rev = "develop";

  sha256 = "sha256-pAWC3z2aW2GKPzJ8fzLlv0fNWM7FeNSa8UVI933G2UY=";

 };


 nativeBuildInputs = [ cmake nasm pkg-config ];


 buildInputs = [

  gtk2 glib ffmpeg_4 alsa-lib libmad libogg libvorbis

  glew libpulseaudio udev openssl doxygen

  libX11 libGLU libGL libXpm libXext libXxf86vm

 ];


 cmakeFlags = [

  "-DCMAKE_BUILD_TYPE=Release"

  "-DWITH_SYSTEM_FFMPEG=1"

  "-DGTK2_GDKCONFIG_INCLUDE_DIR=${gtk2.out}/lib/gtk-2.0/include"

  "-DGTK2_GLIBCONFIG_INCLUDE_DIR=${glib.out}/lib/glib-2.0/include"

  "-DWITH_CRASHPAD=OFF"

 ];


 postInstall = '''';


 meta = with lib; {

  homepage = "https://www.etterna.com/";

  description = "Free dance and rhythm game for Windows, Mac, and Linux";

  platforms = platforms.linux;

  license = licenses.mit;

  maintainers = [ ];

  broken = stdenv.isLinux && stdenv.isAarch64;

 };

}


Most of this was copied from here because everything I tried would fail to compile for one reason or another. I had to make a few modifications because after installing it as-is, I ran into an issue.


To my knowledge, all of Etterna's data directories are hard-coded to be in the same directory as the executable binary. On other distros this wouldn't be as much of a problem, put it wherever you want and symlink the executable to /usr/bin.


On NixOS, since directories in /nix/store are immutable and read-only, you can't have the data directories in there because they need to be written to, post-installation. This is a problem because if the Etterna binary isn't in the same directory as the data directories, it doesn't work.


My solution to this was to create a systemd service that will run a script every rebuild. This script will copy all of Etterna's files in the nix store to ~/.local/share, symlink all of the directories that need to be persistent to ~/.etterna and create a .desktop file in ~/.local/share/applications.


I have all of these files in an etterna directory in my modules. This is what the default.nix file looks like:


{pkgs, userConfigs, ...}:

let

 etterna = pkgs.callPackage ./etterna.nix {};

 script = ./local-install.sh;

 desktopFile = ./etterna.desktop;

in

{

 environment.systemPackages = [

  etterna

 ];


 systemd.services.etterna-local-install = {

  description = "Install Etterna locally";

  wantedBy = ["multi-user.target"];

  serviceConfig = {

   Type = "oneshot";

   ExecStart = "${pkgs.bash}/bin/bash ${script} ${etterna} ${desktopFile} ${userConfigs.username}";

  };

 };

}


this is local-install.sh:


homeDir="/home/$3"

installDir="$homeDir/.local/share/Etterna"

applicationsDir="$homeDir/.local/share/applications"


if [[ -d "$installDir" ]]; then

 rm -rf "$installDir"

 cp -r "$1/Etterna" "$installDir"

 rm -rf "$installDir/Announcers"

 rm -rf "$installDir/Assets"

 rm -rf "$installDir/NoteSkins"

 rm -rf "$installDir/Songs"

 rm -rf "$installDir/Themes"

else

 cp -r "$1/Etterna" "$installDir"

 mkdir -p "$homeDir/.etterna/Save"

 mv "$installDir/Announcers" "$homeDir/.etterna"

 mv "$installDir/Assets" "$homeDir/.etterna"

 mv "$installDir/NoteSkins" "$homeDir/.etterna"

 mv "$installDir/Songs" "$homeDir/.etterna"

 mv "$installDir/Themes" "$homeDir/.etterna"

fi


ln -s "$homeDir/.etterna/Announcers" "$installDir"

ln -s "$homeDir/.etterna/Assets" "$installDir"

ln -s "$homeDir/.etterna/NoteSkins" "$installDir"

ln -s "$homeDir/.etterna/Save" "$installDir"

ln -s "$homeDir/.etterna/Songs" "$installDir"

ln -s "$homeDir/.etterna/Themes" "$installDir"


if [[ -f "$applicationsDir/etterna.desktop" ]]; then

 rm "$applicationsDir/etterna.desktop"

fi


cp "$2" "$applicationsDir/etterna.desktop"

echo "Exec=$installDir/Etterna" | tee -a "$applicationsDir/etterna.desktop"


chown -R "$3":users "$homeDir/.etterna"

chmod -R 755 "$homeDir/.etterna"


mkdir "$installDir/Cache"

chown -R "$3":users "$installDir/Cache"

chmod -R 755 "$installDir/Cache"


and this is etterna.desktop:


[Desktop Entry]

Name=Etterna

Comment=The Next Step in Dance Simulation

Type=Application

Categories=Game


This configuration is working as of when I'm writing this. If anyone has a better solution to this, feel free to email me about it.


Categories: Technology NixOS Etterna Games Rhythm Games Linux