{ lib , stdenv , makeWrapper , symlinkJoin , runCommand , retroarch , cores ? [ ] , settings ? { } }: let settings' = { libretro_directory = coresPath; } // settings; settingsPath = runCommand "declarative-retroarch.cfg" { value = lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: "${n} = \"${v}\"") settings); passAsFile = [ "value" ]; } '' cp "$valuePath" "$out" ''; coresPath = let path = assert lib.assertMsg (builtins.length (map (c: c.libretroCore) cores) == 1) "Libretro cores are not under the same paths"; (builtins.head cores).libretroCore; in symlinkJoin { name = "retroarch-cores"; paths = cores; } + path; wrapperArgs = lib.strings.escapeShellArgs [ "--add-flags" "--config=${settingsPath}" ]; in symlinkJoin { name = "retroarch-with-cores-${lib.getVersion retroarch}"; paths = [ retroarch ]; nativeBuildInputs = [ makeWrapper ]; passthru = { inherit cores; unwrapped = retroarch; }; postBuild = '' # wrap binary to load cores from the proper location(s) wrapProgram $out/bin/retroarch ${wrapperArgs} ''; meta = with retroarch.meta; { inherit changelog description homepage license maintainers platforms; longDescription = '' RetroArch is the reference frontend for the libretro API. '' + lib.optionalString (cores != [ ]) '' The following cores are included: ${lib.concatStringsSep ", " (map (c: c.core) cores)} ''; mainProgram = "retroarch"; }; }