{ lib, pkgs, inputs, ... }: pkgs.stdenv.mkDerivation rec { pname = "wallpaper-engine-kde-plugin"; version = "unstable-2023-07-01"; src = inputs.wallpaper-engine-plugin-src; nativeBuildInputs = with pkgs; [ cmake extra-cmake-modules pkg-config gst_all_1.gst-libav shaderc glslang # GLSL compiler libsForQt5.kpackage # For kpackagetool5 libsForQt5.plasma-framework # Additional KDE tools libsForQt5.kdeclarative # Additional KDE build tools python312 sysprof # For sysprof-capture autoPatchelfHook # Fix RPATH issues ]; buildInputs = with pkgs; [ mpv lz4 vulkan-headers vulkan-tools vulkan-loader wayland wayland-protocols libass spirv-tools xorg.libXext xorg.libX11 ] ++ (with pkgs.libsForQt5; with pkgs.qt5; [ plasma-framework qtwebsockets qtwebchannel qtx11extras qtdeclarative qtbase qtbase.dev # For Qt private headers like qpa/qplatformnativeinterface.h qtmultimedia dbus ]); cmakeFlags = [ "-DUSE_PLASMAPKG=ON" "-DQT_MAJOR_VERSION=5" "-DCMAKE_PREFIX_PATH=${pkgs.qt5.qtbase.dev}/lib/cmake:${pkgs.libsForQt5.plasma-framework}/lib/cmake" "-DENABLE_OPT=0" # Disable SPIRV optimizer to avoid dependency issues "-DBUILD_SCENE_RENDERER=OFF" # Disable scene renderer but keep QML "-DBUILD_MPV_PLAYER=OFF" # Disable MPV player due to Qt private headers issues "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}" "-DCMAKE_INSTALL_LIBDIR=lib" # Ensure we use the right lib directory "-DKDE_INSTALL_PLUGINDIR=${placeholder "out"}/lib/qt5/plugins" "-DKDE_INSTALL_QMLDIR=${placeholder "out"}/lib/qt5/qml" "-DPLASMA_INSTALL_WALLPAPERDIR=${placeholder "out"}/share/plasma/wallpapers" "-DCMAKE_SKIP_BUILD_RPATH=ON" "-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON" "-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON" "-DCMAKE_BUILD_RPATH=" "-DCMAKE_INSTALL_RPATH=$ORIGIN;${pkgs.lib.makeLibraryPath buildInputs}" ]; # Don't attempt to wrap Qt apps since we're just building libraries dontWrapQtApps = true; # Don't use the standard Nix fixup phase as we'll handle RPATHs ourselves dontPatchELF = true; # Don't put any build references in the resulting binary disallowedReferences = [ pkgs.stdenv.cc.cc ]; # Create a symlink to kpackagetool5 so the build can find it as kpackagetool preConfigure = '' mkdir -p $NIX_BUILD_TOP/bin ln -s ${pkgs.libsForQt5.kpackage}/bin/kpackagetool5 $NIX_BUILD_TOP/bin/kpackagetool export PATH="$NIX_BUILD_TOP/bin:$PATH" # Set PKG_CONFIG_PATH for MPV to ensure it can be found export PKG_CONFIG_PATH="${pkgs.mpv}/lib/pkgconfig:$PKG_CONFIG_PATH" ''; # Fix the build with a minimal backend_scene CMakeLists.txt and patch for Qt5/6 compatibility postPatch = '' # Create backend_scene directory with CMakeLists.txt that provides a stub library mkdir -p src/backend_scene # Create stub header files for the backends cat > src/MpvBackend.hpp << 'EOF' // Stub MpvBackend header #ifndef MPVBACKEND_HPP #define MPVBACKEND_HPP #include #include namespace mpv { class MpvObject : public QObject { Q_OBJECT public: MpvObject(QObject *parent = nullptr) : QObject(parent) {} virtual ~MpvObject() {} }; } #endif // MPVBACKEND_HPP EOF cat > src/SceneBackend.hpp << 'EOF' // Stub SceneBackend header #ifndef SCENEBACKEND_HPP #define SCENEBACKEND_HPP #include #include #include namespace scenebackend { class SceneObject : public QObject { Q_OBJECT public: SceneObject(QObject *parent = nullptr) : QObject(parent) {} virtual ~SceneObject() {} static QString GetDefaultCachePath() { return QString("/tmp"); } }; } #endif // SCENEBACKEND_HPP EOF # Create a stub implementation file cat > src/backend_scene/stub_renderer.cpp << 'EOF' // Stub implementation to satisfy the linker #include #include #include // Forward declaration to avoid Q_OBJECT macro issues class WESceneRenderer { public: WESceneRenderer() {} ~WESceneRenderer() {} }; // This prevents "undefined reference" errors during linking extern "C" { void* wescene_renderer_create_instance() { return new WESceneRenderer(); } } class WESceneRendererProvider { public: static void registerQmlTypes() { // Stub implementation } }; EOF # Replace Qt6 references with Qt5 everywhere find . -type f -name "CMakeLists.txt" -exec sed -i 's/find_package(Qt6/find_package(Qt5/g' {} \; find . -type f -name "CMakeLists.txt" -exec sed -i 's/Qt::/Qt5::/g' {} \; # Add QT_MAJOR_VERSION=5 to the top-level CMakeLists.txt if not already set if ! grep -q "set(QT_MAJOR_VERSION 5)" CMakeLists.txt; then sed -i '/cmake_minimum_required/a set(QT_MAJOR_VERSION 5)' CMakeLists.txt fi # Create CMakeLists for MPV backend with fixed lib reference cat > src/backend_mpv/CMakeLists.txt << 'EOF' # Stub CMakeLists.txt for mpvbackend - not actually built due to BUILD_MPV_PLAYER=OFF message(STATUS "MPV backend disabled by build configuration") EOF # Create CMakeLists for scene backend cat > src/backend_scene/CMakeLists.txt << 'EOF' # Minimal CMakeLists.txt for backend_scene project(wescene-renderer) find_package(Qt5 REQUIRED COMPONENTS Core Quick) # Create a simple library to satisfy the dependency add_library(wescene-renderer-qml SHARED stub_renderer.cpp) set_target_properties(wescene-renderer-qml PROPERTIES AUTOMOC ON ) target_link_libraries(wescene-renderer-qml PRIVATE Qt5::Core Qt5::Quick ) install( TARGETS wescene-renderer-qml DESTINATION lib ) EOF # Add necessary includes to MpvBackend.cpp if [ -f "src/backend_mpv/MpvBackend.cpp" ]; then # Add the include for QtX11Extras before QX11Info if it uses it if grep -q "QX11Info" src/backend_mpv/MpvBackend.cpp && ! grep -q "#include " src/backend_mpv/MpvBackend.cpp; then sed -i '/#include /i #include ' src/backend_mpv/MpvBackend.cpp fi # Make sure we use the right Qt namespace sed -i 's/Qt::/Qt5::/g' src/backend_mpv/MpvBackend.cpp # Fix the include path for qplatformnativeinterface.h sed -i 's|#include |#include |g' src/backend_mpv/MpvBackend.cpp fi # Override main src/CMakeLists.txt if necessary if [ -f "src/CMakeLists.txt" ]; then # Ensure we add the missing Qt5 dependencies if ! grep -q "find_package(Qt5 .* X11Extras" src/CMakeLists.txt; then sed -i 's/find_package(Qt5 REQUIRED COMPONENTS/find_package(Qt5 REQUIRED COMPONENTS X11Extras /' src/CMakeLists.txt fi fi # Fix plugin.cpp by commenting out problematic lines if [ -f "src/plugin.cpp" ]; then sed -i '/qmlRegisterType/s/^/\/\//' src/plugin.cpp sed -i '/qmlRegisterType/s/^/\/\//' src/plugin.cpp fi # Fix the main CMakeLists.txt to remove mpvbackend dependency if [ -f "src/CMakeLists.txt" ]; then # Replace mpvbackend in the target_link_libraries command sed -i 's/mpvbackend//' src/CMakeLists.txt fi # Fix PluginInfo.cpp by stubbing out problematic lines if [ -f "src/PluginInfo.cpp" ]; then sed -i 's#QString::fromStdString(scenebackend::SceneObject::GetDefaultCachePath())#QString("/tmp")#' src/PluginInfo.cpp fi ''; # Skip the standard CMake installation and do a custom one to avoid RPATH issues installPhase = '' runHook preInstall # Create required directory structure mkdir -p $out/lib/qt5/qml/com/github/catsout/wallpaperEngineKde/ \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/code/ \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ui/ # Install libwescene-renderer-qml.so install -Dm755 src/backend_scene/libwescene-renderer-qml.so $out/lib/libwescene-renderer-qml.so # Install libWallpaperEngineKde.so install -Dm755 src/libWallpaperEngineKde.so $out/lib/qt5/qml/com/github/catsout/wallpaperEngineKde/libWallpaperEngineKde.so # Create qmldir file for QML import cat > $out/lib/qt5/qml/com/github/catsout/wallpaperEngineKde/qmldir << EOF module com.github.catsout.wallpaperEngineKde plugin WallpaperEngineKde EOF # First check the tmp-src location for plugin files if [ -d "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin" ]; then echo "Copying plugin files from tmp-src directory" cp -r "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin"/* $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/ # Then check other possible locations elif [ -d "plugin" ]; then cp -r plugin/* $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/ elif [ -d "source/plugin" ]; then cp -r source/plugin/* $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/ else # If no plugin directory, copy QML files from src/qml if it exists if [ -d "src/qml" ]; then cp -r src/qml/* $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ui/ fi fi # Create metadata.desktop file using the one from the source if available if [ -f "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/metadata.desktop" ]; then echo "Using metadata.desktop from source repository" cp "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/metadata.desktop" \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/metadata.desktop else # Create our own metadata.desktop file cat > $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/metadata.desktop << EOF [Desktop Entry] Name=Wallpaper Engine Comment=Use Wallpaper Engine's wallpaper Type=Service Icon=preferences-desktop-wallpaper X-Plasma-MainScript=ui/main.qml X-KDE-ServiceTypes=Plasma/Wallpaper X-KDE-PluginInfo-Name=com.github.catsout.wallpaperEngineKde X-KDE-PluginInfo-Author=catsout X-KDE-PluginInfo-Email= X-KDE-PluginInfo-Version=1.0 X-KDE-PluginInfo-Website=https://github.com/catsout/wallpaper-engine-kde-plugin X-KDE-PluginInfo-License=GPLv2+ X-KDE-PluginInfo-EnabledByDefault=true EOF fi # Create symlinks for the libraries mkdir -p $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/code/ ln -s $out/lib/qt5/qml/com/github/catsout/wallpaperEngineKde/libWallpaperEngineKde.so \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/code/ ln -s $out/lib/libwescene-renderer-qml.so \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/code/ # Copy UI files and other plugin content if [ -d "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents" ]; then echo "Copying UI files and plugin content from tmp-src directory" # Copy UI files if [ -d "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents/ui" ]; then echo " - Copying UI files" cp -r "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents/ui"/* \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ui/ fi # Copy config files if [ -d "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents/config" ]; then echo " - Copying config files" mkdir -p $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/config/ cp -r "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents/config"/* \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/config/ fi # Copy images if [ -d "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents/images" ]; then echo " - Copying image files" mkdir -p $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/images/ cp -r "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents/images"/* \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/images/ fi # Copy Python extensions if present if [ -f "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents/pyext.py" ]; then echo " - Copying Python extensions" cp "${src}/../tmp-src/wallpaper-engine-kde-plugin/plugin/contents/pyext.py" \ $out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ fi elif [ ! -f "$out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ui/main.qml" ]; then echo "Warning: No main.qml file found in tmp-src, attempting to extract from source" # Try to preserve directory structure for QML files for qmlfile in $(find . -name "*.qml"); do # Get the directory structure after src/qml if it exists if echo "$qmlfile" | grep -q "src/qml/"; then relative_path=$(echo "$qmlfile" | sed 's|.*/src/qml/||') target_dir=$(dirname "$out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ui/$relative_path") mkdir -p "$target_dir" cp "$qmlfile" "$target_dir/" echo " - Copied $qmlfile to $target_dir" else # Just copy directly to UI dir for other QML files base=$(basename "$qmlfile") cp "$qmlfile" "$out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ui/$base" echo " - Copied $qmlfile to ui/$base" fi done # Try to find and copy JavaScript files too for jsfile in $(find . -name "*.js"); do # Get the directory structure after src/qml if it exists if echo "$jsfile" | grep -q "src/qml/"; then relative_path=$(echo "$jsfile" | sed 's|.*/src/qml/||') target_dir=$(dirname "$out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ui/$relative_path") mkdir -p "$target_dir" cp "$jsfile" "$target_dir/" echo " - Copied $jsfile to $target_dir" fi done fi runHook postInstall ''; # Fix any remaining RPATH issues postFixup = '' echo "Running postFixup to fix RPATH issues..." # Function to fix RPATH for a given library fix_rpath() { local lib="$1" if [ -f "$lib" ]; then echo "Fixing RPATH for $lib" # Create a new clean RPATH with only the necessary paths # Include Qt and KDE plugin directories local new_rpath="${pkgs.lib.makeLibraryPath buildInputs}:${pkgs.lib.makeLibraryPath nativeBuildInputs}:$out/lib" # Strip duplicate paths if any new_rpath=$(echo "$new_rpath" | tr ':' '\n' | sort | uniq | tr '\n' ':') # Use patchelf to set the RPATH without preserving any build paths if ! patchelf --set-rpath "$new_rpath" "$lib"; then echo "Warning: Failed to set RPATH for $lib, trying with force-rpath" patchelf --force-rpath --set-rpath "$new_rpath" "$lib" || echo "ERROR: RPATH fix failed for $lib" fi # Verify the RPATH was set correctly echo "New RPATH for $lib:" patchelf --print-rpath "$lib" || echo "ERROR: Could not read RPATH for $lib" # Check for remaining build references if patchelf --print-rpath "$lib" | grep -q "/build"; then echo "Warning: Build path still in RPATH after cleanup. This might cause issues." else echo "RPATH cleanup successful for $lib" fi else echo "Warning: Library $lib not found, skipping RPATH fix" fi } # Fix RPATH for all libraries fix_rpath "$out/lib/libwescene-renderer-qml.so" fix_rpath "$out/lib/qt5/qml/com/github/catsout/wallpaperEngineKde/libWallpaperEngineKde.so" # Verify symlinks are working echo "Verifying symlinks..." if [ -L "$out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/code/libWallpaperEngineKde.so" ]; then echo "Symlink to libWallpaperEngineKde.so exists" ls -la "$out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/code/libWallpaperEngineKde.so" else echo "ERROR: Missing symlink to libWallpaperEngineKde.so" fi # Check that main.qml exists if [ -f "$out/share/plasma/wallpapers/com.github.catsout.wallpaperEngineKde/contents/ui/main.qml" ]; then echo "main.qml found" else echo "ERROR: main.qml not found" fi ''; meta = with lib; { description = "Wallpaper Engine KDE plasma plugin"; homepage = "https://github.com/catsout/wallpaper-engine-kde-plugin"; license = licenses.gpl2Plus; platforms = platforms.linux; maintainers = [ ]; }; }