cmake_minimum_required(VERSION 3.24) project(DocView VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) include(CTest) if(MSVC) add_compile_options(/utf-8 /permissive- /Zc:__cplusplus) endif() if(WIN32 AND (NOT MSVC OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8)) message(FATAL_ERROR "DocView on Windows requires a 64-bit MSVC-compatible toolchain and matching Qt WebEngine.") endif() find_package(Qt6 6.11.2 EXACT REQUIRED COMPONENTS Core Gui Network Qml Quick QuickControls2 WebEngineQuick Xml LinguistTools) if(WIN32) find_package(libzip 1.11 CONFIG REQUIRED) find_package(tomlplusplus 3.4 CONFIG REQUIRED) set(DOCVIEW_ZIP_TARGET libzip::zip) set(DOCVIEW_TOML_TARGET tomlplusplus::tomlplusplus) else() find_package(PkgConfig REQUIRED) pkg_check_modules(LIBZIP REQUIRED IMPORTED_TARGET libzip>=1.11) pkg_check_modules(TOML REQUIRED IMPORTED_TARGET tomlplusplus>=3.4) pkg_check_modules(SECCOMP REQUIRED IMPORTED_TARGET libseccomp>=2.5) pkg_check_modules(FONTCONFIG REQUIRED IMPORTED_TARGET fontconfig>=2.13) set(DOCVIEW_ZIP_TARGET PkgConfig::LIBZIP) set(DOCVIEW_TOML_TARGET PkgConfig::TOML) endif() include(cmake/Pdfium.cmake) find_package(qpdf 12.4.1 EXACT CONFIG REQUIRED) add_library(docview_common src/common/ipc.cpp src/common/contracts.cpp src/common/sandbox.cpp src/common/worker_process.cpp src/common/session_storage.cpp src/common/single_instance.cpp src/common/windows_sandbox.cpp src/common/windows_pipe.cpp src/common/windows_runtime_staging.cpp src/common/worker_runtime.cpp src/common/font_contract.cpp src/common/worker_font_client.cpp src/web/resource_policy.cpp src/web/renderer_watchdog.cpp) target_include_directories(docview_common PUBLIC src) target_link_libraries(docview_common PUBLIC Qt6::Core Qt6::Network) if(WIN32) target_compile_definitions(docview_common PUBLIC _WIN32_WINNT=0x0A00 NOMINMAX WIN32_LEAN_AND_MEAN) target_link_libraries(docview_common PRIVATE userenv advapi32 kernel32 shell32 ole32 psapi) else() target_link_libraries(docview_common PRIVATE PkgConfig::SECCOMP) endif() add_library(docview_core src/core/config.cpp src/core/input.cpp src/core/state.cpp src/core/types.cpp src/common/memory_pressure.cpp) target_include_directories(docview_core PUBLIC src) target_link_libraries(docview_core PUBLIC Qt6::Core ${DOCVIEW_TOML_TARGET}) if(WIN32) target_compile_definitions(docview_core PRIVATE _WIN32_WINNT=0x0A00 NOMINMAX WIN32_LEAN_AND_MEAN) target_link_libraries(docview_core PRIVATE shell32 ole32) endif() add_library(docview_pdf src/pdf/pdf_document.cpp src/pdf/link_border_reader.cpp src/pdf/pdf_metadata_context.cpp src/pdf/structure_reader.cpp) target_sources(docview_pdf PRIVATE src/pdf/system_font_adapter.cpp) target_include_directories(docview_pdf PUBLIC src) target_link_libraries(docview_pdf PUBLIC Qt6::Core PDFium::PDFium docview_common) target_link_libraries(docview_pdf PRIVATE qpdf::libqpdf) add_library(docview_font_broker src/broker/font_broker.cpp src/broker/font_backend.cpp) target_include_directories(docview_font_broker PUBLIC src) target_link_libraries(docview_font_broker PUBLIC docview_common Qt6::Core) if(WIN32) target_sources(docview_font_broker PRIVATE src/broker/font_backend_win.cpp) target_link_libraries(docview_font_broker PRIVATE gdi32) else() target_sources(docview_font_broker PRIVATE src/broker/font_backend_linux.cpp) target_link_libraries(docview_font_broker PRIVATE PkgConfig::FONTCONFIG) endif() add_executable(docview-pdf-worker src/pdf/main.cpp) target_link_libraries(docview-pdf-worker PRIVATE docview_pdf docview_common) add_library(docview_archive src/archive/archive.cpp) target_include_directories(docview_archive PUBLIC src) target_link_libraries(docview_archive PUBLIC Qt6::Core Qt6::Xml ${DOCVIEW_ZIP_TARGET}) add_executable(docview-archive-worker src/archive/main.cpp) target_link_libraries(docview-archive-worker PRIVATE docview_archive docview_common) set(DOCVIEW_SHELL_SOURCES src/app/controller.cpp src/app/pdf_canvas.cpp src/web/web_profile.cpp resources.qrc) qt_add_executable(docview src/app/main.cpp src/app/benchmark.cpp src/app/translations.cpp ${DOCVIEW_SHELL_SOURCES}) target_link_libraries(docview PRIVATE docview_core docview_common docview_font_broker Qt6::Gui Qt6::Quick Qt6::Qml Qt6::QuickControls2 Qt6::WebEngineQuick) add_dependencies(docview docview-pdf-worker docview-archive-worker) qt_add_translations(TARGETS docview SOURCE_TARGETS docview docview_core docview_common docview_pdf docview_archive docview_font_broker docview-pdf-worker docview-archive-worker SOURCES qml/Main.qml qml/WebPane.qml TS_FILES resources/i18n/docview_ja.ts LUPDATE_OPTIONS -locations relative -no-obsolete LUPDATE_TARGET docview_lupdate LRELEASE_TARGET docview_lrelease RESOURCE_PREFIX "/i18n") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") # Register candidate revalidation before any install rule copies a binary. include(cmake/PdfiumSupplementalNotices.cmake) endif() if(UNIX) set_target_properties(docview-pdf-worker PROPERTIES INSTALL_RPATH "$ORIGIN/../lib") install(FILES "${DOCVIEW_PDFIUM_LIBRARY}" DESTINATION lib) endif() install(TARGETS docview docview-pdf-worker docview-archive-worker RUNTIME DESTINATION bin) install(FILES resources/config.example.toml DESTINATION share/doc/docview) install(DIRECTORY resources/licenses/qpdf DESTINATION share/doc/docview/licenses) install(FILES "${DOCVIEW_PDFIUM_ROOT}/LICENSE" DESTINATION share/doc/docview/pdfium) install(DIRECTORY "${DOCVIEW_PDFIUM_ROOT}/licenses/" DESTINATION share/doc/docview/pdfium/licenses) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") install(FILES docs/LINUX-DEVELOPMENT-PACKAGE.md DESTINATION share/doc/docview) install(FILES resources/licenses/README.md DESTINATION share/doc/docview RENAME THIRD-PARTY-SCOPE.md) include(cmake/LinuxDevelopmentPackage.cmake) endif() if(WIN32) include(cmake/WindowsDeployment.cmake) foreach(worker docview-pdf-worker docview-archive-worker) docview_configure_windows_worker(${worker}) docview_install_windows_worker(${worker}) endforeach() docview_install_windows_gui(docview) endif() if(BUILD_TESTING) find_package(Qt6 REQUIRED COMPONENTS Test QuickTest) find_package(Python3 REQUIRED COMPONENTS Interpreter) qt_add_executable(test_translations tests/test_translations.cpp src/app/translations.cpp) target_link_libraries(test_translations PRIVATE docview_core Qt6::Test Qt6::Quick Qt6::Qml Qt6::QuickControls2) qt_add_resources(test_translations test_translations_catalog PREFIX "/i18n" BASE "${CMAKE_CURRENT_BINARY_DIR}" FILES "${CMAKE_CURRENT_BINARY_DIR}/docview_ja.qm") add_dependencies(test_translations docview_lrelease) add_test(NAME translations COMMAND test_translations) set_tests_properties(translations PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen;QT_QUICK_BACKEND=software;LANG=C.UTF-8") add_test(NAME runtime_manifest COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_runtime_manifest.py" -v) add_test(NAME benchmark_runner COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_benchmark_runner.py" -v) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_test(NAME linux_package COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_linux_package.py" -v) add_test(NAME dependency_provenance COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_dependency_provenance_qt.py" -v) add_test(NAME ubuntu_runtime_inventory COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_ubuntu_validation_runtime.py" -v) add_test(NAME pdfium_candidate_staging COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_stage_pdfium_candidate.py" -v) add_test(NAME pdfium_candidate_integration COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_pdfium_candidate_integration.py" -v) endif() foreach(name core archive pdf security instance renderer_watchdog worker_process runtime_staging font_contract font_broker system_font_adapter memory_pressure) add_executable(test_${name} tests/test_${name}.cpp) target_link_libraries(test_${name} PRIVATE docview_common Qt6::Test) if(TARGET docview_${name}) target_link_libraries(test_${name} PRIVATE docview_${name}) endif() add_test(NAME ${name} COMMAND test_${name}) endforeach() target_link_libraries(test_memory_pressure PRIVATE docview_core) target_link_libraries(test_pdf PRIVATE docview_font_broker qpdf::libqpdf) target_link_libraries(test_system_font_adapter PRIVATE docview_pdf) add_executable(pdf-worker-evidence tests/render_pdf_worker.cpp) target_link_libraries(pdf-worker-evidence PRIVATE docview_common docview_font_broker Qt6::Gui) add_dependencies(pdf-worker-evidence docview-pdf-worker) if(WIN32) foreach(name windows_pipe windows_resources windows_worker) add_executable(test_${name} tests/test_${name}.cpp) target_link_libraries(test_${name} PRIVATE docview_common Qt6::Test) add_test(NAME ${name} COMMAND test_${name}) endforeach() add_executable(docview-windows-worker-probe tests/windows_worker_probe.cpp) target_link_libraries(docview-windows-worker-probe PRIVATE docview_common ws2_32 userenv advapi32 ole32) docview_configure_windows_worker(docview-windows-worker-probe) add_dependencies(test_windows_worker docview-windows-worker-probe) set_tests_properties(windows_worker PROPERTIES TIMEOUT 120) endif() add_dependencies(test_pdf docview-pdf-worker) add_dependencies(test_archive docview-archive-worker) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") # Exercises the actual 10/30/120-second timers without shortening the # production budgets. Run explicitly, or opt in to the long CTest case. add_executable(test_worker_deadlines tests/test_worker_deadlines.cpp) target_link_libraries(test_worker_deadlines PRIVATE docview_common Qt6::Test) option(DOCVIEW_ENABLE_LONG_TESTS "Register real-time worker watchdog tests" OFF) if(DOCVIEW_ENABLE_LONG_TESTS) add_test(NAME worker_deadlines COMMAND test_worker_deadlines) set_tests_properties(worker_deadlines PROPERTIES TIMEOUT 150 LABELS "long") endif() endif() add_executable(test_pdf_canvas tests/test_pdf_canvas.cpp src/app/pdf_canvas.cpp) target_link_libraries(test_pdf_canvas PRIVATE docview_pdf docview_common docview_font_broker Qt6::Test Qt6::Quick Qt6::Gui) add_dependencies(test_pdf_canvas docview-pdf-worker) add_test(NAME pdf_canvas COMMAND test_pdf_canvas) set_tests_properties(pdf_canvas PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen") add_test(NAME pdf_canvas_hidpi COMMAND test_pdf_canvas annotationFlagsHitTargetsMatchRenderedPixels sceneGraphPresentsPdfPixelsAndReplacesOldPage) set_tests_properties(pdf_canvas_hidpi PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen;QT_SCALE_FACTOR=2") qt_add_executable(test_app tests/test_app.cpp ${DOCVIEW_SHELL_SOURCES}) target_link_libraries(test_app PRIVATE docview_core docview_common docview_font_broker Qt6::Gui Qt6::Quick Qt6::Qml Qt6::QuickControls2 Qt6::WebEngineQuick Qt6::Test ${DOCVIEW_ZIP_TARGET}) target_compile_definitions(test_app PRIVATE DOCVIEW_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") add_dependencies(test_app docview-pdf-worker docview-archive-worker) add_test(NAME app COMMAND test_app) qt_add_executable(test_web_qml tests/test_web_qml.cpp src/web/web_profile.cpp resources.qrc) target_link_libraries(test_web_qml PRIVATE docview_common Qt6::Gui Qt6::Quick Qt6::Qml Qt6::WebEngineQuick Qt6::QuickTest Qt6::Test) add_test(NAME web COMMAND test_web_qml) set_tests_properties(app web PROPERTIES TIMEOUT 90) endif()