diff --git a/.gitignore b/.gitignore index 86318a6..66814f2 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,11 @@ release/ build/ .idea cmake-build-debug/ -packaging/ + +# Arch package outputs +packaging/arch/pkg/ +packaging/arch/src/ +packaging/arch/*.tar.gz +packaging/arch/*.src.tar.* +packaging/arch/*.pkg.tar.* +packaging/arch/*.log diff --git a/CMakeLists.txt b/CMakeLists.txt index 7349978..c4f4718 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,15 @@ include(QEmbyPlatformDeps) set(QEMBY_RUNTIME_LIB_SUBDIR "qemby" CACHE STRING "Subdirectory under the install libdir for bundled private runtime libraries") +option(QEMBY_USE_SYSTEM_DEPS + "Prefer system packages for third-party dependencies" ON) +option(QEMBY_FETCHCONTENT_FALLBACK + "Allow FetchContent fallback when a system dependency is missing" ON) +option(QEMBY_NATIVE_OPTIMIZE + "Build qEmby targets with -march=native -mtune=native in optimized configs" OFF) +option(QEMBY_ENABLE_IPO + "Enable interprocedural optimization/LTO for qEmby targets" OFF) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") @@ -30,6 +39,46 @@ if(MSVC) add_compile_options(/MP) endif() +if(NOT QEMBY_USE_SYSTEM_DEPS AND NOT QEMBY_FETCHCONTENT_FALLBACK) + message(FATAL_ERROR + "At least one dependency source must be enabled: " + "QEMBY_USE_SYSTEM_DEPS or QEMBY_FETCHCONTENT_FALLBACK") +endif() + +add_library(qemby_build_options INTERFACE) + +if(QEMBY_NATIVE_OPTIMIZE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(qemby_build_options INTERFACE + "$<$:-march=native>" + "$<$:-mtune=native>" + "$<$:-march=native>" + "$<$:-mtune=native>" + ) +endif() + +set(_qemby_ipo_supported FALSE) +if(QEMBY_ENABLE_IPO) + include(CheckIPOSupported) + check_ipo_supported(RESULT _qemby_ipo_supported + OUTPUT _qemby_ipo_error + LANGUAGES CXX) + if(NOT _qemby_ipo_supported) + message(WARNING + "IPO/LTO was requested but is not supported: ${_qemby_ipo_error}") + endif() +endif() + +function(qemby_apply_build_options target) + if(TARGET qemby_build_options) + target_link_libraries("${target}" PRIVATE qemby_build_options) + endif() + + if(QEMBY_ENABLE_IPO AND _qemby_ipo_supported) + set_target_properties("${target}" PROPERTIES + INTERPROCEDURAL_OPTIMIZATION TRUE) + endif() +endfunction() + # ========================================== # 允许通过缓存变量或环境变量提供 Qt 安装路径 # Windows 未显式指定时仍会尝试兼容现有本地默认路径 @@ -68,37 +117,67 @@ endfunction() set(_qemby_saved_skip_install_rules ${CMAKE_SKIP_INSTALL_RULES}) set(CMAKE_SKIP_INSTALL_RULES ON) -FetchContent_Declare( - QCoro - GIT_REPOSITORY https://github.com/danvratil/qcoro.git - GIT_TAG v0.10.0 -) +if(QEMBY_USE_SYSTEM_DEPS) + find_package(QCoro6 CONFIG QUIET COMPONENTS Core Network) +endif() -# 强制 QCoro 使用 Qt6 进行编译,并关闭不必要的测试与示例构建以加快编译速度 -set(QCORO_QT_MAJOR_VERSION 6 CACHE STRING "Use Qt6 for QCoro" FORCE) -set(QCORO_BUILD_EXAMPLES OFF CACHE BOOL "Disable QCoro examples" FORCE) -set(QCORO_WITH_QML OFF CACHE BOOL "Disable QCoro QML module" FORCE) -set(QCORO_WITH_QTQUICK OFF CACHE BOOL "Disable QCoro QtQuick module" FORCE) -set(BUILD_TESTING OFF CACHE BOOL "Disable QCoro tests" FORCE) +if(QCoro6_FOUND) + message(STATUS "Using system QCoro6") +else() + if(NOT QEMBY_FETCHCONTENT_FALLBACK) + message(FATAL_ERROR + "QCoro6 was not found. Install the system package or enable " + "QEMBY_FETCHCONTENT_FALLBACK.") + endif() -FetchContent_MakeAvailable(QCoro) -FetchContent_GetProperties(QCoro) -qemby_ensure_noop_install_script("${qcoro_BINARY_DIR}") + message(STATUS "System QCoro6 not found; fetching bundled QCoro") + FetchContent_Declare( + QCoro + GIT_REPOSITORY https://github.com/danvratil/qcoro.git + GIT_TAG v0.10.0 + ) + + # 强制 QCoro 使用 Qt6 进行编译,并关闭不必要的测试与示例构建以加快编译速度 + set(QCORO_QT_MAJOR_VERSION 6 CACHE STRING "Use Qt6 for QCoro" FORCE) + set(QCORO_BUILD_EXAMPLES OFF CACHE BOOL "Disable QCoro examples" FORCE) + set(QCORO_WITH_QML OFF CACHE BOOL "Disable QCoro QML module" FORCE) + set(QCORO_WITH_QTQUICK OFF CACHE BOOL "Disable QCoro QtQuick module" FORCE) + set(BUILD_TESTING OFF CACHE BOOL "Disable QCoro tests" FORCE) + + FetchContent_MakeAvailable(QCoro) + FetchContent_GetProperties(QCoro) + qemby_ensure_noop_install_script("${qcoro_BINARY_DIR}") +endif() # ========================================== # 引入 spdlog (高性能线程安全日志库, MIT License) # ========================================== -FetchContent_Declare( - spdlog - GIT_REPOSITORY https://github.com/gabime/spdlog.git - GIT_TAG v1.15.3 -) -set(SPDLOG_BUILD_EXAMPLE OFF CACHE BOOL "Disable spdlog examples" FORCE) -set(SPDLOG_BUILD_TESTS OFF CACHE BOOL "Disable spdlog tests" FORCE) -set(SPDLOG_INSTALL OFF CACHE BOOL "Disable spdlog install rules" FORCE) -FetchContent_MakeAvailable(spdlog) -FetchContent_GetProperties(spdlog) -qemby_ensure_noop_install_script("${spdlog_BINARY_DIR}") +if(QEMBY_USE_SYSTEM_DEPS) + find_package(spdlog CONFIG QUIET) +endif() + +if(spdlog_FOUND) + message(STATUS "Using system spdlog") +else() + if(NOT QEMBY_FETCHCONTENT_FALLBACK) + message(FATAL_ERROR + "spdlog was not found. Install the system package or enable " + "QEMBY_FETCHCONTENT_FALLBACK.") + endif() + + message(STATUS "System spdlog not found; fetching bundled spdlog") + FetchContent_Declare( + spdlog + GIT_REPOSITORY https://github.com/gabime/spdlog.git + GIT_TAG v1.15.3 + ) + set(SPDLOG_BUILD_EXAMPLE OFF CACHE BOOL "Disable spdlog examples" FORCE) + set(SPDLOG_BUILD_TESTS OFF CACHE BOOL "Disable spdlog tests" FORCE) + set(SPDLOG_INSTALL OFF CACHE BOOL "Disable spdlog install rules" FORCE) + FetchContent_MakeAvailable(spdlog) + FetchContent_GetProperties(spdlog) + qemby_ensure_noop_install_script("${spdlog_BINARY_DIR}") +endif() set(CMAKE_SKIP_INSTALL_RULES ${_qemby_saved_skip_install_rules}) unset(_qemby_saved_skip_install_rules) # ========================================== diff --git a/packaging/arch/.SRCINFO b/packaging/arch/.SRCINFO new file mode 100644 index 0000000..fd8794a --- /dev/null +++ b/packaging/arch/.SRCINFO @@ -0,0 +1,23 @@ +pkgbase = qemby + pkgdesc = Desktop client for Emby and Jellyfin media servers + pkgver = 0.0.5 + pkgrel = 1 + url = https://github.com/AlanHJ/qEmby + arch = x86_64 + license = MIT + makedepends = cmake + makedepends = ninja + makedepends = pkgconf + makedepends = qt6-tools + depends = gcc-libs + depends = glibc + depends = mpv + depends = qcoro + depends = qt6-base + depends = qt6-svg + depends = qt6-websockets + depends = spdlog + source = qemby-0.0.5.tar.gz::https://github.com/AlanHJ/qEmby/archive/refs/tags/v0.0.5.tar.gz + sha256sums = SKIP + +pkgname = qemby diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD new file mode 100644 index 0000000..dbed1c1 --- /dev/null +++ b/packaging/arch/PKGBUILD @@ -0,0 +1,46 @@ +# Maintainer: local + +pkgname=qemby +pkgver=0.0.5 +pkgrel=1 +pkgdesc="Desktop client for Emby and Jellyfin media servers" +arch=('x86_64') +url="https://github.com/AlanHJ/qEmby" +license=('MIT') +depends=( + 'gcc-libs' + 'glibc' + 'mpv' + 'qcoro' + 'qt6-base' + 'qt6-svg' + 'qt6-websockets' + 'spdlog' +) +makedepends=( + 'cmake' + 'ninja' + 'pkgconf' + 'qt6-tools' +) +source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz") +sha256sums=('SKIP') + +build() { + cmake -S "${srcdir}/qEmby-${pkgver}" -B "${srcdir}/build" -G Ninja \ + -DCMAKE_BUILD_TYPE=None \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DQEMBY_USE_SYSTEM_DEPS=ON \ + -DQEMBY_FETCHCONTENT_FALLBACK=OFF \ + -DFETCHCONTENT_FULLY_DISCONNECTED=ON \ + -DQEMBY_NATIVE_OPTIMIZE=OFF \ + -DQEMBY_ENABLE_IPO=OFF + cmake --build "${srcdir}/build" +} + +package() { + DESTDIR="${pkgdir}" cmake --install "${srcdir}/build" --prefix /usr + install -Dm644 "${srcdir}/qEmby-${pkgver}/LICENSE" \ + "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" +} diff --git a/packaging/arch/README.md b/packaging/arch/README.md new file mode 100644 index 0000000..d190d62 --- /dev/null +++ b/packaging/arch/README.md @@ -0,0 +1,36 @@ +# Arch package + +This PKGBUILD is intended for Arch Linux and AUR-style release packaging. It +builds from the project release tag, uses Arch system libraries, and disables +FetchContent so package builds do not download dependencies during CMake +configure. + +Before publishing a release package, replace the temporary `SKIP` checksum in +`PKGBUILD` with a real checksum, for example by running `updpkgsums` after the +tag archive is available. + +## Build + +```fish +cd packaging/arch +makepkg -f +``` + +## Install + +```fish +cd packaging/arch +sudo pacman -U qemby-*.pkg.tar.zst +``` + +## Run + +```fish +qemby +``` + +## Uninstall + +```fish +sudo pacman -R qemby +``` diff --git a/src/qEmbyApp/CMakeLists.txt b/src/qEmbyApp/CMakeLists.txt index 97ac629..ebadd14 100644 --- a/src/qEmbyApp/CMakeLists.txt +++ b/src/qEmbyApp/CMakeLists.txt @@ -83,6 +83,10 @@ target_link_libraries(qEmbyApp PRIVATE ) target_link_libraries(qEmbyApp PRIVATE Qt${QT_VERSION_MAJOR}::Core) +if(COMMAND qemby_apply_build_options) + qemby_apply_build_options(qEmbyApp) +endif() + if(APPLE) target_link_libraries(qEmbyApp PRIVATE "-framework CoreFoundation" diff --git a/src/qEmbyCore/CMakeLists.txt b/src/qEmbyCore/CMakeLists.txt index 2fe549c..7f71278 100644 --- a/src/qEmbyCore/CMakeLists.txt +++ b/src/qEmbyCore/CMakeLists.txt @@ -23,6 +23,10 @@ target_link_libraries(qEmbyCore PUBLIC Qt${QT_VERSION_MAJOR}::Gui target_compile_definitions(qEmbyCore PRIVATE QEMBYCORE_LIBRARY) +if(COMMAND qemby_apply_build_options) + qemby_apply_build_options(qEmbyCore) +endif() + include(GNUInstallDirs) set(_qemby_core_library_install_dir "${CMAKE_INSTALL_LIBDIR}")