Files
orbithub/CMakeLists.txt
T
ksmithandClaude Sonnet 5 aa812b0da7 macOS: fix launch crash, missing dylibs, and dmg volume icon
The app crashed at launch with "cannot be opened because of a
problem" because macdeployqt invalidates the code signature when it
rewrites library load paths; re-sign (ad hoc) after macdeployqt runs.

Also fixes the underlying cause of a Library-missing crash: orbithub's
INSTALL_RPATH used the Linux linker token $ORIGIN, which dyld does not
understand, and the bundled FreeRDP/WinPR/KodoTerm dylibs installed to
a sibling lib/orbithub/ directory outside OrbitHub.app rather than
Contents/Frameworks, so they were never copied into the dmg at all.
Both are now APPLE-specific, matching macdeployqt's own layout
(Contents/Frameworks, @executable_path/../Frameworks).

build-dmg.sh now also sets a custom volume icon (via SetFile or the
fileicon brew formula, whichever is available) instead of the
generic disk image icon, degrading gracefully if neither is present.

Also includes the StartupWMClass desktop-file fix from the prior
commit's message, which was never actually staged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-08 14:00:46 -06:00

261 lines
9.6 KiB
CMake

cmake_minimum_required(VERSION 3.21)
project(OrbitHub VERSION 2026.9.8 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/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)
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
"$<TARGET_FILE_DIR:orbithub>/platforms"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:Qt6::QWindowsIntegrationPlugin>"
"$<TARGET_FILE_DIR:orbithub>/platforms/"
COMMENT "Deploying Qt Windows platform plugin"
)
install(FILES "$<TARGET_FILE:Qt6::QWindowsIntegrationPlugin>"
DESTINATION "${CMAKE_INSTALL_BINDIR}/platforms"
)
endif()
if(TARGET Qt6::QSQLiteDriverPlugin)
add_custom_command(TARGET orbithub POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
"$<TARGET_FILE_DIR:orbithub>/sqldrivers"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:Qt6::QSQLiteDriverPlugin>"
"$<TARGET_FILE_DIR:orbithub>/sqldrivers/"
COMMENT "Deploying Qt SQLite driver plugin"
)
install(FILES "$<TARGET_FILE:Qt6::QSQLiteDriverPlugin>"
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}"
"$<TARGET_FILE_DIR:orbithub>/"
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/orbithub)