Skip to content

Commit 55c65a7

Browse files
Changes before error encountered
Co-authored-by: infinityabundance <255699974+infinityabundance@users.noreply.github.com>
1 parent d258315 commit 55c65a7

14 files changed

Lines changed: 2276 additions & 566 deletions

CMakeLists.txt

Lines changed: 134 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -302,202 +302,228 @@ set(WINDOWS_SOURCES
302302
src/service.c
303303
)
304304

305+
# =============================================================================
306+
# PHASE-93: rootstream_core — Linkable Static Library
307+
#
308+
# ALL protocol/crypto/decode/encode/network/audio logic lives here.
309+
# Executables (rootstream, rstr-player, rootstream-client) and the KDE client
310+
# link this single library instead of re-compiling the same sources N times.
311+
#
312+
# WHY A LIBRARY?
313+
# --------------
314+
# Before PHASE-93, each executable compiled every source file independently.
315+
# That meant:
316+
# 1. Duplicate compilation = longer build times.
317+
# 2. The KDE client could not link the real backend — it had no library to
318+
# link against, forcing it to stub or duplicate all protocol logic.
319+
# 3. Adding src/client_session.c (PHASE-94) would have to be added to every
320+
# executable's source list separately.
321+
#
322+
# With rootstream_core STATIC:
323+
# - One authoritative compiled object for all streaming logic.
324+
# - KDE client links it via add_subdirectory (see clients/kde-plasma-client).
325+
# - Tests can link specific subsets without re-compiling the world.
326+
# - PUBLIC include/ means any downstream target automatically gets the
327+
# correct include paths with no extra configuration.
328+
# =============================================================================
329+
305330
# =============================================================================
306331
# Targets
307332
# =============================================================================
308333

