315 lines
10 KiB
CMake
315 lines
10 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
|
|
project(media-image-service
|
|
VERSION 0.1.0
|
|
DESCRIPTION "Polymech image resize service (CLI, REST, IPC) — libvips"
|
|
LANGUAGES CXX
|
|
)
|
|
|
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/dist")
|
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}/dist")
|
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}/dist")
|
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_SOURCE_DIR}/dist")
|
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_SOURCE_DIR}/dist")
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
# MSVC: UTF-8 source/execution charset so wide string literals (L"...") match UTF-8 in .cpp files.
|
|
if(MSVC)
|
|
add_compile_options(/utf-8)
|
|
endif()
|
|
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
|
|
# Windows: official libvips dev tree (see scripts/fetch-vips-windows.ps1) — vips-dev-* under third_party/
|
|
if(WIN32)
|
|
file(GLOB _MEDIA_VIPS_SDK "${CMAKE_CURRENT_SOURCE_DIR}/third_party/vips-dev-*")
|
|
if(_MEDIA_VIPS_SDK)
|
|
list(APPEND CMAKE_PREFIX_PATH ${_MEDIA_VIPS_SDK})
|
|
endif()
|
|
endif()
|
|
|
|
include(FetchContent)
|
|
|
|
set(JSON_BuildTests OFF CACHE BOOL "" FORCE)
|
|
|
|
FetchContent_Declare(
|
|
cli11
|
|
GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git
|
|
GIT_TAG v2.4.2
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
|
|
FetchContent_Declare(
|
|
asio
|
|
GIT_REPOSITORY https://github.com/chriskohlhoff/asio.git
|
|
GIT_TAG asio-1-28-0
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
|
|
FetchContent_Declare(
|
|
nlohmann_json
|
|
GIT_REPOSITORY https://github.com/nlohmann/json.git
|
|
GIT_TAG v3.11.3
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
|
|
FetchContent_Declare(
|
|
cpp_httplib
|
|
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
|
|
GIT_TAG v0.16.3
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
|
|
FetchContent_MakeAvailable(cli11 asio nlohmann_json cpp_httplib)
|
|
|
|
# libcurl — HTTP(S) URL inputs (minimal static build; SChannel on Windows, OpenSSL on Linux).
|
|
set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "" FORCE)
|
|
FetchContent_Declare(
|
|
CURL
|
|
URL https://github.com/curl/curl/releases/download/curl-8_12_1/curl-8.12.1.tar.xz
|
|
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
|
)
|
|
set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
|
|
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
|
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
|
if(WIN32)
|
|
set(CURL_USE_OPENSSL OFF CACHE BOOL "" FORCE)
|
|
set(CURL_USE_SCHANNEL ON CACHE BOOL "" FORCE)
|
|
else()
|
|
set(CURL_USE_SCHANNEL OFF CACHE BOOL "" FORCE)
|
|
set(CURL_USE_OPENSSL ON CACHE BOOL "" FORCE)
|
|
endif()
|
|
set(CURL_ZLIB OFF CACHE BOOL "" FORCE)
|
|
set(CURL_BROTLI OFF CACHE BOOL "" FORCE)
|
|
set(CURL_ZSTD OFF CACHE BOOL "" FORCE)
|
|
set(USE_NGHTTP2 OFF CACHE BOOL "" FORCE)
|
|
set(CURL_USE_LIBSSH2 OFF CACHE BOOL "" FORCE)
|
|
set(CURL_USE_LIBPSL OFF CACHE BOOL "" FORCE)
|
|
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
|
set(CURL_DISABLE_LDAPS ON CACHE BOOL "" FORCE)
|
|
FetchContent_MakeAvailable(CURL)
|
|
|
|
# PicoSHA2 — header-only SHA256 for cache keys.
|
|
FetchContent_Declare(
|
|
picosha2
|
|
GIT_REPOSITORY https://github.com/okdshin/PicoSHA2.git
|
|
GIT_TAG master
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
FetchContent_GetProperties(picosha2)
|
|
if(NOT picosha2_POPULATED)
|
|
FetchContent_Populate(picosha2)
|
|
endif()
|
|
|
|
# p-ranav/glob — same as packages/kbot/cpp (glob / rglob for **).
|
|
FetchContent_Declare(
|
|
pranav_glob
|
|
GIT_REPOSITORY https://github.com/p-ranav/glob.git
|
|
GIT_TAG master
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
FetchContent_GetProperties(pranav_glob)
|
|
if(NOT pranav_glob_POPULATED)
|
|
FetchContent_Populate(pranav_glob)
|
|
endif()
|
|
add_library(pranav_glob STATIC ${pranav_glob_SOURCE_DIR}/source/glob.cpp)
|
|
target_include_directories(pranav_glob PUBLIC ${pranav_glob_SOURCE_DIR}/include)
|
|
target_compile_features(pranav_glob PUBLIC cxx_std_17)
|
|
if(MSVC)
|
|
target_compile_options(pranav_glob PRIVATE /permissive-)
|
|
endif()
|
|
|
|
# laserpants/dotenv-cpp — load .env (same pattern as packages/kbot/cpp).
|
|
FetchContent_Declare(
|
|
laserpants_dotenv
|
|
GIT_REPOSITORY https://github.com/laserpants/dotenv-cpp.git
|
|
GIT_TAG master
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
FetchContent_GetProperties(laserpants_dotenv)
|
|
if(NOT laserpants_dotenv_POPULATED)
|
|
FetchContent_Populate(laserpants_dotenv)
|
|
endif()
|
|
add_library(laserpants_dotenv INTERFACE)
|
|
target_include_directories(laserpants_dotenv INTERFACE ${laserpants_dotenv_SOURCE_DIR}/include)
|
|
add_library(laserpants::dotenv ALIAS laserpants_dotenv)
|
|
|
|
# libsodium — encrypted UI settings (Windows: secretbox + DPAPI key file; see src/win/settings_store.cpp)
|
|
if(WIN32)
|
|
set(SODIUM_DISABLE_TESTS ON CACHE BOOL "" FORCE)
|
|
FetchContent_Declare(
|
|
libsodium_cmake
|
|
GIT_REPOSITORY https://github.com/robinlinden/libsodium-cmake.git
|
|
GIT_TAG cfebfd3da486d5a86c644c8b47067e5411c7599c
|
|
)
|
|
FetchContent_MakeAvailable(libsodium_cmake)
|
|
endif()
|
|
|
|
find_package(Vips REQUIRED)
|
|
|
|
add_executable(pm-image
|
|
src/main.cpp
|
|
src/core/cache.cpp
|
|
src/core/glob_paths.cpp
|
|
src/core/output_path.cpp
|
|
src/core/resize.cpp
|
|
src/core/transform.cpp
|
|
src/core/url_fetch.cpp
|
|
src/http/serve.cpp
|
|
src/ipc/ipc_serve.cpp
|
|
)
|
|
if(WIN32)
|
|
target_sources(pm-image PRIVATE
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/win/register_explorer.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/win/resize_ui.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/win/resize_progress_ui.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/win/ui_singleton.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/win/settings_store.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/win/media-img-win.manifest"
|
|
)
|
|
|
|
# ── ui_next (Win32++ ribbon + dock UI) ──────────────────────────────
|
|
set(_UI_NEXT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/win/ui_next")
|
|
|
|
# Try to compile Ribbon.xml → Ribbon.bml + RibbonUI.h + RibbonUI.rc via uicc.exe.
|
|
find_program(UICC_EXE uicc
|
|
HINTS "C:/Program Files (x86)/Windows Kits/10/bin"
|
|
"$ENV{WindowsSdkDir}/bin"
|
|
PATH_SUFFIXES "${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64"
|
|
"${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x86"
|
|
"10.0.22621.0/x64" "10.0.22621.0/x86"
|
|
"10.0.19041.0/x64" "10.0.19041.0/x86"
|
|
)
|
|
|
|
if(UICC_EXE)
|
|
message(STATUS "uicc found: ${UICC_EXE} — ribbon resources will be compiled")
|
|
add_custom_command(
|
|
OUTPUT "${_UI_NEXT_DIR}/Ribbon.bml"
|
|
"${_UI_NEXT_DIR}/RibbonUI.h"
|
|
"${_UI_NEXT_DIR}/RibbonUI.rc"
|
|
COMMAND "${UICC_EXE}"
|
|
"${_UI_NEXT_DIR}/Ribbon.xml"
|
|
"${_UI_NEXT_DIR}/Ribbon.bml"
|
|
"/header:${_UI_NEXT_DIR}/RibbonUI.h"
|
|
"/res:${_UI_NEXT_DIR}/RibbonUI.rc"
|
|
"/name:APPLICATION"
|
|
DEPENDS "${_UI_NEXT_DIR}/Ribbon.xml"
|
|
COMMENT "Compiling Ribbon.xml → Ribbon.bml + RibbonUI.h/rc (uicc)"
|
|
VERBATIM
|
|
)
|
|
add_custom_target(pm_image_ribbon DEPENDS
|
|
"${_UI_NEXT_DIR}/Ribbon.bml"
|
|
"${_UI_NEXT_DIR}/RibbonUI.h"
|
|
"${_UI_NEXT_DIR}/RibbonUI.rc"
|
|
)
|
|
else()
|
|
message(STATUS "uicc NOT found — ribbon disabled; classic menu fallback will be used")
|
|
add_custom_target(pm_image_ribbon)
|
|
endif()
|
|
|
|
target_sources(pm-image PRIVATE
|
|
"${_UI_NEXT_DIR}/App.cpp"
|
|
"${_UI_NEXT_DIR}/DropView.cpp"
|
|
"${_UI_NEXT_DIR}/FileQueue.cpp"
|
|
"${_UI_NEXT_DIR}/LogPanel.cpp"
|
|
"${_UI_NEXT_DIR}/FileInfoPanel.cpp"
|
|
"${_UI_NEXT_DIR}/SettingsPanel.cpp"
|
|
"${_UI_NEXT_DIR}/ProviderDlg.cpp"
|
|
"${_UI_NEXT_DIR}/Mainfrm.cpp"
|
|
"${_UI_NEXT_DIR}/launch_ui_next.cpp"
|
|
"${_UI_NEXT_DIR}/Resource.rc"
|
|
)
|
|
add_dependencies(pm-image pm_image_ribbon)
|
|
target_include_directories(pm-image PRIVATE "${_UI_NEXT_DIR}")
|
|
endif()
|
|
|
|
# Win32++ — header-only (vendor tree under packages/Win32xx). See samples e.g.
|
|
# packages/Win32xx/samples/MovieShow/ProjectFiles/*_2026.vcxproj: AdditionalIncludeDirectories=..\..\..\include
|
|
if(WIN32)
|
|
set(MEDIA_WIN32XX_DIR "${CMAKE_CURRENT_SOURCE_DIR}/packages/Win32xx" CACHE PATH "Win32++ root (expects include/wxx_*.h)")
|
|
if(EXISTS "${MEDIA_WIN32XX_DIR}/include/wxx_wincore.h")
|
|
add_library(win32xx INTERFACE)
|
|
target_include_directories(win32xx INTERFACE "${MEDIA_WIN32XX_DIR}/include")
|
|
target_compile_definitions(win32xx INTERFACE UNICODE _UNICODE)
|
|
# Same optional deps as MovieShow (beyond what pragma in our .cpp already pulls).
|
|
target_link_libraries(win32xx INTERFACE shlwapi Propsys gdiplus Crypt32 uxtheme)
|
|
add_library(media::win32xx ALIAS win32xx)
|
|
target_link_libraries(pm-image PRIVATE win32xx)
|
|
endif()
|
|
endif()
|
|
|
|
target_include_directories(pm-image PRIVATE
|
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
|
${asio_SOURCE_DIR}/asio/include
|
|
${picosha2_SOURCE_DIR}
|
|
)
|
|
|
|
target_compile_definitions(pm-image PRIVATE
|
|
ASIO_STANDALONE
|
|
ASIO_NO_DEPRECATED
|
|
CPPHTTPLIB_NO_EXCEPTIONS=0
|
|
)
|
|
|
|
if(WIN32)
|
|
target_compile_definitions(pm-image PRIVATE
|
|
_WIN32_WINNT=0x0A00
|
|
NOMINMAX
|
|
)
|
|
endif()
|
|
|
|
target_link_libraries(pm-image PRIVATE
|
|
CLI11::CLI11
|
|
nlohmann_json::nlohmann_json
|
|
httplib::httplib
|
|
laserpants::dotenv
|
|
pranav_glob
|
|
CURL::libcurl
|
|
Vips::vips
|
|
)
|
|
if(WIN32)
|
|
target_link_libraries(pm-image PRIVATE sodium)
|
|
endif()
|
|
|
|
# GObject (g_object_ref / g_object_unref) — not re-exported through libvips import lib on MSVC.
|
|
if(WIN32)
|
|
file(GLOB _MEDIA_VIPS_SDK_LIST "${CMAKE_CURRENT_SOURCE_DIR}/third_party/vips-dev-*")
|
|
if(_MEDIA_VIPS_SDK_LIST)
|
|
list(GET _MEDIA_VIPS_SDK_LIST 0 _MEDIA_VIPS_SDK)
|
|
if(EXISTS "${_MEDIA_VIPS_SDK}/lib/libgobject-2.0.lib")
|
|
target_link_libraries(pm-image PRIVATE
|
|
"${_MEDIA_VIPS_SDK}/lib/libgobject-2.0.lib"
|
|
"${_MEDIA_VIPS_SDK}/lib/libglib-2.0.lib"
|
|
)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
if(UNIX AND NOT APPLE)
|
|
target_link_libraries(pm-image PRIVATE pthread)
|
|
endif()
|
|
|
|
target_compile_definitions(pm-image PRIVATE
|
|
"MEDIA_IMG_VERSION=\"${PROJECT_VERSION}\""
|
|
)
|
|
|
|
# Runtime: libvips and deps are DLLs next to pm-image.exe (Windows dev bundle bin/).
|
|
if(WIN32)
|
|
file(GLOB _MEDIA_VIPS_SDK_LIST "${CMAKE_CURRENT_SOURCE_DIR}/third_party/vips-dev-*")
|
|
if(_MEDIA_VIPS_SDK_LIST)
|
|
list(GET _MEDIA_VIPS_SDK_LIST 0 _MEDIA_VIPS_SDK)
|
|
if(EXISTS "${_MEDIA_VIPS_SDK}/bin")
|
|
add_custom_command(
|
|
TARGET pm-image
|
|
POST_BUILD
|
|
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
|
"${_MEDIA_VIPS_SDK}/bin"
|
|
"${CMAKE_SOURCE_DIR}/dist"
|
|
COMMENT "Copy libvips DLLs to dist/"
|
|
)
|
|
endif()
|
|
endif()
|
|
endif()
|