Files
TZShot/CMakeLists.txt

490 lines
17 KiB
CMake

cmake_minimum_required(VERSION 3.16)
project(TZshot VERSION 1.0 LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
include(ExternalProject)
find_package(Qt6 REQUIRED COMPONENTS
Core
Gui
Widgets
Network
Concurrent
LinguistTools
)
qt_standard_project_setup()
# ── Third-party build options ─────────────────────────────────
option(BUILD_THIRDPART_OCR "Auto build OCR libs" ON)
option(OCR_FETCH_FROM_GITHUB "Fetch Leptonica/Tesseract from GitHub before building" ON)
# ── 翻译文件 ──────────────────────────────────────────────
set(TS_FILES
i18n/app_zh_CN.ts
i18n/app_en.ts
)
# ── 平台无关源文件 ────────────────────────────────────────
set(SOURCES
src/main.cpp
src/app/tzshot_app.cpp
src/app/tzshot_app.h
src/app/tzshot_services.cpp
src/app/tzshot_services.h
src/app/tzshot_widget_runtime.cpp
src/app/tzshot_widget_runtime.h
src/tray_icon_helper.cpp
src/tray_icon_helper.h
src/language_manager.cpp
src/language_manager.h
src/sticky_image_store.cpp
src/sticky_image_store.h
src/instance_activation.cpp
src/instance_activation.h
src/singleton.h
src/widgets/about_dialog.cpp
src/widgets/about_dialog.h
src/widgets/sticky_pin_widget.cpp
src/widgets/sticky_pin_widget.h
src/widgets/sticky_canvas_widget.cpp
src/widgets/sticky_canvas_widget.h
src/widgets/capture_overlay_widget.cpp
src/widgets/capture_overlay_widget.h
src/widgets/gif_record_overlay_widget.cpp
src/widgets/gif_record_overlay_widget.h
src/widgets/long_capture_controller.cpp
src/widgets/long_capture_controller.h
src/widgets/magnifier_widget.cpp
src/widgets/magnifier_widget.h
src/widgets/selection_mask_controller.cpp
src/widgets/selection_mask_controller.h
src/widgets/ocr_result_widget.cpp
src/widgets/ocr_result_widget.h
src/widgets/vision_result_widget.cpp
src/widgets/vision_result_widget.h
src/widgets/settings_dialog.cpp
src/widgets/settings_dialog.h
src/widgets/widget_window_bridge.cpp
src/widgets/widget_window_bridge.h
# Model
src/model/desktop_snapshot.cpp
src/model/desktop_snapshot.h
src/model/app_settings.cpp
src/model/app_settings.h
# ViewModel
src/viewmodel/screenshot_view_model.cpp
src/viewmodel/screenshot_view_model.h
src/viewmodel/sticky_view_model.cpp
src/viewmodel/sticky_view_model.h
src/viewmodel/ai_view_model.cpp
src/viewmodel/ai_view_model.h
src/viewmodel/storage_view_model.cpp
src/viewmodel/storage_view_model.h
src/viewmodel/gif_record_view_model.cpp
src/viewmodel/gif_record_view_model.h
src/viewmodel/scroll_capture_view_model.cpp
src/viewmodel/scroll_capture_view_model.h
src/viewmodel/ocr_view_model.cpp
src/viewmodel/ocr_view_model.h
src/viewmodel/vision_view_model.cpp
src/viewmodel/vision_view_model.h
# GIF Encoder
src/gif_encoder/gif.h
src/gif_encoder/gif_encoder.cpp
src/gif_encoder/gif_encoder.h
src/gif_encoder/gif_frame_grabber.cpp
src/gif_encoder/gif_frame_grabber.h
src/scroll/scroll_stitcher.cpp
src/scroll/scroll_stitcher.h
# OCR
src/ocr/ocr_engine.cpp
src/ocr/ocr_engine.h
src/paint_board/shape/shape.cpp
src/paint_board/shape/shape.h
src/paint_board/shape/shape_type.h
src/paint_board/shape/shape_factory.cpp
src/paint_board/shape/shape_factory.h
src/paint_board/shape/two_point_shape.cpp
src/paint_board/shape/two_point_shape.h
src/paint_board/shape/arrow_shape.cpp
src/paint_board/shape/arrow_shape.h
src/paint_board/shape/blur_shape.cpp
src/paint_board/shape/blur_shape.h
src/paint_board/shape/ellipse_shape.cpp
src/paint_board/shape/ellipse_shape.h
src/paint_board/shape/mosaic_shape.cpp
src/paint_board/shape/mosaic_shape.h
src/paint_board/shape/pen_shape.cpp
src/paint_board/shape/pen_shape.h
src/paint_board/shape/rect_shape.cpp
src/paint_board/shape/rect_shape.h
src/paint_board/shape/text_shape.cpp
src/paint_board/shape/text_shape.h
src/paint_board/shape/number_shape.cpp
src/paint_board/shape/number_shape.h
# AI
src/ai_call/ai_call_base.cpp
src/ai_call/ai_call_base.h
src/ai_call/ai_type.h
src/ai_call/qwen_ai_call.cpp
src/ai_call/qwen_ai_call.h
src/ai_call/seedream_ai_call.cpp
src/ai_call/seedream_ai_call.h
src/ai_call/doubao_vision_call.cpp
src/ai_call/doubao_vision_call.h
# Shortcut — 跨平台公共部分
src/shortcut_key/globalshortcut.cpp
src/shortcut_key/globalshortcut.h
# Resources
qml.qrc
)
# ── 平台专属源文件 ────────────────────────────────────────
if(UNIX)
list(APPEND SOURCES
src/shortcut_key/linux_grab.c
src/shortcut_key/linux_grab.h
)
endif()
if(WIN32)
list(APPEND SOURCES
resource/windows/tzshot.rc
src/shortcut_key/win_grab.c
src/shortcut_key/win_grab.h
)
endif()
qt_add_executable(TZshot
${SOURCES}
)
# ── include 路径 ──────────────────────────────────────────
target_include_directories(TZshot PRIVATE
src
src/ai_call
src/gif_encoder
src/ocr
src/paint_board
src/paint_board/shape
src/model
src/viewmodel
src/scroll
src/shortcut_key
)
# ── 编译定义 ──────────────────────────────────────────────
target_compile_definitions(TZshot PRIVATE
QT_DEPRECATED_WARNINGS
)
target_compile_definitions(TZshot PRIVATE
$<$<CONFIG:Debug>:STICKY_MEM_DEBUG>
)
# ── Qt 模块链接 ───────────────────────────────────────────
target_link_libraries(TZshot PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
Qt6::Network
Qt6::Concurrent
)
# ── 平台系统库 ────────────────────────────────────────────
if(UNIX)
target_link_libraries(TZshot PRIVATE
X11
xcb
pthread
)
set(OCR_ENABLED FALSE)
set(OCR_PREFIX "$ENV{OCR_PREFIX}")
if(OCR_PREFIX STREQUAL "")
set(OCR_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/thirdpart/ocr")
endif()
set(OCR_LIB_DIR "")
if(EXISTS "${OCR_PREFIX}/lib/libtesseract.so" OR EXISTS "${OCR_PREFIX}/lib/libtesseract.a")
set(OCR_LIB_DIR "${OCR_PREFIX}/lib")
elseif(EXISTS "${OCR_PREFIX}/lib64/libtesseract.so" OR EXISTS "${OCR_PREFIX}/lib64/libtesseract.a")
set(OCR_LIB_DIR "${OCR_PREFIX}/lib64")
endif()
if(NOT OCR_LIB_DIR STREQUAL "")
target_include_directories(TZshot PRIVATE
"${OCR_PREFIX}/include"
"${OCR_PREFIX}/include/leptonica"
)
target_link_directories(TZshot PRIVATE "${OCR_LIB_DIR}")
target_link_libraries(TZshot PRIVATE tesseract leptonica)
target_compile_definitions(TZshot PRIVATE
ENABLE_OCR
OCR_TESSDATA_DIR=\"${OCR_PREFIX}/share/tessdata\"
)
set(OCR_ENABLED TRUE)
message(STATUS "OCR enabled via thirdpart: ${OCR_PREFIX}")
endif()
if(NOT OCR_ENABLED)
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
pkg_check_modules(TESSERACT QUIET IMPORTED_TARGET tesseract)
pkg_check_modules(LEPT QUIET IMPORTED_TARGET lept)
if(TESSERACT_FOUND AND LEPT_FOUND)
target_link_libraries(TZshot PRIVATE PkgConfig::TESSERACT PkgConfig::LEPT)
target_compile_definitions(TZshot PRIVATE ENABLE_OCR)
message(STATUS "OCR enabled via pkg-config: tesseract + lept")
else()
message(STATUS "OCR disabled: thirdpart OCR not found and pkg-config tesseract/lept unavailable")
endif()
else()
message(STATUS "OCR disabled: PkgConfig not found")
endif()
endif()
endif()
if(WIN32)
target_link_libraries(TZshot PRIVATE
user32 # RegisterHotKey / UnregisterHotKey / EnumWindows
gdi32
)
set(OCR_ENABLED FALSE)
if(BUILD_THIRDPART_OCR AND OCR_FETCH_FROM_GITHUB)
set(OCR_THIRDPART_DIR "${CMAKE_CURRENT_SOURCE_DIR}/thirdpart")
set(OCR_INSTALL_DIR "${OCR_THIRDPART_DIR}/ocr-install")
set(OCR_TESSDATA_DIR "${OCR_INSTALL_DIR}/share/tessdata")
# ExternalProject build trees must be generator-specific.
# Otherwise switching between Ninja/VS reuses incompatible CMake caches.
set(OCR_EP_KEY "${CMAKE_GENERATOR}-${CMAKE_GENERATOR_PLATFORM}")
string(REGEX REPLACE "[^A-Za-z0-9_.-]" "_" OCR_EP_KEY "${OCR_EP_KEY}")
set(OCR_EP_ROOT_DIR "${OCR_THIRDPART_DIR}/_ep_${OCR_EP_KEY}")
set(OCR_ZLIB_VERSION "v1.3.1")
set(OCR_LIBPNG_VERSION "v1.6.43")
set(OCR_LIBJPEG_TURBO_VERSION "3.0.3")
set(OCR_LIBTIFF_VERSION "v4.7.0")
set(OCR_LEPTONICA_VERSION "1.87.0")
set(OCR_TESSERACT_VERSION "5.5.2")
# Imported target include dirs are validated at generate time.
# Create expected install dirs up front; actual contents are produced by ExternalProject.
file(MAKE_DIRECTORY
"${OCR_INSTALL_DIR}/include"
"${OCR_INSTALL_DIR}/lib"
"${OCR_TESSDATA_DIR}"
)
# Make ExternalProject follow current build type (Debug/Release) on
# single-config generators (e.g. Ninja in Qt Creator kits).
set(OCR_EP_BUILD_TYPE_ARG "")
if(NOT CMAKE_CONFIGURATION_TYPES)
if(CMAKE_BUILD_TYPE STREQUAL "")
set(OCR_EP_BUILD_TYPE "Debug")
else()
set(OCR_EP_BUILD_TYPE "${CMAKE_BUILD_TYPE}")
endif()
set(OCR_EP_BUILD_TYPE_ARG "-DCMAKE_BUILD_TYPE=${OCR_EP_BUILD_TYPE}")
endif()
ExternalProject_Add(zlib_ep
PREFIX "${OCR_EP_ROOT_DIR}/zlib"
GIT_REPOSITORY "https://github.com/madler/zlib.git"
GIT_TAG "${OCR_ZLIB_VERSION}"
UPDATE_DISCONNECTED 1
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
-DBUILD_SHARED_LIBS=ON
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
${OCR_EP_BUILD_TYPE_ARG}
)
ExternalProject_Add(libpng_ep
PREFIX "${OCR_EP_ROOT_DIR}/libpng"
GIT_REPOSITORY "https://github.com/pnggroup/libpng.git"
GIT_TAG "${OCR_LIBPNG_VERSION}"
UPDATE_DISCONNECTED 1
DEPENDS zlib_ep
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
-DCMAKE_PREFIX_PATH=${OCR_INSTALL_DIR}
-DZLIB_ROOT=${OCR_INSTALL_DIR}
-DPNG_SHARED=ON
-DPNG_TESTS=OFF
-DPNG_EXECUTABLES=OFF
-DPNG_FRAMEWORK=OFF
${OCR_EP_BUILD_TYPE_ARG}
)
ExternalProject_Add(libjpeg_ep
PREFIX "${OCR_EP_ROOT_DIR}/libjpeg"
GIT_REPOSITORY "https://github.com/libjpeg-turbo/libjpeg-turbo.git"
GIT_TAG "${OCR_LIBJPEG_TURBO_VERSION}"
UPDATE_DISCONNECTED 1
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
-DBUILD_SHARED_LIBS=ON
-DENABLE_SHARED=ON
-DENABLE_STATIC=OFF
-DWITH_TURBOJPEG=ON
-DWITH_JPEG8=ON
${OCR_EP_BUILD_TYPE_ARG}
)
ExternalProject_Add(libtiff_ep
PREFIX "${OCR_EP_ROOT_DIR}/libtiff"
GIT_REPOSITORY "https://github.com/libsdl-org/libtiff.git"
GIT_TAG "${OCR_LIBTIFF_VERSION}"
UPDATE_DISCONNECTED 1
DEPENDS zlib_ep
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
-DCMAKE_PREFIX_PATH=${OCR_INSTALL_DIR}
-DBUILD_SHARED_LIBS=ON
-Dzlib=ON
-Djpeg=OFF
-Dwebp=OFF
-Dzstd=OFF
-Dlzma=OFF
-Djbig=OFF
-Dlerc=OFF
-Dtiff-tools=OFF
-Dtiff-tests=OFF
-Dtiff-contrib=OFF
-Dtiff-docs=OFF
${OCR_EP_BUILD_TYPE_ARG}
)
ExternalProject_Add(leptonica_ep
PREFIX "${OCR_EP_ROOT_DIR}/leptonica"
GIT_REPOSITORY "https://github.com/DanBloomberg/leptonica.git"
GIT_TAG "${OCR_LEPTONICA_VERSION}"
UPDATE_DISCONNECTED 1
DEPENDS libpng_ep libjpeg_ep libtiff_ep
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
-DCMAKE_PREFIX_PATH=${OCR_INSTALL_DIR}
-DBUILD_SHARED_LIBS=ON
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
-DSW_BUILD=OFF
-DSTRICT_CONF=ON
-DENABLE_ZLIB=ON
-DENABLE_PNG=ON
-DENABLE_GIF=OFF
-DENABLE_JPEG=ON
-DENABLE_TIFF=ON
-DENABLE_WEBP=OFF
-DENABLE_OPENJPEG=OFF
${OCR_EP_BUILD_TYPE_ARG}
)
ExternalProject_Add(tesseract_ep
PREFIX "${OCR_EP_ROOT_DIR}/tesseract"
GIT_REPOSITORY "https://github.com/tesseract-ocr/tesseract.git"
GIT_TAG "${OCR_TESSERACT_VERSION}"
UPDATE_DISCONNECTED 1
DEPENDS leptonica_ep
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
-DCMAKE_PREFIX_PATH=${OCR_INSTALL_DIR}
-DBUILD_SHARED_LIBS=ON
-DSW_BUILD=OFF
-DBUILD_TRAINING_TOOLS=OFF
-DBUILD_TESTS=OFF
-DDISABLE_ARCHIVE=ON
-DDISABLE_CURL=ON
-DOPENMP_BUILD=OFF
${OCR_EP_BUILD_TYPE_ARG}
)
add_dependencies(TZshot tesseract_ep)
target_include_directories(TZshot PRIVATE "${OCR_INSTALL_DIR}/include")
target_link_directories(TZshot PRIVATE "${OCR_INSTALL_DIR}/lib")
set(OCR_LEPTONICA_LINK_NAME "leptonica-${OCR_LEPTONICA_VERSION}$<$<CONFIG:Debug>:d>")
if(MINGW)
# Our MinGW Leptonica ExternalProject installs libleptonica.dll.a
# without a version/debug suffix, so link against that stable name.
set(OCR_LEPTONICA_LINK_NAME "leptonica")
endif()
target_link_libraries(TZshot PRIVATE
"tesseract55$<$<CONFIG:Debug>:d>"
"${OCR_LEPTONICA_LINK_NAME}"
Ws2_32
)
target_compile_definitions(TZshot PRIVATE
ENABLE_OCR
OCR_TESSDATA_DIR=\"${OCR_TESSDATA_DIR}\"
)
# Ensure runtime OCR DLLs are available beside TZshot.exe.
add_custom_command(TARGET TZshot POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${OCR_INSTALL_DIR}/bin"
"$<TARGET_FILE_DIR:TZshot>"
VERBATIM
)
set(OCR_ENABLED TRUE)
message(STATUS "OCR enabled via GitHub fetch/build (Leptonica ${OCR_LEPTONICA_VERSION}, Tesseract ${OCR_TESSERACT_VERSION})")
endif()
if(NOT OCR_ENABLED)
message(STATUS "OCR disabled on Windows: BUILD_THIRDPART_OCR/OCR_FETCH_FROM_GITHUB is OFF")
endif()
# Windows 子系统:Release 用 /SUBSYSTEM:WINDOWS 隐藏控制台窗口
set_target_properties(TZshot PROPERTIES
WIN32_EXECUTABLE $<IF:$<CONFIG:Debug>,FALSE,TRUE>
)
endif()
# ── 翻译 ──────────────────────────────────────────────────
qt_add_translations(TZshot
TS_FILES ${TS_FILES}
QM_FILES_OUTPUT_VARIABLE QM_FILES
)
# Package generated .qm files into the app resource at :/i18n.
foreach(qm_file IN LISTS QM_FILES)
get_filename_component(qm_name "${qm_file}" NAME)
set_source_files_properties("${qm_file}" PROPERTIES
QT_RESOURCE_ALIAS "${qm_name}"
)
endforeach()
qt_add_resources(TZshot "i18n_translations"
PREFIX "/i18n"
FILES ${QM_FILES}
)
# ── 安装 ──────────────────────────────────────────────────
if(UNIX AND NOT ANDROID)
install(TARGETS TZshot
DESTINATION /opt/TZshot/bin
)
endif()
if(WIN32)
install(TARGETS TZshot
DESTINATION bin
)
endif()