So, I have been trying to create a Nixos build config for the 3nd party Minecraft launcher MultiMC and I cant seem to get the QT5 libraries to import correctly.
I get this error:
From this build file:
{ stdenv, lib, fetchurl, makeDesktopItem, qt5, wrapQtAppsHook }:
stdenv.mkDerivation rec {
pname = "MultiMC";
version = "1.6.1";
meta = with lib; {
description = "MultiMC: A custom launcher for Minecraft";
homepage = "https://multimc.org/";
license = licenses.asl20;
platforms = platforms.linux;
maintainers = [ ];
};
src = fetchurl {
url = "https://files.multimc.org/downloads/mmc-stable-lin64.tar.gz";
sha256 = "BYV3jD6ejNUdMkr2xpRpQ582qIVx74O+RK4B/P790lE=";
};
nativeBuildInputs = [
wrapQtAppsHook
];
buildInputs = [
qt5.qtbase
];
unpackPhase = ''
mkdir -p $out
tar -xzf $src -C $out
chmod +x $out/MultiMC/bin/MultiMC
chmod +x $out/MultiMC/
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share/applications
substituteInPlace $out/MultiMC/MultiMC \
--replace 'QT_PLUGIN_PATH="''${LAUNCHER_DIR}/plugins"' "QT_PLUGIN_PATH=\"${qt5.qtbase.bin}/${qt5.qtbase.qtPluginPrefix}\""
wrapQtApp "$out/MultiMC/MultiMC"
wrapQtApp "$out/MultiMC/bin/MultiMC"
mv $out/MultiMC/.MultiMC-wrapped $out/MultiMC/MultiMC
mv $out/MultiMC/bin/.MultiMC-wrapped $out/MultiMC/bin/MultiMC
runHook postInstall
'';
dontWrapQtApps = true;
preFixup = ''
'';
}
From the website, you have 2 options, the .deb and the source tar file. Decompiling the .deb, leads to this script
#!/bin/bash
INSTDIR="${XDG_DATA_HOME-$HOME/.local/share}/multimc"
if [ `getconf LONG_BIT` = "64" ]
then
PACKAGE="mmc-stable-lin64.tar.gz"
else
PACKAGE="mmc-stable-lin32.tar.gz"
fi
deploy() {
mkdir -p $INSTDIR
cd ${INSTDIR}
wget --progress=dot:force "https://files.multimc.org/downloads/${PACKAGE}" 2>&1 | sed -u 's/.* \([0-9]\+%\)\ \+\([0-9.]\+.\) \(.*\)/\1\n# Downloading at \2\/s, ETA \3/' | zenity --progress --auto-close --auto-kill --title="Downloading MultiMC..."
tar -xzf ${PACKAGE} --transform='s,MultiMC/,,'
rm ${PACKAGE}
chmod +x MultiMC
}
runmmc() {
cd ${INSTDIR}
./MultiMC "$@"
}
if [[ ! -f ${INSTDIR}/MultiMC ]]; then
deploy
runmmc "$@"
else
runmmc "$@"
fi
The key part of the code is :
wget --progress=dot:force "https://files.multimc.org/downloads/${PACKAGE}" 2>&1 | sed -u 's/.* \([0-9]\+%\)\ \+\([0-9.]\+.\) \(.*\)/\1\n# Downloading at \2\/s, ETA \3/' | zenity --progress --auto-close --auto-kill --title="Downloading MultiMC..."
So the .deb wget’s the latest package from the website, unpacks the tar file, and makes the script in the tar file executable.
What is more interesting is the script and application in the tar file.
The Script:
#!/bin/bash
# Basic start script for running the launcher with the libs packaged with it.
function printerror {
printf "$1"
if which zenity >/dev/null; then zenity --error --text="$1" &>/dev/null;
elif which kdialog >/dev/null; then kdialog --error "$1" &>/dev/null;
fi
}
if [[ $EUID -eq 0 ]]; then
printerror "This program should not be run using sudo or as the root user!\n"
exit 1
fi
LAUNCHER_NAME=MultiMC
LAUNCHER_DIR="$(dirname "$(readlink -f "$0")")"
echo "Launcher Dir: ${LAUNCHER_DIR}"
# Set up env - filter out input LD_ variables but pass them in under different names
export GAME_LIBRARY_PATH=${GAME_LIBRARY_PATH-${LD_LIBRARY_PATH}}
export GAME_PRELOAD=${GAME_PRELOAD-${LD_PRELOAD}}
export LD_LIBRARY_PATH="${LAUNCHER_DIR}/bin":$LAUNCHER_LIBRARY_PATH
export LD_PRELOAD=$LAUNCHER_PRELOAD
export QT_PLUGIN_PATH="${LAUNCHER_DIR}/plugins"
export QT_FONTPATH="${LAUNCHER_DIR}/fonts"
# Detect missing dependencies...
DEPS_LIST=`ldd "${LAUNCHER_DIR}"/plugins/*/*.so 2>/dev/null |QT_PLUGIN_PATH grep "not found" | sort -u | awk -vORS=", " '{ print $1 }'`
if [ "x$DEPS_LIST" = "x" ]; then
# We have all our dependencies. Run the launcher.
echo "No missing dependencies found."
# Just to be sure...
chmod +x "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}"
# Run the launcher
exec -a "${LAUNCHER_DIR}/${LAUNCHER_NAME}" "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}" -d "${LAUNCHER_DIR}" "$@"
# Run the launcher in valgrind
# valgrind --log-file="valgrind.log" --leak-check=full --track-origins=yes "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}" -d "${LAUNCHER_DIR}" "$@"
# Run the launcher with callgrind, delay instrumentation
# valgrind --log-file="valgrind.log" --tool=callgrind --instr-atstart=no "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}" -d "${LAUNCHER_DIR}" "$@"
# use callgrind_control -i on/off to profile actions
# Exit with launcher's exit code.
# exit $?
else
# apt
if which apt-file &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do apt-file -l search $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo apt-get install $COMMAND_LIBS"
# pacman
elif which pkgfile &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pkgfile $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo pacman -S $COMMAND_LIBS"
# dnf
elif which dnf &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do dnf whatprovides -q $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | grep -v 'Repo' | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo dnf install $COMMAND_LIBS"
# yum
elif which yum &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do yum whatprovides $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo yum install $COMMAND_LIBS"
# zypper
elif which zypper &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do zypper wp $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo zypper install $COMMAND_LIBS"
# emerge
elif which pfl &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pfl $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo emerge $COMMAND_LIBS"
fi
MESSAGE="Error: The launcher is missing the following libraries that it needs to work correctly:\n\t${DEPS_LIST}\nPlease install them from your distribution's package manager."
MESSAGE="$MESSAGE\n\nHint (please apply common sense): $INSTALL_CMD\n"
printerror "$MESSAGE"
exit 1
fi
The key parts are:
LAUNCHER_NAME=MultiMC
LAUNCHER_DIR="$(dirname "$(readlink -f "$0")")"
echo "Launcher Dir: ${LAUNCHER_DIR}"
# Set up env - filter out input LD_ variables but pass them in under different names
export GAME_LIBRARY_PATH=${GAME_LIBRARY_PATH-${LD_LIBRARY_PATH}}
export GAME_PRELOAD=${GAME_PRELOAD-${LD_PRELOAD}}
export LD_LIBRARY_PATH="${LAUNCHER_DIR}/bin":$LAUNCHER_LIBRARY_PATH
export LD_PRELOAD=$LAUNCHER_PRELOAD
export QT_PLUGIN_PATH="${LAUNCHER_DIR}/plugins"
export QT_FONTPATH="${LAUNCHER_DIR}/fonts"
and
exec -a "${LAUNCHER_DIR}/${LAUNCHER_NAME}" "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}" -d "${LAUNCHER_DIR}" "$@"
So, the the original application was expecting QT_PLUGIN_PATH to have the path for the QT plugins and then calling the application with that information. But I think I fixed that in the build config with:
substituteInPlace $out/MultiMC/MultiMC \
--replace 'QT_PLUGIN_PATH="''${LAUNCHER_DIR}/plugins"' "QT_PLUGIN_PATH=\"${qt5.qtbase.bin}/${qt5.qtbase.qtPluginPrefix}\""
I would like some advice on how to get MultiMC to run on Nixos. Any help would be appreciated.