]> Some of my projects - aniplayer.git/commitdiff
Add CMake build system
authorAPTX <marek321@gmail.com>
Thu, 23 Nov 2017 15:47:59 +0000 (00:47 +0900)
committerAPTX <marek321@gmail.com>
Thu, 23 Nov 2017 16:04:36 +0000 (01:04 +0900)
qmake is to be removed

16 files changed:
.gitignore
CMakeLists.txt [new file with mode: 0644]
backendplugins/CMakeLists.txt [new file with mode: 0644]
backendplugins/backend_mpv/CMakeLists.txt [new file with mode: 0644]
core/CMakeLists.txt [new file with mode: 0644]
core/qtsingleapplication/CMakeLists.txt [new file with mode: 0644]
featureplugins/CMakeLists.txt [new file with mode: 0644]
featureplugins/feature_localmylist/CMakeLists.txt [new file with mode: 0644]
pluginapi/CMakeLists.txt [new file with mode: 0644]
pluginapi/aniplayer/backendpluginbase.h [new file with mode: 0644]
pluginapi/aniplayer/featurepluginbase.h [new file with mode: 0644]
pluginapi/aniplayer/playerfeatureplugininterface.h [new file with mode: 0644]
pluginapi/aniplayer/playerplugininterface.h [new file with mode: 0644]
pluginapi/aniplayer/uipluginbase.h [new file with mode: 0644]
uiplugins/CMakeLists.txt [new file with mode: 0644]
uiplugins/ui_desktop_qml_default/CMakeLists.txt [new file with mode: 0644]

index fa63ce16c2516cb665161dac794529f9fb048c41..2c89b87e1c07b2161e9946268bc12894343b84ee 100644 (file)
@@ -30,6 +30,7 @@ qrc_*.cpp
 # qtcreator generated files
 *.pro.user
 *.pro.user.*
+CMakeLists.txt.user
 *.autosave
 *.files
 *.creator
@@ -63,6 +64,7 @@ qrc_*.cpp
 # ---------------------
 
 build
+cmakebuild
 debug
 release
 lib/qtsingleapplication/lib
@@ -71,12 +73,3 @@ lib/qtsingleapplication/doc
 .tmp
 qtc-gdbmacros
 test-data