309334
if(UNIX AND NOT APPLE)
310-
# Linux: Full host + client
311-
add_executable(rootstream
312-
src/main.c
335+
# ── rootstream_core: the shared backend library ────────────────────────
336+
#
337+
# Contains everything EXCEPT:
338+
# - src/main.c (CLI entry point — stays in rootstream exe)
339+
# - tools/rstr-player.c (player tool entry point)
340+
# - src/tray*.c (tray UI — only needed by the host executable)
341+
#
342+
# display_sdl2.c is included because service_run_client() (which is in
343+
# service.c → rootstream_core) still calls display_init() for the SDL
344+
# fallback path. Once PHASE-94 is complete, service_run_client() becomes
345+
# a thin wrapper and display_sdl2.c can be moved to the executable.
346+
add_library(rootstream_core STATIC
313347
${COMMON_SOURCES}
314348
${LINUX_SOURCES}
315349
${PLATFORM_SOURCES}
350+
src/client_session.c
316351
)
317352

318-
target_include_directories(rootstream PRIVATE
319-
${CMAKE_SOURCE_DIR}/include
320-
${SDL2_INCLUDE_DIRS}
321-
${DRM_INCLUDE_DIRS}
322-
${GTK3_INCLUDE_DIRS}
353+
# PUBLIC include dir: any target that links rootstream_core automatically
354+
# receives the correct include path for rootstream.h and
355+
# rootstream_client_session.h without needing a separate
356+
# target_include_directories call.
357+
target_include_directories(rootstream_core
358+
PUBLIC
359+
${CMAKE_SOURCE_DIR}/include
360+
PRIVATE
361+
${CMAKE_SOURCE_DIR}/src
362+
${SDL2_INCLUDE_DIRS}
363+
${DRM_INCLUDE_DIRS}
364+
${GTK3_INCLUDE_DIRS}
323365
)
324366

325-
target_link_libraries(rootstream PRIVATE
367+
# Link all system libraries against rootstream_core (PUBLIC where needed
368+
# by downstream, PRIVATE for internal use only).
369+
target_link_libraries(rootstream_core PUBLIC
326370
${SDL2_LIBRARIES}
327371
${DRM_LIBRARIES}
328372
m pthread
329373
)
330374

331-
# Conditional libraries
332375
if(unofficial-sodium_FOUND)
333-
target_link_libraries(rootstream PRIVATE unofficial-sodium::sodium)
376+
target_link_libraries(rootstream_core PUBLIC unofficial-sodium::sodium)
334377
else()
335-
target_link_libraries(rootstream PRIVATE ${SODIUM_LIBRARIES})
336-
target_include_directories(rootstream PRIVATE ${SODIUM_INCLUDE_DIRS})
378+
target_link_libraries(rootstream_core PUBLIC ${SODIUM_LIBRARIES})
379+
target_include_directories(rootstream_core PUBLIC ${SODIUM_INCLUDE_DIRS})
337380
endif()
338381

339382
if(Opus_FOUND)
340-
target_link_libraries(rootstream PRIVATE Opus::opus)
383+
target_link_libraries(rootstream_core PUBLIC Opus::opus)
341384
else()
342-
target_link_libraries(rootstream PRIVATE ${OPUS_LIBRARIES})
343-
target_include_directories(rootstream PRIVATE ${OPUS_INCLUDE_DIRS})
385+
target_link_libraries(rootstream_core PUBLIC ${OPUS_LIBRARIES})
386+
target_include_directories(rootstream_core PUBLIC ${OPUS_INCLUDE_DIRS})
344387
endif()
345388

346389
if(VAAPI_FOUND)
347-
target_link_libraries(rootstream PRIVATE ${VAAPI_LIBRARIES})
348-
target_include_directories(rootstream PRIVATE ${VAAPI_INCLUDE_DIRS})
390+
target_link_libraries(rootstream_core PUBLIC ${VAAPI_LIBRARIES})
391+
target_include_directories(rootstream_core PUBLIC ${VAAPI_INCLUDE_DIRS})
349392
endif()
350393

351394
if(ALSA_FOUND)
352-
target_link_libraries(rootstream PRIVATE ${ALSA_LIBRARIES})
353-
target_include_directories(rootstream PRIVATE ${ALSA_INCLUDE_DIRS})
395+
target_link_libraries(rootstream_core PRIVATE ${ALSA_LIBRARIES})
396+
target_include_directories(rootstream_core PRIVATE ${ALSA_INCLUDE_DIRS})
354397
endif()
355398

356399
if(PULSEAUDIO_FOUND)
357-
target_link_libraries(rootstream PRIVATE ${PULSEAUDIO_LIBRARIES})
358-
target_include_directories(rootstream PRIVATE ${PULSEAUDIO_INCLUDE_DIRS})
400+
target_link_libraries(rootstream_core PRIVATE ${PULSEAUDIO_LIBRARIES})
401+
target_include_directories(rootstream_core PRIVATE ${PULSEAUDIO_INCLUDE_DIRS})
359402
endif()
360403

361404
if(PIPEWIRE_FOUND)
362-
target_link_libraries(rootstream PRIVATE ${PIPEWIRE_LIBRARIES})
363-
target_include_directories(rootstream PRIVATE ${PIPEWIRE_INCLUDE_DIRS})
405+
target_link_libraries(rootstream_core PRIVATE ${PIPEWIRE_LIBRARIES})
406+
target_include_directories(rootstream_core PRIVATE ${PIPEWIRE_INCLUDE_DIRS})
364407
endif()
365408

366409
if(NOT HEADLESS AND GTK3_FOUND)
367-
target_link_libraries(rootstream PRIVATE ${GTK3_LIBRARIES})
368-
target_include_directories(rootstream PRIVATE ${GTK3_INCLUDE_DIRS})
410+
target_link_libraries(rootstream_core PRIVATE ${GTK3_LIBRARIES})
411+
target_include_directories(rootstream_core PRIVATE ${GTK3_INCLUDE_DIRS})
369412
endif()
370413

371414
if(AVAHI_FOUND)
372-
target_link_libraries(rootstream PRIVATE ${AVAHI_LIBRARIES})
373-
target_include_directories(rootstream PRIVATE ${AVAHI_INCLUDE_DIRS})
415+
target_link_libraries(rootstream_core PRIVATE ${AVAHI_LIBRARIES})
416+
target_include_directories(rootstream_core PRIVATE ${AVAHI_INCLUDE_DIRS})
374417
endif()
375418

376419
if(X11_FOUND)
377-
target_link_libraries(rootstream PRIVATE ${X11_LIBRARIES})
378-
target_include_directories(rootstream PRIVATE ${X11_INCLUDE_DIRS})
420+
target_link_libraries(rootstream_core PRIVATE ${X11_LIBRARIES})
421+
target_include_directories(rootstream_core PRIVATE ${X11_INCLUDE_DIRS})
379422
endif()
380423

381424
if(QRENCODE_FOUND)
382-
target_link_libraries(rootstream PRIVATE ${QRENCODE_LIBRARIES})
383-
target_include_directories(rootstream PRIVATE ${QRENCODE_INCLUDE_DIRS})
425+
target_link_libraries(rootstream_core PRIVATE ${QRENCODE_LIBRARIES})
426+
target_include_directories(rootstream_core PRIVATE ${QRENCODE_INCLUDE_DIRS})
384427
endif()
385428

386429
if(PNG_FOUND)
387-
target_link_libraries(rootstream PRIVATE ${PNG_LIBRARIES})
388-
target_include_directories(rootstream PRIVATE ${PNG_INCLUDE_DIRS})
430+
target_link_libraries(rootstream_core PRIVATE ${PNG_LIBRARIES})
431+
target_include_directories(rootstream_core PRIVATE ${PNG_INCLUDE_DIRS})
389432
endif()
390-
433+
391434
if(NCURSES_FOUND)
392-
target_link_libraries(rootstream PRIVATE ${NCURSES_LIBRARIES})
393-
target_include_directories(rootstream PRIVATE ${NCURSES_INCLUDE_DIRS})
435+
target_link_libraries(rootstream_core PRIVATE ${NCURSES_LIBRARIES})
436+
target_include_directories(rootstream_core PRIVATE ${NCURSES_INCLUDE_DIRS})
394437
endif()
395-
438+
396439
if(FFMPEG_FOUND)
397-
target_link_libraries(rootstream PRIVATE ${FFMPEG_LIBRARIES})
398-
target_include_directories(rootstream PRIVATE ${FFMPEG_INCLUDE_DIRS})
440+
target_link_libraries(rootstream_core PUBLIC ${FFMPEG_LIBRARIES})
441+
target_include_directories(rootstream_core PUBLIC ${FFMPEG_INCLUDE_DIRS})
399442
endif()
400443

401-
# Recording player tool
402-
add_executable(rstr-player
403-
tools/rstr-player.c
404-
src/recording.c
405-
src/vaapi_decoder.c
406-
src/display_sdl2.c
407-
src/network.c
408-
src/network_tcp.c
409-
src/network_reconnect.c
410-
src/packet_validate.c
411-
src/crypto.c
412-
src/config.c
413-
src/input.c
414-
src/opus_codec.c
415-
src/audio_playback.c
416-
src/audio_playback_pulse.c
417-
src/audio_playback_pipewire.c
418-
src/audio_playback_dummy.c
419-
src/latency.c
420-
${PLATFORM_SOURCES}
444+
# ── rootstream: host + client CLI executable ───────────────────────────
445+
#
446+
# src/main.c is the ONLY source here — all real logic is in rootstream_core.
447+
# This keeps the executable thin and makes it easy to verify that no
448+
# protocol logic accidentally lives only in main.c.
449+
add_executable(rootstream
450+
src/main.c
421451
)
422452

423-
target_include_directories(rstr-player PRIVATE
424-
${CMAKE_SOURCE_DIR}/include
425-
${SDL2_INCLUDE_DIRS}
426-
)
453+
target_link_libraries(rootstream PRIVATE rootstream_core)
427454

428-
target_link_libraries(rstr-player PRIVATE
429-
${SDL2_LIBRARIES}
430-
${VAAPI_LIBRARIES}
431-
${ALSA_LIBRARIES}
432-
${SODIUM_LIBRARIES}
433-
${AVAHI_LIBRARIES}
434-
m pthread
455+
# ── rstr-player: recording playback tool ──────────────────────────────
456+
#
457+
# Links rootstream_core for all decode/display/audio logic.
458+
# Only the player tool's own main (tools/rstr-player.c) is compiled here.
459+
add_executable(rstr-player
460+
tools/rstr-player.c
435461
)
436462

437-
if(PULSEAUDIO_FOUND)
438-
target_link_libraries(rstr-player PRIVATE ${PULSEAUDIO_LIBRARIES})
439-
target_include_directories(rstr-player PRIVATE ${PULSEAUDIO_INCLUDE_DIRS})
440-
endif()
463+
target_link_libraries(rstr-player PRIVATE rootstream_core)
441464

442-
if(PIPEWIRE_FOUND)
443-
target_link_libraries(rstr-player PRIVATE ${PIPEWIRE_LIBRARIES})
444-
target_include_directories(rstr-player PRIVATE ${PIPEWIRE_INCLUDE_DIRS})
445-
endif()
446-
447-
if(Opus_FOUND)
448-
target_link_libraries(rstr-player PRIVATE Opus::opus)
449-
else()
450-
target_link_libraries(rstr-player PRIVATE ${OPUS_LIBRARIES})
451-
endif()
465+
# KDE Plasma client is built via its own CMakeLists.txt which uses
466+
# add_subdirectory(../.. rootstream_build) to pull in rootstream_core.
467+
# See: clients/kde-plasma-client/CMakeLists.txt (PHASE-93.2)
452468

453469
endif()
454470

455471
if(WIN32)
456-
# Windows: Client only
457-
add_executable(rootstream-client WIN32
458-
src/main_client.c
472+
# ── Windows: rootstream_core_win (Windows backend library) ────────────
473+
#
474+
# Same principle as the Linux library: all backend logic in one library,
475+
# thin executable on top.
476+
add_library(rootstream_core_win STATIC
459477
${COMMON_SOURCES}
460478
${WINDOWS_SOURCES}
461479
${PLATFORM_SOURCES}
480+
src/client_session.c
462481
)
463482

464-
target_include_directories(rootstream-client PRIVATE
465-
${CMAKE_SOURCE_DIR}/include
483+
target_include_directories(rootstream_core_win
484+
PUBLIC
485+
${CMAKE_SOURCE_DIR}/include
486+
PRIVATE
487+
${CMAKE_SOURCE_DIR}/src
466488
)
467489

468-
# Windows system libraries
469-
target_link_libraries(rootstream-client PRIVATE
470-
ws2_32 # Winsock
471-
mfplat # Media Foundation
472-
mfuuid # Media Foundation GUIDs
473-
mf # Media Foundation
474-
ole32 # COM
475-
d3d11 # Direct3D 11
476-
dxgi # DXGI
490+
target_link_libraries(rootstream_core_win PUBLIC
491+
ws2_32 mfplat mfuuid mf ole32 d3d11 dxgi
477492
)
478493

479-
# vcpkg dependencies
480494
if(unofficial-sodium_FOUND)
481-
target_link_libraries(rootstream-client PRIVATE unofficial-sodium::sodium)
495+
target_link_libraries(rootstream_core_win PUBLIC unofficial-sodium::sodium)
482496
endif()
483-
484497
if(SDL2_FOUND)
485-
target_link_libraries(rootstream-client PRIVATE SDL2::SDL2 SDL2::SDL2main)
498+
target_link_libraries(rootstream_core_win PUBLIC SDL2::SDL2 SDL2::SDL2main)
486499
endif()
487-
488500
if(Opus_FOUND)
489-
target_link_libraries(rootstream-client PRIVATE Opus::opus)
501+
target_link_libraries(rootstream_core_win PUBLIC Opus::opus)
490502
endif()
503+
504+
# Windows client executable — thin, links the library
505+
add_executable(rootstream-client WIN32
506+
src/main_client.c
507+
)
508+
509+
target_link_libraries(rootstream-client PRIVATE rootstream_core_win)
491510
endif()
492511

493512
# =============================================================================
494513
# Installation
495514
# =============================================================================
496515

497516
if(UNIX AND NOT APPLE)
517+
install(TARGETS rootstream_core ARCHIVE DESTINATION lib)
498518
install(TARGETS rootstream RUNTIME DESTINATION bin)
499519
install(TARGETS rstr-player RUNTIME DESTINATION bin)
500520

521+
# Public headers (needed by downstream consumers like KDE client)
522+
install(FILES
523+
include/rootstream.h
524+
include/rootstream_client_session.h
525+
DESTINATION include/rootstream)
526+
501527
# Desktop file
502528
install(FILES assets/rootstream.desktop
503529
DESTINATION share/applications)
@@ -508,6 +534,7 @@ if(UNIX AND NOT APPLE)
508534
endif()
509535

510536
if(WIN32)
537+
install(TARGETS rootstream_core_win ARCHIVE DESTINATION lib)
511538
install(TARGETS rootstream-client RUNTIME DESTINATION bin)
512539
endif()
513540

@@ -517,7 +544,8 @@ endif()
517544

518545
enable_testing()
519546

520-
# Unit tests
547+
# Unit tests — link against rootstream_core to avoid re-listing source files
548+
# and to ensure the tests exercise the same compiled code as the executables.
521549
add_executable(test_crypto tests/unit/test_crypto.c src/crypto.c ${PLATFORM_SOURCES})
522550
target_include_directories(test_crypto PRIVATE ${CMAKE_SOURCE_DIR}/include)
523551
if(unofficial-sodium_FOUND)

0 commit comments

Comments
 (0)