cmake_minimum_required(VERSION 3.21) project(OrbitHub VERSION 2026.9.15 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) include(GNUInstallDirs) find_package(Qt6 6.2 REQUIRED COMPONENTS Widgets Sql) qt_standard_project_setup() add_subdirectory(third_party/KodoTerm) if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/FreeRDP/CMakeLists.txt") message(FATAL_ERROR "Vendored FreeRDP source is missing at third_party/FreeRDP") endif() # Pin FreeRDP build to the vendored source tree so headers/libs are always from the same revision. set(FREERDP_UNIFIED_BUILD ON CACHE BOOL "" FORCE) set(WITH_MANPAGES OFF CACHE BOOL "" FORCE) set(WITH_SAMPLE OFF CACHE BOOL "" FORCE) set(BUILD_TESTING OFF CACHE BOOL "" FORCE) set(BUILD_TESTING_INTERNAL OFF CACHE BOOL "" FORCE) set(WITH_CLIENT_COMMON ON CACHE BOOL "" FORCE) set(WITH_CLIENT OFF CACHE BOOL "" FORCE) set(WITH_CLIENT_SDL OFF CACHE BOOL "" FORCE) set(WITH_CLIENT_INTERFACE OFF CACHE BOOL "" FORCE) set(WITH_SERVER OFF CACHE BOOL "" FORCE) set(WITH_CHANNELS ON CACHE BOOL "" FORCE) set(WITH_CLIENT_CHANNELS ON CACHE BOOL "" FORCE) set(WITH_FUSE OFF CACHE BOOL "" FORCE) set(CHANNEL_DRDYNVC ON CACHE BOOL "" FORCE) set(CHANNEL_DRDYNVC_CLIENT ON CACHE BOOL "" FORCE) set(CHANNEL_DISP ON CACHE BOOL "" FORCE) set(CHANNEL_DISP_CLIENT ON CACHE BOOL "" FORCE) set(CHANNEL_AINPUT OFF CACHE BOOL "" FORCE) set(CHANNEL_AUDIN OFF CACHE BOOL "" FORCE) set(CHANNEL_CLIPRDR ON CACHE BOOL "" FORCE) set(CHANNEL_CLIPRDR_CLIENT ON CACHE BOOL "" FORCE) set(CHANNEL_DRIVE OFF CACHE BOOL "" FORCE) set(CHANNEL_ECHO OFF CACHE BOOL "" FORCE) set(CHANNEL_ENCOMSP OFF CACHE BOOL "" FORCE) set(CHANNEL_GEOMETRY OFF CACHE BOOL "" FORCE) set(CHANNEL_LOCATION OFF CACHE BOOL "" FORCE) set(CHANNEL_PARALLEL OFF CACHE BOOL "" FORCE) set(CHANNEL_PRINTER OFF CACHE BOOL "" FORCE) set(CHANNEL_RAIL OFF CACHE BOOL "" FORCE) set(CHANNEL_RDPDR OFF CACHE BOOL "" FORCE) set(CHANNEL_RDPEAR OFF CACHE BOOL "" FORCE) set(CHANNEL_RDPECAM OFF CACHE BOOL "" FORCE) set(CHANNEL_RDPEI OFF CACHE BOOL "" FORCE) set(CHANNEL_RDPEMSC OFF CACHE BOOL "" FORCE) set(CHANNEL_RDPGFX OFF CACHE BOOL "" FORCE) set(CHANNEL_RDPSND OFF CACHE BOOL "" FORCE) set(CHANNEL_REMDESK OFF CACHE BOOL "" FORCE) set(CHANNEL_SERIAL OFF CACHE BOOL "" FORCE) set(CHANNEL_SMARTCARD OFF CACHE BOOL "" FORCE) set(CHANNEL_SSHAGENT OFF CACHE BOOL "" FORCE) set(CHANNEL_TELEMETRY OFF CACHE BOOL "" FORCE) set(CHANNEL_URBDRC OFF CACHE BOOL "" FORCE) set(CHANNEL_VIDEO OFF CACHE BOOL "" FORCE) set(WITH_FFMPEG OFF CACHE BOOL "" FORCE) set(WITH_DSP_FFMPEG OFF CACHE BOOL "" FORCE) set(WITH_VIDEO_FFMPEG OFF CACHE BOOL "" FORCE) set(WITH_CAIRO OFF CACHE BOOL "" FORCE) set(WITH_SWSCALE OFF CACHE BOOL "" FORCE) set(WITH_JPEG OFF CACHE BOOL "" FORCE) set(WITH_KRB5 OFF CACHE BOOL "" FORCE) set(WITH_UNICODE_BUILTIN ON CACHE BOOL "" FORCE) set(WITH_WINPR_TOOLS OFF CACHE BOOL "" FORCE) add_subdirectory(third_party/FreeRDP EXCLUDE_FROM_ALL) set(ORBITHUB_SOURCES src/about_dialog.cpp src/about_dialog.h src/user_guide_dialog.cpp src/user_guide_dialog.h docs/user_guide.qrc src/app_icon.cpp src/app_icon.h src/main.cpp src/profile_dialog.cpp src/profile_dialog.h src/profile_repository.cpp src/profile_repository.h src/profiles_tree_widget.cpp src/profiles_tree_widget.h src/profiles_window.cpp src/profiles_window.h src/session_backend.h src/session_backend_factory.cpp src/session_backend_factory.h src/session_tab.cpp src/session_tab.h src/rdp_display_widget.cpp src/rdp_display_widget.h src/terminal_view.cpp src/terminal_view.h src/session_window.cpp src/session_window.h src/rdp_session_backend.cpp src/rdp_session_backend.h src/ssh_session_backend.cpp src/ssh_session_backend.h src/unsupported_session_backend.cpp src/unsupported_session_backend.h ) if(WIN32) list(APPEND ORBITHUB_SOURCES packaging/windows/orbithub.rc) endif() if(APPLE) list(APPEND ORBITHUB_SOURCES packaging/macos/orbithub.icns) set_source_files_properties(packaging/macos/orbithub.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources" ) set(MACOSX_BUNDLE_ICON_FILE orbithub.icns) set(MACOSX_BUNDLE_BUNDLE_NAME "OrbitHub") set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.darksingularity.OrbitHub") set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") endif() add_executable(orbithub WIN32 MACOSX_BUNDLE ${ORBITHUB_SOURCES}) target_link_libraries(orbithub PRIVATE Qt6::Widgets Qt6::Sql) target_link_libraries(orbithub PRIVATE KodoTerm::KodoTerm) target_compile_definitions(orbithub PRIVATE ORBITHUB_VERSION_STRING="${PROJECT_VERSION}") if(TARGET freerdp AND TARGET winpr) target_compile_definitions(orbithub PRIVATE ORBITHUB_HAS_FREERDP) target_include_directories(orbithub PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/FreeRDP/include ${CMAKE_CURRENT_SOURCE_DIR}/third_party/FreeRDP/winpr/include ${CMAKE_CURRENT_BINARY_DIR}/third_party/FreeRDP/include ${CMAKE_CURRENT_BINARY_DIR}/third_party/FreeRDP/winpr/include ) target_link_libraries(orbithub PRIVATE freerdp winpr) if(TARGET freerdp-client) target_link_libraries(orbithub PRIVATE freerdp-client) endif() else() message(FATAL_ERROR "Vendored FreeRDP targets were not produced as expected.") endif() # Qt loads platform integration and SQL driver plugins dynamically at # runtime (QFactoryLoader), so they never appear in orbithub.exe's import # table. vcpkg's automatic DLL deployment only follows the import table, so # these plugins have to be copied out explicitly or the app fails to start # with "Could not find the Qt platform plugin" / "can not load requested # driver 'QSQLITE'". if(WIN32) if(TARGET Qt6::QWindowsIntegrationPlugin) add_custom_command(TARGET orbithub POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "$/platforms" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$/platforms/" COMMENT "Deploying Qt Windows platform plugin" ) install(FILES "$" DESTINATION "${CMAKE_INSTALL_BINDIR}/platforms" ) endif() if(TARGET Qt6::QSQLiteDriverPlugin) add_custom_command(TARGET orbithub POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "$/sqldrivers" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$/sqldrivers/" COMMENT "Deploying Qt SQLite driver plugin" ) install(FILES "$" DESTINATION "${CMAKE_INSTALL_BINDIR}/sqldrivers" ) # vcpkg's qtbase[sql-sqlite] links the plugin against vcpkg's own # shared sqlite3 port rather than bundling SQLite into the plugin, # so the plugin fails to load ("can not load requested driver # 'QSQLITE'") unless sqlite3.dll also ships next to the executable. find_file(ORBITHUB_SQLITE3_DLL NAMES sqlite3.dll PATHS ${CMAKE_PREFIX_PATH} PATH_SUFFIXES bin ) if(ORBITHUB_SQLITE3_DLL) add_custom_command(TARGET orbithub POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ORBITHUB_SQLITE3_DLL}" "$/" COMMENT "Deploying sqlite3.dll (Qt SQLite plugin dependency)" ) install(FILES "${ORBITHUB_SQLITE3_DLL}" DESTINATION "${CMAKE_INSTALL_BINDIR}") endif() endif() endif() if(APPLE) # Mirrors macdeployqt's own layout for Qt frameworks: dylibs live in # Contents/Frameworks inside the bundle, found via @executable_path # (the macOS/dyld equivalent of Linux's $ORIGIN token, which dyld # does not understand). set_target_properties(orbithub PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks" INSTALL_RPATH_USE_LINK_PATH ON ) else() set_target_properties(orbithub PROPERTIES BUILD_RPATH_USE_ORIGIN ON INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/orbithub" INSTALL_RPATH_USE_LINK_PATH ON ) endif() install(TARGETS orbithub RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} BUNDLE DESTINATION . ) if(APPLE) set(ORBITHUB_PRIVATE_LIB_DESTINATION "OrbitHub.app/Contents/Frameworks") else() set(ORBITHUB_PRIVATE_LIB_DESTINATION "${CMAKE_INSTALL_LIBDIR}/orbithub") endif() set(ORBITHUB_RUNTIME_TARGETS KodoTerm freerdp winpr) if(TARGET freerdp-client) list(APPEND ORBITHUB_RUNTIME_TARGETS freerdp-client) endif() foreach(runtime_target IN LISTS ORBITHUB_RUNTIME_TARGETS) if(TARGET ${runtime_target}) install(TARGETS ${runtime_target} RUNTIME DESTINATION ${ORBITHUB_PRIVATE_LIB_DESTINATION} LIBRARY DESTINATION ${ORBITHUB_PRIVATE_LIB_DESTINATION} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() endforeach() install(FILES packaging/linux/org.darksingularity.OrbitHub.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications ) foreach(icon_size IN ITEMS 16 24 32 48 64 128 256) install(FILES packaging/linux/icons/${icon_size}x${icon_size}/apps/org.darksingularity.OrbitHub.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${icon_size}x${icon_size}/apps ) endforeach() install(FILES packaging/linux/org.darksingularity.OrbitHub.metainfo.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo ) install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/org.darksingularity.OrbitHub ) install(FILES third_party/FreeRDP/LICENSE DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/org.darksingularity.OrbitHub RENAME LICENSE-FreeRDP ) install(FILES third_party/KodoTerm/LICENSE DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/org.darksingularity.OrbitHub RENAME LICENSE-KodoTerm )