-
-# Binaries
-# --------
-build/*.dll
-build/*.lib
-build/*.exe
-build/*.so*
-
-
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f9bc421
--- /dev/null
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
+include(FeatureSummary)
+
+project(AniPlayer)
+
+set(QT_MIN_VERSION "5.3.0")
+
+option(WITH_DESKTOP_UI "Build default QML desktop UI" ON)
+add_feature_info(QmlDesktopUI WITH_DESKTOP_UI "default desktop UI, using QML")
+
+option(WITH_BACKEND_MPV "Build MPV backend" ON)
+add_feature_info(BackendMpv WITH_BACKEND_MPV "the MPV backend")
+
+option(WITH_LOCALMYLIST "Build LocalMyList feature plugin" ON)
+add_feature_info(FeatureLocalMyList WITH_LOCALMYLIST "automatically mark files as watched that are in your LocalMyList")
+
+
+add_subdirectory(pluginapi)
+add_subdirectory(core)
+add_subdirectory(backendplugins)
+add_subdirectory(uiplugins)
+add_subdirectory(featureplugins)
+
+feature_summary(WHAT ALL)
diff --git a/backendplugins/CMakeLists.txt b/backendplugins/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fd4dd74
--- /dev/null
@@ -0,0 +1,7 @@
+project(backendplugins)
+
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/backendplugins)
+
+if (WITH_BACKEND_MPV)
+    add_subdirectory(backend_mpv)
+endif()
diff --git a/backendplugins/backend_mpv/CMakeLists.txt b/backendplugins/backend_mpv/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d338026
--- /dev/null
@@ -0,0 +1,55 @@
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+project(backend_mpv)
+
+find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
+    Core
+    Gui
+    Qml
+    Quick
+)
+
+set(backend_mpv_LIBS
+    Qt5::Core
+    Qt5::Gui
+    pluginapi
+    # TODO find_package this
+    mpv-1
+)
+
+set(backend_mpv_SOURCES
+    backendmpv.cpp
+)
+
+set(backend_mpv_HEADERS
+    backendmpv.h
+    backend_mpv_global.h
+)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTORCC ON)
+
+add_library(backend_mpv MODULE
+    ${backend_mpv_SOURCES}
+    ${backend_mpv_HEADERS}
+)
+
+set_property(TARGET backend_mpv PROPERTY CXX_STANDARD 14)
+set_property(TARGET backend_mpv PROPERTY OUTPUT_NAME "backend_mpv")
+target_link_libraries(backend_mpv ${backend_mpv_LIBS})
+
+add_definitions(-DBACKEND_MPV_LIBRARY)
+
+if(WIN32)
+    set(INSTALL_DESTINATION "aniplayer/uiplugins")
+else()
+    set(INSTALL_DESTINATION "lib${LIB_SUFFIX}/aniplayer/uiplugins")
+endif()
+
+install(TARGETS backend_mpv
+    LIBRARY DESTINATION ${INSTALL_DESTINATION}
+    ARCHIVE DESTINATION ${INSTALL_DESTINATION}
+)
+install(FILES $<TARGET_PDB_FILE:backend_mpv>
+    DESTINATION ${INSTALL_DESTINATION} OPTIONAL
+)
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
new file mode 100644 (file)
index 0000000..49cc671
--- /dev/null
@@ -0,0 +1,92 @@
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+project(core)
+
+set(core_VERSION "0.4.0")
+
+add_subdirectory("qtsingleapplication")
+
+find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
+    Core
+    Gui
+    Widgets
+    Qml
+    Quick
+)
+
+find_package(LocalMyList CONFIG REQUIRED)
+
+set(core_LIBS
+    Qt5::Core
+    Qt5::Gui
+    Qt5::Widgets
+    Qt5::Qml
+    Qt5::Quick
+    pluginapi
+    qtsingleapplication
+)
+
+if(WITH_ANIDBUDPCLIENT)
+    find_package(AniDBUdpClient CONFIG REQUIRED)
+endif()
+
+set(core_SOURCES
+    main.cpp
+    player.cpp
+    pluginmanager.cpp
+    videoelement.cpp
+    instancemanager.cpp
+    settings.cpp
+    trackmodel.cpp
+    chaptermodel.cpp
+    annotationmodel.cpp
+)
+
+set(core_HEADERS
+    player.h
+    pluginmanager.h
+    videoelement.h
+    instancemanager.h
+    settings.h
+    trackmodel.h
+    chaptermodel.h
+    annotationmodel.h
+)
+
+set(core_PUBLIC_HEADERS
+    include/aniplayer/backendpluginbase.h
+    include/aniplayer/playerplugininterface.h
+    include/aniplayer/featurepluginbase.h
+    include/aniplayer/uipluginbase.h
+    include/aniplayer/playerfeatureplugininterface.h
+)
+
+if(WIN32)
+    set(core_SOURCES
+        ${core_SOURCES}
+        aniplayer.rc
+    )
+    # TODO CMake should handle this automatically
+    set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST:NO")
+endif()
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTORCC ON)
+
+add_executable(core WIN32
+    ${core_SOURCES}
+    ${core_HEADERS}
+)
+
+set_property(TARGET core PROPERTY CXX_STANDARD 14)
+set_property(TARGET core PROPERTY OUTPUT_NAME "aniplayer")
+target_link_libraries(core ${core_LIBS})
+
+install(TARGETS core
+    LIBRARY DESTINATION lib${LIB_SUFFIX}
+    ARCHIVE DESTINATION lib${LIB_SUFFIX}
+    RUNTIME DESTINATION bin
+)
+install(FILES $<TARGET_PDB_FILE:core> DESTINATION bin OPTIONAL)
diff --git a/core/qtsingleapplication/CMakeLists.txt b/core/qtsingleapplication/CMakeLists.txt
new file mode 100644 (file)
index 0000000..30a3d46
--- /dev/null
@@ -0,0 +1,41 @@
+set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
+project(qtsingleapplication)
+
+find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
+    Core
+    Widgets
+    Network
+)
+
+set(qtsingleapplication_LIBS
+    Qt5::Core
+    Qt5::Widgets
+    Qt5::Network
+)
+
+set(qtsingleapplication_SOURCES
+    qtsingleapplication.cpp
+    qtlocalpeer.cpp
+)
+
+set(qtsingleapplication_HEADERS
+    qtsingleapplication.h
+    qtlocalpeer.h
+)
+
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTORCC ON)
+
+add_library(qtsingleapplication STATIC
+    ${qtsingleapplication_SOURCES}
+    ${qtsingleapplication_HEADERS}
+)
+
+set_property(TARGET qtsingleapplication PROPERTY CXX_STANDARD 14)
+target_link_libraries(qtsingleapplication ${qtsingleapplication_LIBS})
+if(WIN32)
+    add_definitions(-DUNICODE -D_UNICODE)
+endif()
+
diff --git a/featureplugins/CMakeLists.txt b/featureplugins/CMakeLists.txt
new file mode 100644 (file)
index 0000000..acee97d
--- /dev/null
@@ -0,0 +1,7 @@
+project(featureplugins)
+
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/featureplugins)
+
+if (WITH_LOCALMYLIST)
+    add_subdirectory(feature_localmylist)
+endif()
diff --git a/featureplugins/feature_localmylist/CMakeLists.txt b/featureplugins/feature_localmylist/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ca92f1d
--- /dev/null
@@ -0,0 +1,53 @@
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+project(feature_localmylist)
+
+find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
+    Core
+)
+
+find_package(LocalMyList CONFIG REQUIRED)
+
+set(feature_localmylist_LIBS
+    Qt5::Core
+    pluginapi
+    # TODO find_package this
+    LocalMyList::LocalMyList
+)
+
+set(feature_localmylist_SOURCES
+    featurelocalmylist.cpp
+)
+
+set(feature_localmylist_HEADERS
+    featurelocalmylist.h
+    feature_localmylist_global.h
+)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTORCC ON)
+
+add_library(feature_localmylist MODULE
+    ${feature_localmylist_SOURCES}
+    ${feature_localmylist_HEADERS}
+)
+
+set_property(TARGET feature_localmylist PROPERTY CXX_STANDARD 14)
+set_property(TARGET feature_localmylist PROPERTY OUTPUT_NAME "feature_localmylist")
+target_link_libraries(feature_localmylist ${feature_localmylist_LIBS})
+
+add_definitions(-DFEATURE_LOCALMYLIST_LIBRARY)
+
+if(WIN32)
+    set(INSTALL_DESTINATION "aniplayer/uiplugins")
+else()
+    set(INSTALL_DESTINATION "lib${LIB_SUFFIX}/aniplayer/uiplugins")
+endif()
+
+install(TARGETS feature_localmylist
+    LIBRARY DESTINATION ${INSTALL_DESTINATION}
+    ARCHIVE DESTINATION ${INSTALL_DESTINATION}
+)
+install(FILES $<TARGET_PDB_FILE:feature_localmylist>
+    DESTINATION ${INSTALL_DESTINATION} OPTIONAL
+)
diff --git a/pluginapi/CMakeLists.txt b/pluginapi/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c25990b
--- /dev/null
@@ -0,0 +1,24 @@
+set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
+project(pluginapi CXX)
+
+set(pluginapi_PUBLIC_HEADERS
+    aniplayer/backendpluginbase.h
+    aniplayer/playerplugininterface.h
+    aniplayer/featurepluginbase.h
+    aniplayer/uipluginbase.h
+    aniplayer/playerfeatureplugininterface.h
+)
+
+add_library(pluginapi INTERFACE)
+find_package(Qt5 COMPONENTS Core)
+target_link_libraries(pluginapi INTERFACE ${pluginapi_LIBS})
+target_link_libraries(pluginapi INTERFACE Qt5::Core)
+
+install(FILES ${pluginapi_PUBLIC_HEADERS}
+    DESTINATION include/aniplayer
+)
+
+# IDE hack
+#project(pluginapi_ide CXX)
+add_custom_target(pluginapi_ide SOURCES ${pluginapi_PUBLIC_HEADERS})
+
diff --git a/pluginapi/aniplayer/backendpluginbase.h b/pluginapi/aniplayer/backendpluginbase.h
new file mode 100644 (file)
index 0000000..56d6728
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef BACKENDPLUGINBASE_H
+#define BACKENDPLUGINBASE_H
+
+#include "playerplugininterface.h"
+
+class QUrl;
+
+class BackendInstance {
+public:
+  using TrackIndex = int;
+  // In seconds
+  using TimeStamp = double;
+  // Volume valid range is 0.0-1.0
+  using Volume = double;
+  virtual ~BackendInstance() = default;
+
+  virtual VideoRendererBase *createRenderer(VideoUpdateInterface *) = 0;
+
+  virtual bool open(const QUrl &resource) = 0;
+
+  virtual void play() = 0;
+  virtual void pause() = 0;
+  virtual void stop() = 0;
+
+  virtual void seek(TimeStamp) = 0;
+
+  virtual void setVolume(Volume) = 0;
+
+  virtual void setCurrentVideoStream(TrackIndex) = 0;
+  virtual void setCurrentAudioStream(TrackIndex) = 0;
+  virtual void setCurrentSubtitleStream(TrackIndex) = 0;
+};
+
+class BackendPluginBase {
+public:
+  virtual ~BackendPluginBase() = default;
+
+  virtual BackendInstance *createInstance(PlayerPluginInterface *) = 0;
+};
+
+#define ANIPLAYER_BACKEND_DPLUGIN_INTERFACE_IID                                \
+  "org.aptx.aniplayer.BackendPluginInterface"
+
+#include <QObject>
+Q_DECLARE_INTERFACE(BackendPluginBase, ANIPLAYER_BACKEND_DPLUGIN_INTERFACE_IID)
+
+#endif // BACKENDPLUGINBASE_H
diff --git a/pluginapi/aniplayer/featurepluginbase.h b/pluginapi/aniplayer/featurepluginbase.h
new file mode 100644 (file)
index 0000000..b20b3b3
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef FEATUREPLUGINBASE_H
+#define FEATUREPLUGINBASE_H
+
+#include <QObject>
+
+#include "aniplayer/playerfeatureplugininterface.h"
+
+class FeaturePluginInstance {
+public:
+  virtual ~FeaturePluginInstance() = default;
+
+  FeaturePluginInstance(QObject *player,
+                        PlayerFeaturePlauginInterface *interface)
+      : m_player{player}, m_playerInterface{interface} {}
+
+protected:
+  QObject *m_player;
+  PlayerFeaturePlauginInterface *m_playerInterface;
+};
+
+class FeaturePluginBase {
+public:
+  virtual ~FeaturePluginBase() = default;
+
+  virtual FeaturePluginInstance *
+  createInstance(QObject *instance, PlayerFeaturePlauginInterface *) = 0;
+};
+
+#define ANIPLAYER_FEATURE_PLUGIN_INTERFACE_IID                                 \
+  "org.aptx.aniplayer.FeaturePluginInterface"
+
+Q_DECLARE_INTERFACE(FeaturePluginBase, ANIPLAYER_FEATURE_PLUGIN_INTERFACE_IID)
+
+#endif // FEATUREPLUGINBASE_H
diff --git a/pluginapi/aniplayer/playerfeatureplugininterface.h b/pluginapi/aniplayer/playerfeatureplugininterface.h
new file mode 100644 (file)
index 0000000..b738094
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef PLAYERFEATUREPLUGININTERFACE_H
+#define PLAYERFEATUREPLUGININTERFACE_H
+
+#include <QString>
+#include <QList>
+
+class PlayerFeaturePlauginInterface {
+public:
+  struct Annotation {
+    double x;
+    double y;
+    double w;
+    double h;
+    QString color;
+    QString text;
+  };
+
+  using AnnotationList = QList<Annotation>;
+
+  virtual ~PlayerFeaturePlauginInterface() = default;
+
+  virtual void featureShowStatusMessage(const QString &message) = 0;
+
+  virtual void featureSetAnnotations(const AnnotationList &) = 0;
+};
+
+#endif // PLAYERFEATUREPLUGININTERFACE_H
diff --git a/pluginapi/aniplayer/playerplugininterface.h b/pluginapi/aniplayer/playerplugininterface.h
new file mode 100644 (file)
index 0000000..1f7b70a
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef PLAYERPLUGININTERFACE_H
+#define PLAYERPLUGININTERFACE_H
+
+#include <QtGlobal>
+#include <QUrl>
+
+class QOpenGLFramebufferObject;
+
+class VideoUpdateInterface {
+public:
+  virtual ~VideoUpdateInterface() = default;
+
+  virtual void videoUpdated() = 0;
+};
+
+class PlayerPluginInterface {
+public:
+  using TrackIndex = int;
+  using TimeStamp = double;
+  using Volume = double;
+
+  enum class PlayState { Stopped, Paused, Playing };
+  /*
+   *    .-----.
+   *    |     | Error
+   *    v     |
+   * Stopped -'<--+<-------.
+   *    |         ^        |
+   *    | Load    | Error  |
+   *    v         |        |
+   * Paused<------+        | File End
+   *    |         ^        |
+   *    | Play    | Pause  |
+   *    v         |        |
+   * Playing------+--------'
+   */
+
+  virtual ~PlayerPluginInterface() = default;
+
+  virtual void backendReadyToPlay() = 0;
+
+  virtual void backendSourceChanged(QUrl source) = 0;
+  virtual void playStateChanged(PlayState) = 0;
+  virtual void playbackDurationChanged(TimeStamp) = 0;
+  virtual void playbackPositionChanged(TimeStamp) = 0;
+  virtual void playbackVolumeChanged(Volume) = 0;
+  virtual void playbackMaxVolumeChanged(Volume) = 0;
+
+  struct Track {
+    QString title;
+    QString language;
+    int id;
+  };
+  using TrackList = QList<Track>;
+  virtual void backendVideoTracksChanged(const TrackList &) = 0;
+  virtual void backendAudioTracksChanged(const TrackList &) = 0;
+  virtual void backendSubtitleTracksChanged(const TrackList &) = 0;
+
+  virtual void backendCurrentVideoTrackChanged(TrackIndex) = 0;
+  virtual void backendCurrentAudioTrackChanged(TrackIndex) = 0;
+  virtual void backendCurrentSubtitleTrackChanged(TrackIndex) = 0;
+
+  struct Chapter {
+    QString title;
+    TimeStamp startTime;
+  };
+  using ChapterList = QList<Chapter>;
+  virtual void backendChaptersChanged(const ChapterList &chapters) = 0;
+};
+
+class PlayerRendererInterface {
+public:
+  virtual ~PlayerRendererInterface() = default;
+  virtual void rendererSinkSet(VideoUpdateInterface *) = 0;
+  virtual void rendererReady() = 0;
+};
+
+class VideoRendererBase {
+public:
+  VideoRendererBase() = default;
+  VideoRendererBase(const VideoRendererBase &) = delete;
+  VideoRendererBase &operator=(const VideoRendererBase &) = delete;
+  virtual ~VideoRendererBase() = default;
+  virtual void render(QOpenGLFramebufferObject *) = 0;
+};
+
+#endif // PLAYERPLUGININTERFACE_H
diff --git a/pluginapi/aniplayer/uipluginbase.h b/pluginapi/aniplayer/uipluginbase.h
new file mode 100644 (file)
index 0000000..04b0479
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef UIPLUGINBASE_H
+#define UIPLUGINBASE_H
+
+#include <QObject>
+
+class UiInstance {
+public:
+  virtual ~UiInstance() = default;
+};
+
+class UiPluginBase {
+public:
+  virtual ~UiPluginBase() = default;
+
+  virtual UiInstance *createUi(QObject *player, QObject *settings,
+                               QObject *parent = nullptr) = 0;
+};
+
+#define ANIPLAYER_UI_PLUGIN_INTERFACE_IID "org.aptx.aniplayer.UiPluginInterface"
+
+Q_DECLARE_INTERFACE(UiPluginBase, ANIPLAYER_UI_PLUGIN_INTERFACE_IID)
+
+#endif // UIPLUGINBASE_H
diff --git a/uiplugins/CMakeLists.txt b/uiplugins/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c0ae8c0
--- /dev/null
@@ -0,0 +1,7 @@
+project(uiplugins)
+
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/uiplugins)
+
+if (WITH_DESKTOP_UI)
+    add_subdirectory(ui_desktop_qml_default)
+endif()
diff --git a/uiplugins/ui_desktop_qml_default/CMakeLists.txt b/uiplugins/ui_desktop_qml_default/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6019414
--- /dev/null
@@ -0,0 +1,59 @@
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+project(ui_desktop_qml_default)
+
+find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
+    Core
+    Gui
+    Qml
+    Quick
+)
+
+set(ui_desktop_qml_default_LIBS
+    Qt5::Core
+    Qt5::Gui
+    Qt5::Qml
+    Qt5::Quick
+    pluginapi
+)
+
+set(ui_desktop_qml_default_SOURCES
+    uidesktopqmldefault.cpp
+    timeformatter.cpp
+
+    qml.qrc
+)
+
+set(ui_desktop_qml_default_HEADERS
+    ui_desktop_qml_default_global.h
+    uidesktopqmldefault.h
+    timeformatter.h
+)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTORCC ON)
+
+add_library(ui_desktop_qml_default MODULE
+    ${ui_desktop_qml_default_SOURCES}
+    ${ui_desktop_qml_default_HEADERS}
+)
+
+set_property(TARGET ui_desktop_qml_default PROPERTY CXX_STANDARD 14)
+set_property(TARGET ui_desktop_qml_default PROPERTY OUTPUT_NAME "ui_desktop_qml_default")
+target_link_libraries(ui_desktop_qml_default ${ui_desktop_qml_default_LIBS})
+
+add_definitions(-DUI_DESKTOP_QML_DEFAULT_LIBRARY)
+
+if(WIN32)
+    set(INSTALL_DESTINATION "aniplayer/uiplugins")
+else()
+    set(INSTALL_DESTINATION "lib${LIB_SUFFIX}/aniplayer/uiplugins")
+endif()
+
+install(TARGETS ui_desktop_qml_default
+    LIBRARY DESTINATION ${INSTALL_DESTINATION}
+    ARCHIVE DESTINATION ${INSTALL_DESTINATION}
+)
+install(FILES $<TARGET_PDB_FILE:ui_desktop_qml_default>
+    DESTINATION ${INSTALL_DESTINATION} OPTIONAL
+)