-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
945 lines (874 loc) · 39.2 KB
/
Copy pathCMakeLists.txt
File metadata and controls
945 lines (874 loc) · 39.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
cmake_minimum_required(VERSION 3.20)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" DECKBOY_VERSION_RAW)
string(STRIP "${DECKBOY_VERSION_RAW}" DECKBOY_VERSION_STRING)
if(NOT DECKBOY_VERSION_STRING MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-[0-9A-Za-z.-]+)?$")
message(FATAL_ERROR
"VERSION must use SemVer: MAJOR.MINOR.PATCH or MAJOR.MINOR.PATCH-prerelease"
)
endif()
set(DECKBOY_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(DECKBOY_VERSION_MINOR "${CMAKE_MATCH_2}")
set(DECKBOY_VERSION_PATCH "${CMAKE_MATCH_3}")
set(DECKBOY_VERSION_PRERELEASE "${CMAKE_MATCH_4}")
set(DECKBOY_VERSION_TAG "v${DECKBOY_VERSION_STRING}")
# HOW OLD A macOS THIS BINARY WILL RUN ON.
#
# Must be set BEFORE project(), because that is when the compiler is probed.
#
# With nothing here, clang stamps the BUILD machine's OS as the minimum, and
# the OS refuses to launch a binary whose minimum is newer than itself. CI
# builds on a GitHub runner, so the release bundle quietly acquired whatever
# macOS that image happened to be -- and would not open on Sonoma, which is
# exactly what was reported from the field.
#
# This floor is only half of it. The bundle also carries Homebrew's dylibs,
# and a Homebrew bottle is built for the runner's own OS, so the REAL floor is
# the runner image. That is why the packaging job is pinned rather than left on
# macos-latest; see .github/workflows/build.yml.
if(APPLE AND NOT CMAKE_OSX_DEPLOYMENT_TARGET)
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0" CACHE STRING
"Oldest macOS this build will run on" FORCE)
endif()
project(deckboy_native VERSION
${DECKBOY_VERSION_MAJOR}.${DECKBOY_VERSION_MINOR}.${DECKBOY_VERSION_PATCH}
LANGUAGES CXX
)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
function(deckboy_target_link_frameworks target)
if(NOT APPLE)
return()
endif()
foreach(framework IN LISTS ARGN)
find_library(DECKBOY_${framework}_FRAMEWORK NAMES ${framework})
if(NOT DECKBOY_${framework}_FRAMEWORK)
message(FATAL_ERROR "Required macOS framework not found: ${framework}")
endif()
target_link_libraries(${target} PRIVATE ${DECKBOY_${framework}_FRAMEWORK})
endforeach()
endfunction()
# SDL3 + SDL3_ttf (migrated from SDL2, v0.77.0). Prefer CMake config packages
# (vcpkg on Windows); fall back to pkg-config on Linux.
set(DECKBOY_SDL_TARGET "")
set(DECKBOY_SDL_TTF_TARGET "")
set(DECKBOY_SDL_INCLUDE_DIRS "")
set(DECKBOY_SDL_TTF_INCLUDE_DIRS "")
set(DECKBOY_SDL_LINK_LIBS "")
set(DECKBOY_SDL_TTF_LINK_LIBS "")
set(DECKBOY_SDL_COMPILE_OPTIONS "")
set(DECKBOY_SDL_LINK_DIRS "")
find_package(SDL3 QUIET CONFIG)
find_package(SDL3_ttf QUIET CONFIG)
if(TARGET SDL3::SDL3)
set(DECKBOY_SDL_TARGET SDL3::SDL3)
elseif(TARGET SDL3::SDL3-static)
set(DECKBOY_SDL_TARGET SDL3::SDL3-static)
endif()
if(TARGET SDL3_ttf::SDL3_ttf)
set(DECKBOY_SDL_TTF_TARGET SDL3_ttf::SDL3_ttf)
elseif(TARGET SDL3_ttf::SDL3_ttf-static)
set(DECKBOY_SDL_TTF_TARGET SDL3_ttf::SDL3_ttf-static)
endif()
# Unconditional: pkg_check_modules is also used further down (RtMidi), and
# looking PkgConfig up only inside the SDL fallback meant that when SDL3 came
# from a CONFIG package the command was never defined — so configuring with
# -DENABLE_MIDI=ON failed outright with "Unknown CMake command".
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND AND NOT DECKBOY_SDL_TARGET)
pkg_check_modules(SDL3 QUIET sdl3)
set(DECKBOY_SDL_INCLUDE_DIRS ${SDL3_INCLUDE_DIRS})
set(DECKBOY_SDL_LINK_LIBS ${SDL3_LIBRARIES})
list(APPEND DECKBOY_SDL_COMPILE_OPTIONS ${SDL3_CFLAGS_OTHER})
list(APPEND DECKBOY_SDL_LINK_DIRS ${SDL3_LIBRARY_DIRS})
endif()
if(PkgConfig_FOUND AND NOT DECKBOY_SDL_TTF_TARGET)
pkg_check_modules(SDL3_TTF QUIET sdl3-ttf)
set(DECKBOY_SDL_TTF_INCLUDE_DIRS ${SDL3_TTF_INCLUDE_DIRS})
set(DECKBOY_SDL_TTF_LINK_LIBS ${SDL3_TTF_LIBRARIES})
list(APPEND DECKBOY_SDL_COMPILE_OPTIONS ${SDL3_TTF_CFLAGS_OTHER})
list(APPEND DECKBOY_SDL_LINK_DIRS ${SDL3_TTF_LIBRARY_DIRS})
endif()
if(NOT DECKBOY_SDL_TARGET AND NOT DECKBOY_SDL_LINK_LIBS)
message(FATAL_ERROR "SDL3 development files are required")
endif()
if(NOT DECKBOY_SDL_TTF_TARGET AND NOT DECKBOY_SDL_TTF_LINK_LIBS)
message(FATAL_ERROR "SDL3_ttf development files are required")
endif()
option(DECKBOY_ENABLE_NDI "Enable optional NDI SDK integration" ON)
if(DECKBOY_ENABLE_NDI)
find_path(DECKBOY_NDI_INCLUDE_DIR
NAMES Processing.NDI.Lib.h
PATHS
"$ENV{DECKBOY_NDI_SDK}/include"
"$ENV{NDI_SDK_DIR}/Include"
# Windows — NDI 6/5 SDK standard install locations
"C:/Program Files/NDI/NDI 6 SDK/Include"
"C:/Program Files/NDI/NDI 5 SDK/Include"
# Linux — standard install locations (installer extracts to CWD)
"/opt/NDI SDK for Linux/include"
"$ENV{HOME}/NDI SDK for Linux/include"
"/usr/local/include"
"/usr/include"
)
endif()
option(DECKBOY_ENABLE_ALSA_MTC "Enable optional ALSA MTC ingest integration" ON)
if(UNIX AND NOT APPLE AND DECKBOY_ENABLE_ALSA_MTC)
find_path(DECKBOY_ALSA_INCLUDE_DIR
NAMES asoundlib.h
PATH_SUFFIXES alsa
PATHS
/usr/include
/usr/local/include
)
find_library(DECKBOY_ALSA_LIBRARY
NAMES asound
)
endif()
# XTEST — driving a browser cue on Linux.
#
# The Linux browser backend is Chromium on a private Xvfb display, so there is
# no JavaScript channel the way WebView2 gives one on Windows. XTEST sends REAL
# pointer events to that display instead, which is strictly better: it drives
# the page exactly as a person would, including anything a synthetic DOM event
# would miss.
#
# Optional, and found rather than required: libXtst is present on any desktop
# Linux, but a headless build box may not have it, and a browser cue that
# cannot be clicked is a smaller loss than a build that will not configure.
if(UNIX AND NOT APPLE)
find_path(DECKBOY_XTEST_INCLUDE_DIR
NAMES X11/extensions/XTest.h
PATHS /usr/include /usr/local/include
)
find_library(DECKBOY_XTEST_LIBRARY NAMES Xtst)
find_library(DECKBOY_X11_LIBRARY NAMES X11)
endif()
# In-process libav* decode (GPU decode rewrite, docs/GPU_DECODE_PLAN.md).
# When ON and the FFmpeg dev libraries are found, file-backed Video/Audio
# cues decode in-process (d3d11va zero-copy on Windows) instead of spawning
# ffmpeg subprocess pipes. OFF (or libs missing) keeps the CLI pipe path —
# the break-glass fallback build.
option(DECKBOY_INPROC_DECODE "Decode media in-process via libav (GPU zero-copy)" ON)
set(DECKBOY_INPROC_DECODE_ACTIVE OFF)
if(DECKBOY_INPROC_DECODE)
find_path(DECKBOY_AVCODEC_INCLUDE_DIR NAMES libavcodec/avcodec.h)
find_library(DECKBOY_AVCODEC_LIBRARY NAMES avcodec)
find_library(DECKBOY_AVFORMAT_LIBRARY NAMES avformat)
find_library(DECKBOY_AVUTIL_LIBRARY NAMES avutil)
find_library(DECKBOY_AVFILTER_LIBRARY NAMES avfilter)
find_library(DECKBOY_SWSCALE_LIBRARY NAMES swscale)
find_library(DECKBOY_SWRESAMPLE_LIBRARY NAMES swresample)
if(DECKBOY_AVCODEC_INCLUDE_DIR AND DECKBOY_AVCODEC_LIBRARY AND
DECKBOY_AVFORMAT_LIBRARY AND DECKBOY_AVUTIL_LIBRARY AND
DECKBOY_AVFILTER_LIBRARY AND DECKBOY_SWSCALE_LIBRARY AND
DECKBOY_SWRESAMPLE_LIBRARY)
set(DECKBOY_INPROC_DECODE_ACTIVE ON)
message(STATUS "In-process libav decode enabled: ${DECKBOY_AVCODEC_LIBRARY}")
else()
message(WARNING "DECKBOY_INPROC_DECODE=ON but FFmpeg dev libraries were not found; building with the ffmpeg CLI decode path only")
endif()
endif()
# Pro Features Feature Gates
# ON by default: the SDK headers are vendored in native/extras/decklink-sdk, so
# there is nothing to download and no reason for a downloaded build to arrive
# unable to talk to a card. The runtime comes from Blackmagic's Desktop Video
# package, and a machine without it simply reports no devices.
option(ENABLE_DECKLINK "Build with Blackmagic DeckLink capture and playout" ON)
option(ENABLE_MIDI "Build with RtMidi cross-platform MIDI input" OFF)
option(ENABLE_SIPHON "Build with macOS Siphon interprocess texture sharing" OFF)
option(ENABLE_SPOUT "Build with Windows Spout interprocess texture sharing" OFF)
option(ENABLE_ASIO "Build with Steinberg ASIO low-latency audio (Windows)" ON)
option(ENABLE_CEF "Build with Chromium Embedded Framework browser cues" OFF)
# ── zlib, for reading the notes out of a .pptx ──────────────────────────────
#
# A PowerPoint file is a ZIP, and the speaker notes are XML inside it -- which
# makes them the only per-slide notes that are properly machine-readable
# without a PDF parser. Google Slides exports .pptx too, so a team that works
# in Slides and exports a PDF for the fonts can drop the .pptx beside it and
# keep their notes.
#
# OPTIONAL, and quietly so: zlib is present on macOS and Linux as a matter of
# course and comes from vcpkg on Windows, but a build without it simply loses
# .pptx notes. The sidecar route keeps working either way, so nothing an
# operator relies on disappears.
find_package(ZLIB QUIET)
if(ZLIB_FOUND)
message(STATUS "zlib found: .pptx speaker notes will be read")
else()
message(STATUS "zlib not found: .pptx notes disabled (sidecar notes still work)")
endif()
option(ENABLE_WEBVIEW "Build with native WebView APIs (macOS WKWebView, Windows WebView2)" OFF)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/generated")
# Generate version header at build time so editing VERSION triggers a rebuild
# without needing to re-run cmake configure.
set(GENERATED_VERSION_HPP "${CMAKE_CURRENT_BINARY_DIR}/generated/deckboy_version.hpp")
add_custom_command(
OUTPUT "${GENERATED_VERSION_HPP}"
COMMAND "${CMAKE_COMMAND}"
"-DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}"
"-DOUTPUT_FILE=${GENERATED_VERSION_HPP}"
-P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate_version.cmake"
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/VERSION"
"${CMAKE_CURRENT_SOURCE_DIR}/native/core/version.hpp.in"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate_version.cmake"
COMMENT "Generating deckboy_version.hpp from VERSION"
VERBATIM
)
add_custom_target(deckboy_generate_version DEPENDS "${GENERATED_VERSION_HPP}")
# DeckLink SDK (Blackmagic DeckLink SDK 16.x)
#
# The SDK ships platform-specific headers:
# Windows: .idl files → compiled by MIDL → DeckLinkAPI_h.h + DeckLinkAPI_i.c
# Linux: .h files + DeckLinkAPIDispatch.cpp (dynamic loader stub)
# macOS: .h files + DeckLinkAPIDispatch.cpp (dynamic loader stub)
#
# Set DECKLINK_SDK_DIR (cmake var or env) to the SDK root, e.g.:
# -DDECKLINK_SDK_DIR="G:/Blackmagic_DeckLink_SDK_16.0/Blackmagic DeckLink SDK 16.0"
#
if(ENABLE_DECKLINK)
# Resolve SDK root from cmake variable, then environment variable
if(NOT DECKLINK_SDK_DIR)
set(DECKLINK_SDK_DIR "$ENV{DECKLINK_SDK_DIR}")
endif()
# Also accept the older env var name
if(NOT DECKLINK_SDK_DIR)
set(DECKLINK_SDK_DIR "$ENV{DECKLINK_SDK}")
endif()
# The vendored headers, used unless something else was named explicitly.
if(NOT DECKLINK_SDK_DIR)
set(DECKLINK_SDK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/native/extras/decklink-sdk")
endif()
if(WIN32)
# Windows SDK uses .idl files in Win/include/
find_path(DECKLINK_IDL_DIR
NAMES DeckLinkAPI.idl
PATHS
"${DECKLINK_SDK_DIR}/Win/include"
"$ENV{DECKLINK_SDK}/Win/include"
NO_DEFAULT_PATH
)
if(NOT DECKLINK_IDL_DIR)
# Also try auto-discovery under common install paths
find_path(DECKLINK_IDL_DIR
NAMES DeckLinkAPI.idl
PATHS
"C:/Program Files/Blackmagic Design/DeckLink SDK/Win/include"
"C:/Blackmagic DeckLink SDK/Win/include"
)
endif()
if(NOT DECKLINK_IDL_DIR)
message(FATAL_ERROR "DeckLink SDK not found (Windows). Set DECKLINK_SDK_DIR to the SDK root (containing Win/include/DeckLinkAPI.idl)")
endif()
message(STATUS "DeckLink support enabled (Windows IDL): ${DECKLINK_IDL_DIR}")
else()
# Linux / macOS SDK uses .h files directly
if(APPLE)
set(_DECKLINK_PLATFORM_SUBDIR "Mac")
else()
set(_DECKLINK_PLATFORM_SUBDIR "Linux")
endif()
find_path(DECKLINK_INCLUDE_DIR
NAMES DeckLinkAPI.h
PATHS
"${DECKLINK_SDK_DIR}/${_DECKLINK_PLATFORM_SUBDIR}/include"
"$ENV{DECKLINK_SDK}/${_DECKLINK_PLATFORM_SUBDIR}/include"
"$ENV{DECKLINK_SDK}/include"
"/opt/Blackmagic DeckLink SDK/${_DECKLINK_PLATFORM_SUBDIR}/include"
"/usr/local/include"
"/usr/include"
)
if(NOT DECKLINK_INCLUDE_DIR)
message(FATAL_ERROR "DeckLink SDK not found. Set DECKLINK_SDK_DIR to the SDK root or disable ENABLE_DECKLINK")
endif()
# Verify dispatch source exists
if(NOT EXISTS "${DECKLINK_INCLUDE_DIR}/DeckLinkAPIDispatch.cpp")
message(FATAL_ERROR "DeckLinkAPIDispatch.cpp not found in ${DECKLINK_INCLUDE_DIR}")
endif()
message(STATUS "DeckLink support enabled: ${DECKLINK_INCLUDE_DIR}")
endif()
endif()
# RtMidi — auto-detect from vcpkg, then fallback to pkg-config / manual paths
find_package(rtmidi CONFIG QUIET)
if(rtmidi_FOUND AND NOT ENABLE_MIDI)
set(ENABLE_MIDI ON CACHE BOOL "Build with RtMidi cross-platform MIDI input" FORCE)
message(STATUS "RtMidi auto-detected from vcpkg, enabling MIDI support")
endif()
if(ENABLE_MIDI)
if(NOT rtmidi_FOUND AND PkgConfig_FOUND)
pkg_check_modules(RTMIDI rtmidi QUIET)
endif()
if(NOT rtmidi_FOUND AND NOT RTMIDI_FOUND)
find_path(RTMIDI_INCLUDE_DIR
NAMES RtMidi.h
PATHS
"$ENV{RTMIDI_SDK}/include"
"/usr/local/include"
"/usr/include"
)
find_library(RTMIDI_LIBRARY
NAMES rtmidi
PATHS
"$ENV{RTMIDI_SDK}/lib"
"/usr/local/lib"
"/usr/lib"
)
endif()
if(rtmidi_FOUND OR RTMIDI_FOUND OR (RTMIDI_INCLUDE_DIR AND RTMIDI_LIBRARY))
if(rtmidi_FOUND)
message(STATUS "RtMidi support enabled (vcpkg)")
elseif(RTMIDI_FOUND)
message(STATUS "RtMidi support enabled (pkg-config)")
else()
message(STATUS "RtMidi support enabled: ${RTMIDI_LIBRARY}")
endif()
else()
message(STATUS "RtMidi SDK not found, using stub implementation (no actual MIDI input)")
endif()
else()
message(STATUS "RtMidi support disabled (ENABLE_MIDI=OFF)")
endif()
# Syphon (macOS). NOTE: the framework is "Syphon" (with a y); the earlier
# scaffolding searched for "Siphon" and so could never have found it. The build
# OPTION keeps the historical ENABLE_SIPHON spelling for compatibility.
if(ENABLE_SIPHON AND APPLE)
find_library(SYPHON_FRAMEWORK Syphon)
if(NOT SYPHON_FRAMEWORK)
message(FATAL_ERROR "Syphon.framework not found. Build it from "
"github.com/Syphon/Syphon-Framework and install it where find_library can "
"see it, or disable ENABLE_SIPHON. See docs/SYPHON_PLAN.md.")
endif()
message(STATUS "Syphon support enabled: ${SYPHON_FRAMEWORK}")
endif()
# Spout (Windows) — auto-detect from vcpkg or manual SDK path
if(WIN32)
find_package(Spout2 CONFIG QUIET)
if(Spout2_FOUND)
set(ENABLE_SPOUT ON)
message(STATUS "Spout support auto-detected and enabled (vcpkg)")
elseif(ENABLE_SPOUT)
find_path(SPOUT_INCLUDE_DIR
NAMES SpoutLibrary.h
PATHS
"$ENV{SPOUT_SDK}/include"
"C:/Spout/include"
)
if(NOT SPOUT_INCLUDE_DIR)
message(FATAL_ERROR "Spout SDK not found on Windows. Disable ENABLE_SPOUT or set SPOUT_SDK env var")
endif()
message(STATUS "Spout support enabled (manual SDK)")
endif()
endif()
# CEF (Chromium Embedded Framework)
if(ENABLE_CEF)
# Headers alone are NOT enough to claim CEF support. The previous version of
# this block located cef_api_hash.h, defined DECKBOY_HAS_CEF, and stopped —
# so a build with -DENABLE_CEF=ON advertised CEF in the About dialog while
# browser cues still went through Xvfb. Require the library too, and the
# wrapper static lib that every real CEF app links.
find_path(CEF_INCLUDE_DIR
NAMES cef_api_hash.h
PATHS
"$ENV{CEF_SDK}/include"
"/opt/cef/include"
"/opt/cef"
PATH_SUFFIXES include
)
find_library(CEF_LIBRARY
NAMES cef libcef
PATHS
"$ENV{CEF_SDK}/Release"
"$ENV{CEF_SDK}/lib"
"/opt/cef/Release"
)
find_library(CEF_DLL_WRAPPER
NAMES cef_dll_wrapper libcef_dll_wrapper
PATHS
"$ENV{CEF_SDK}/libcef_dll_wrapper"
"$ENV{CEF_SDK}/build/libcef_dll_wrapper/Release"
"$ENV{CEF_SDK}/Release"
"/opt/cef/libcef_dll_wrapper"
)
if(NOT CEF_INCLUDE_DIR OR NOT CEF_LIBRARY OR NOT CEF_DLL_WRAPPER)
message(FATAL_ERROR
"ENABLE_CEF=ON but a complete CEF SDK was not found.\n"
" headers : ${CEF_INCLUDE_DIR}\n"
" libcef : ${CEF_LIBRARY}\n"
" dll_wrapper : ${CEF_DLL_WRAPPER}\n"
"Set CEF_SDK to a CEF binary distribution whose libcef_dll_wrapper has "
"been built, or disable ENABLE_CEF. See docs/BROWSER_CEF_PLAN.md.")
endif()
message(STATUS "CEF support enabled: ${CEF_LIBRARY}")
endif()
# WebView (macOS/Windows native)
if(ENABLE_WEBVIEW AND NOT APPLE AND NOT WIN32)
message(FATAL_ERROR "ENABLE_WEBVIEW is only supported on macOS and Windows")
endif()
add_executable(deckboy-native
native/main.cpp
native/core/paths.cpp
native/core/i18n.cpp
native/core/utils.cpp
native/core/subprocess.cpp
native/engine/media_engine.cpp
native/platform/browser.cpp
native/platform/pdf_import.cpp
native/platform/capture_backend.cpp
native/platform/integration_backend.cpp
native/platform/output_backend.cpp
# ST 2110-20 sender: plain sockets only, no SDK, so it compiles unconditionally
# on every platform (same reasoning as decklink.cpp above — a feature-guarded
# translation unit whose symbols are referenced unguarded breaks the link).
native/platform/st2110_output.cpp
# HAP frame decoding: container parse + a vendored Snappy decompressor, no
# SDK and no new dependency, so it compiles unconditionally like the two
# above. Snappy is vendored rather than linked because decompression is a
# small frozen format and a per-platform dep is exactly what kept this CI
# red for months.
native/engine/hap_decoder.cpp
# Always compiled: the recording readback is a RENDERER concern, and
# living in libav_decoder.cpp meant a build with in-process decode off
# did not have it at all.
native/engine/gpu_readback.cpp
# Always compiled; the libav half is guarded inside, so a build without
# in-process decode gets stubs rather than a link error.
native/engine/motion_field.cpp
# PTPv2 slave for ST 2059 media-clock alignment. Plain sockets, no SDK.
native/platform/ptp_client.cpp
# NMOS IS-04/IS-05 node: HTTP server + registration client for the 2110
# senders. Plain sockets and a hand-rolled JSON reader, no SDK, so this also
# compiles unconditionally.
native/platform/nmc_sync.cpp
native/platform/nmos_node.cpp
# Vendored Terrarium sim. This shim compiles upstream/terrarium_core.cpp
# INSIDE `namespace terra` — do not add that .cpp here directly, or its
# definitions land at global scope and fail to link. See
# native/extras/upstream/UPSTREAM.md.
native/extras/terrarium_vendor.cpp
native/render/primitives.cpp
native/render/text_renderer.cpp
native/render/waveform_renderer.cpp
native/render/output_renderer.cpp
)
set_target_properties(deckboy-native PROPERTIES OUTPUT_NAME "Deckboy")
# macOS screen capture helper. avfoundation screen capture is gone on current
# macOS, so window/screen cues run this small ScreenCaptureKit binary, which
# writes raw RGBA frames to stdout exactly like ffmpeg does. Built for every
# macOS build (no feature flag) so the bundle always ships it. @available guards
# the 12.3+ symbols, so the deployment target stays at the app's minimum.
if(APPLE)
# ARC, EXPLICITLY.
#
# clang does NOT enable ARC by default, and every .mm file here is written
# for it -- no retain, no release, strong properties, and __block object
# pointers that only hold a reference under ARC. Built without it,
# sckcapture.mm's `__block SCDisplay* chosen` does not retain what the
# completion handler assigns, so the display is gone by the time the filter
# is built: a segfault in -[SCContentFilter initWithDisplay:excludingWindows:],
# which macOS shows the operator as "Deckboy quit unexpectedly".
#
# This hid for a long time because building a helper by hand to test it
# means passing -fobjc-arc on the command line, so the hand-built one worked
# and only the packaged build crashed.
add_executable(deckboy-sckcapture native/platform/sckcapture.mm)
target_compile_options(deckboy-sckcapture PRIVATE -fobjc-arc)
set_target_properties(deckboy-sckcapture PROPERTIES OUTPUT_NAME "deckboy-sckcapture")
target_link_libraries(deckboy-sckcapture PRIVATE
# AppKit for NSApplicationLoad: ScreenCaptureKit aborts a process with no
# window-server connection (CGS_REQUIRE_INIT), and connecting is AppKit's
# job. Building this helper by hand with -framework AppKit is what hid the
# missing link line here.
"-framework AppKit"
"-framework ScreenCaptureKit"
"-framework CoreMedia"
"-framework CoreVideo"
"-framework CoreGraphics"
"-framework Foundation")
# Deckboy depends on the helper existing next to it, so build it alongside.
add_dependencies(deckboy-native deckboy-sckcapture)
# The browser cue backend. A WKWebView in a parked NSWindow, captured through
# the sckcapture helper above as an ordinary "window:<id>" source -- so the
# browser cue reuses the whole macOS capture path rather than growing a
# second one.
add_executable(deckboy-webview native/platform/webview_macos.mm)
target_compile_options(deckboy-webview PRIVATE -fobjc-arc)
set_target_properties(deckboy-webview PROPERTIES OUTPUT_NAME "deckboy-webview")
target_link_libraries(deckboy-webview PRIVATE
"-framework Cocoa"
"-framework WebKit"
"-framework Foundation")
add_dependencies(deckboy-native deckboy-webview)
# The main app's window picker (listCaptureWindows in capture_backend.cpp)
# enumerates on-screen windows via CoreGraphics/CoreFoundation, so the app
# itself must link them (the helper's own link line above is separate).
target_link_libraries(deckboy-native PRIVATE
"-framework CoreGraphics"
"-framework CoreFoundation")
endif()
# ── Steinberg ASIO ───────────────────────────────────────────────────────────
# The vendored SDK subset is used under the GPL v3 half of its DUAL licence,
# which is compatible with Deckboy's own GPL-3.0-or-later. See
# native/third_party/asio/README.md before assuming otherwise -- the common
# advice that ASIO cannot ship in a GPL program describes older SDK releases.
#
# ON by default because there is no licence obstacle and no external dependency
# to install: the driver itself is supplied by the user's audio interface, and
# its absence is a runtime condition rather than a build one.
#
# asio_audio.cpp is compiled EVERYWHERE. It carries a full set of stubs under
# `#if !defined(DECKBOY_HAS_ASIO)` -- "built without ASIO support" -- and the
# app calls AsioOutput unconditionally. Adding the file only inside this Windows
# branch meant macOS and Linux linked against declarations with no definitions
# and failed at link, which is how ASIO broke both of those builds outright.
target_sources(deckboy-native PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/native/platform/asio_audio.cpp")
if(WIN32 AND ENABLE_ASIO)
set(DECKBOY_ASIO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/native/third_party/asio")
if(EXISTS "${DECKBOY_ASIO_DIR}/asio.h")
target_sources(deckboy-native PRIVATE
"${DECKBOY_ASIO_DIR}/asio.cpp"
"${DECKBOY_ASIO_DIR}/asiodrivers.cpp"
"${DECKBOY_ASIO_DIR}/asiolist.cpp")
target_include_directories(deckboy-native PRIVATE "${DECKBOY_ASIO_DIR}")
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_ASIO=1)
# The SDK predates modern warning levels and is not ours to clean up.
if(MSVC)
set_source_files_properties(
"${DECKBOY_ASIO_DIR}/asio.cpp"
"${DECKBOY_ASIO_DIR}/asiodrivers.cpp"
"${DECKBOY_ASIO_DIR}/asiolist.cpp"
# /FI force-includes: the SDK sources use the COM `interface` macro
# and IUnknown without including the headers that define them, relying
# on the host project having done so first. Forcing them per-TU is
# cleaner than editing vendored code we will re-extract on update.
PROPERTIES COMPILE_FLAGS "/w /FIwindows.h /FIobjbase.h")
endif()
message(STATUS "ASIO: enabled (vendored SDK 2.3.4, GPLv3 option)")
else()
message(STATUS "ASIO: SDK sources missing, skipping")
endif()
endif()
# Export dynamic symbols on POSIX so the crash handler's backtrace resolves to
# function names. Without this, backtrace_symbols_fd can only print
# "Deckboy(+0x4b83b)" for our own frames — the crash log tells you a crash
# happened and nothing about where, which is most of its value gone. Verified
# on Linux: the difference between an offset and `App::renderOutputWindow`.
# Costs a slightly larger dynamic symbol table and nothing else.
if(NOT MSVC)
set_target_properties(deckboy-native PROPERTIES ENABLE_EXPORTS ON)
target_link_options(deckboy-native PRIVATE -rdynamic)
endif()
add_dependencies(deckboy-native deckboy_generate_version)
# Slide-deck import renders PDF pages through CoreGraphics and writes them
# with ImageIO. Not behind a feature flag, because importing a deck is not
# optional -- and CI caught this the hard way: the code compiled and only the
# LINK failed, on the one platform that could not be built locally.
# CoreVideo is here for the VideoToolbox zero-copy path: the decoder asks a
# frame's CVPixelBuffer what format it is before wrapping it as a texture. Same
# shape of mistake as the line above, caught the same way -- the header is
# included, every translation unit compiles, and only the link fails.
if(APPLE)
deckboy_target_link_frameworks(deckboy-native
CoreGraphics ImageIO CoreFoundation CoreVideo)
endif()
if(WIN32)
# WindowsApp.lib is the WinRT entry point. It is here for Windows.Data.Pdf,
# which renders imported slide decks -- the same engine Edge uses, so a PDF
# needs no bundled rasteriser and no third-party licence.
target_link_libraries(deckboy-native PRIVATE windowsapp)
set_target_properties(deckboy-native PROPERTIES WIN32_EXECUTABLE TRUE)
# EVERY runtime DLL the binary actually imports, put beside it.
#
# vcpkg deploys the DLLs of the packages it resolved through CONFIG targets,
# which covered SDL3, freetype and the rest -- and silently did not cover
# RtMidi, which is found through pkg-config on some paths. So a feature build
# produced a Deckboy.exe with no rtmidi.dll next to it, the packager copied
# "every .dll CMake placed here" and got a set with a hole in it, and the
# zipped build would not START on any machine that did not already have
# RtMidi installed. It ran fine on the machine that built it, which is the
# worst possible way for this to behave.
#
# TARGET_RUNTIME_DLLS asks the linker what was actually imported instead of
# maintaining a list by hand, so the next optional dependency cannot repeat
# it. CMake 3.21+; the project floor is 3.20, so it is guarded rather than
# made a new requirement.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21)
add_custom_command(TARGET deckboy-native POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_RUNTIME_DLLS:deckboy-native>"
"$<TARGET_FILE_DIR:deckboy-native>"
COMMAND_EXPAND_LISTS
VERBATIM)
endif()
# Embed the application icon as resource IDI_DECKBOY_APP_ICON. This drives the
# Explorer/Alt-Tab/taskbar-pin icon AND is loaded at runtime by
# applyDeckboyWindowIcon() (WM_SETICON) for the live window/taskbar icon.
set(DECKBOY_APP_ICON "${CMAKE_CURRENT_SOURCE_DIR}/art/windows/icons/deckboy_app.ico")
if(EXISTS "${DECKBOY_APP_ICON}")
file(TO_NATIVE_PATH "${DECKBOY_APP_ICON}" _deckboy_icon_native)
string(REPLACE "\\" "\\\\" DECKBOY_APP_ICON_RC_PATH "${_deckboy_icon_native}")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/art/windows/deckboy.rc.in"
"${CMAKE_CURRENT_BINARY_DIR}/deckboy.rc" @ONLY)
target_sources(deckboy-native PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/deckboy.rc")
else()
message(WARNING "Deckboy app icon not found at ${DECKBOY_APP_ICON}; exe will use the default icon.")
endif()
endif()
# Platform modules (conditional)
if(ENABLE_MIDI)
target_sources(deckboy-native PRIVATE native/platform/midi.cpp)
endif()
# decklink.cpp compiles unconditionally: it already carries a full stub
# implementation behind !DECKBOY_HAS_DECKLINK (listDevices returns {}, init
# reports unavailable). The UI calls DeckLinkOutput::listDevices() and the
# mode helpers without feature guards, so excluding the whole translation unit
# left those symbols undefined and broke every build with ENABLE_DECKLINK=OFF
# at link time. That never showed up locally because the Windows dev build
# has DeckLink enabled.
target_sources(deckboy-native PRIVATE native/platform/decklink.cpp)
target_sources(deckboy-native PRIVATE native/platform/ndi_input.cpp)
# ALWAYS COMPILED, like every other platform file here: the whole body is
# behind DECKBOY_HAS_SPOUT and collapses to stubs without it, and callers ask
# SpoutInput::available() unconditionally. Gating the SOURCE on ENABLE_SPOUT
# instead left those callers with nothing to link against and broke all three
# platforms at once -- including Windows, in the configuration without Spout.
target_sources(deckboy-native PRIVATE native/platform/spout_input.cpp)
# The GL context Spout receive needs -- see spout_input.hpp. Only when it is
# actually built with Spout; nothing else in Deckboy uses OpenGL.
if(ENABLE_SPOUT)
target_link_libraries(deckboy-native PRIVATE opengl32)
endif()
if(ENABLE_DECKLINK)
if(WIN32)
# On Windows, compile the IDL with MIDL to generate DeckLinkAPI_h.h and
# DeckLinkAPI_i.c in the build directory, then compile the _i.c file.
set(DECKLINK_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/decklink_generated")
file(MAKE_DIRECTORY "${DECKLINK_GENERATED_DIR}")
add_custom_command(
OUTPUT
"${DECKLINK_GENERATED_DIR}/DeckLinkAPI_h.h"
"${DECKLINK_GENERATED_DIR}/DeckLinkAPI_i.c"
COMMAND midl
/h "DeckLinkAPI_h.h"
/iid "DeckLinkAPI_i.c"
/proxy "DeckLinkAPI_p.c"
/tlb "DeckLinkAPI.tlb"
/out "${DECKLINK_GENERATED_DIR}"
"${DECKLINK_IDL_DIR}/DeckLinkAPI.idl"
DEPENDS "${DECKLINK_IDL_DIR}/DeckLinkAPI.idl"
COMMENT "Compiling DeckLink IDL (MIDL)"
VERBATIM
)
add_custom_target(deckboy_decklink_idl DEPENDS
"${DECKLINK_GENERATED_DIR}/DeckLinkAPI_h.h"
"${DECKLINK_GENERATED_DIR}/DeckLinkAPI_i.c"
)
add_dependencies(deckboy-native deckboy_decklink_idl)
target_sources(deckboy-native PRIVATE "${DECKLINK_GENERATED_DIR}/DeckLinkAPI_i.c")
set_source_files_properties("${DECKLINK_GENERATED_DIR}/DeckLinkAPI_i.c"
PROPERTIES
GENERATED TRUE
LANGUAGE C
)
else()
# On Linux/macOS, compile the SDK dispatch source (provides CreateDeckLinkIteratorInstance)
target_sources(deckboy-native PRIVATE "${DECKLINK_INCLUDE_DIR}/DeckLinkAPIDispatch.cpp")
endif()
endif()
if(ENABLE_SIPHON OR ENABLE_SPOUT)
target_sources(deckboy-native PRIVATE native/platform/siphon_spout.cpp)
endif()
if(DECKBOY_INPROC_DECODE_ACTIVE)
target_sources(deckboy-native PRIVATE native/engine/libav_decoder.cpp)
target_include_directories(deckboy-native PRIVATE ${DECKBOY_AVCODEC_INCLUDE_DIR})
target_link_libraries(deckboy-native PRIVATE
${DECKBOY_AVCODEC_LIBRARY}
${DECKBOY_AVFORMAT_LIBRARY}
${DECKBOY_AVUTIL_LIBRARY}
${DECKBOY_AVFILTER_LIBRARY}
${DECKBOY_SWSCALE_LIBRARY}
${DECKBOY_SWRESAMPLE_LIBRARY}
)
target_compile_definitions(deckboy-native PRIVATE DECKBOY_INPROC_DECODE=1)
endif()
target_include_directories(deckboy-native PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/native
${CMAKE_CURRENT_BINARY_DIR}/generated
)
if(NOT DECKBOY_SDL_TARGET)
target_include_directories(deckboy-native PRIVATE ${DECKBOY_SDL_INCLUDE_DIRS})
endif()
if(NOT DECKBOY_SDL_TTF_TARGET)
target_include_directories(deckboy-native PRIVATE ${DECKBOY_SDL_TTF_INCLUDE_DIRS})
endif()
# Pro Features includes and defines
if(ENABLE_DECKLINK)
if(WIN32)
# Include the MIDL-generated headers directory
target_include_directories(deckboy-native PRIVATE "${DECKLINK_GENERATED_DIR}")
else()
# Include the SDK headers directory (contains DeckLinkAPI.h + LinuxCOM.h)
target_include_directories(deckboy-native PRIVATE "${DECKLINK_INCLUDE_DIR}")
endif()
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_DECKLINK=1)
endif()
if(ENABLE_MIDI)
if(rtmidi_FOUND)
target_link_libraries(deckboy-native PRIVATE RtMidi::rtmidi)
elseif(RTMIDI_FOUND)
target_include_directories(deckboy-native PRIVATE ${RTMIDI_INCLUDE_DIRS})
target_link_libraries(deckboy-native PRIVATE ${RTMIDI_LIBRARIES})
elseif(RTMIDI_INCLUDE_DIR AND RTMIDI_LIBRARY)
target_include_directories(deckboy-native PRIVATE ${RTMIDI_INCLUDE_DIR})
target_link_libraries(deckboy-native PRIVATE ${RTMIDI_LIBRARY})
endif()
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_MIDI=1)
endif()
if(ENABLE_SIPHON AND APPLE)
# The Objective-C++ publisher and the frameworks it needs. Only pulled in with
# ENABLE_SIPHON so a default macOS build stays free of Metal/Syphon.
target_sources(deckboy-native PRIVATE native/platform/syphon_metal.mm)
# Same reasoning as the helpers above: written for ARC, so compile it that way.
set_source_files_properties(native/platform/syphon_metal.mm
PROPERTIES COMPILE_OPTIONS "-fobjc-arc")
deckboy_target_link_frameworks(deckboy-native Syphon Metal Foundation)
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_SIPHON=1)
endif()
if(ENABLE_SPOUT AND WIN32)
if(Spout2_FOUND)
target_link_libraries(deckboy-native PRIVATE Spout2::SpoutLibrary)
else()
target_include_directories(deckboy-native PRIVATE ${SPOUT_INCLUDE_DIR})
endif()
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_SPOUT=1)
endif()
if(ZLIB_FOUND)
target_link_libraries(deckboy-native PRIVATE ZLIB::ZLIB)
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_ZLIB=1)
endif()
if(ENABLE_CEF)
target_include_directories(deckboy-native PRIVATE ${CEF_INCLUDE_DIR})
target_link_libraries(deckboy-native PRIVATE ${CEF_DLL_WRAPPER} ${CEF_LIBRARY})
# DECKBOY_HAS_CEF means "libcef is linked into this binary". It does NOT yet
# mean browser cues run on CEF — that is gated separately at runtime until the
# off-screen backend lands (docs/BROWSER_CEF_PLAN.md, phase 3).
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_CEF=1)
endif()
if(ENABLE_WEBVIEW)
if(APPLE)
deckboy_target_link_frameworks(deckboy-native WebKit)
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_WEBVIEW=1)
elseif(WIN32)
find_package(unofficial-webview2 CONFIG REQUIRED)
target_link_libraries(deckboy-native PRIVATE unofficial::webview2::webview2 dwmapi)
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_WEBVIEW=1)
message(STATUS "WebView2 support enabled")
endif()
elseif(WIN32)
# Auto-detect WebView2 even when ENABLE_WEBVIEW is OFF
find_package(unofficial-webview2 CONFIG QUIET)
if(unofficial-webview2_FOUND)
target_link_libraries(deckboy-native PRIVATE unofficial::webview2::webview2 dwmapi)
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_WEBVIEW=1)
message(STATUS "WebView2 auto-detected and enabled")
endif()
endif()
if(DECKBOY_ENABLE_NDI AND DECKBOY_NDI_INCLUDE_DIR)
target_include_directories(deckboy-native PRIVATE
${DECKBOY_NDI_INCLUDE_DIR}
)
target_compile_definitions(deckboy-native PRIVATE
DECKBOY_HAS_NDI_SDK=1
)
endif()
if(UNIX AND NOT APPLE AND DECKBOY_ENABLE_ALSA_MTC AND DECKBOY_ALSA_INCLUDE_DIR AND DECKBOY_ALSA_LIBRARY)
target_include_directories(deckboy-native PRIVATE
${DECKBOY_ALSA_INCLUDE_DIR}
)
target_link_libraries(deckboy-native PRIVATE
${DECKBOY_ALSA_LIBRARY}
)
target_compile_definitions(deckboy-native PRIVATE
DECKBOY_HAS_ALSA=1
)
endif()
target_compile_options(deckboy-native PRIVATE
${DECKBOY_SDL_COMPILE_OPTIONS}
)
if(DECKBOY_SDL_LINK_DIRS)
target_link_directories(deckboy-native PRIVATE
${DECKBOY_SDL_LINK_DIRS}
)
endif()
if(DECKBOY_SDL_TARGET)
target_link_libraries(deckboy-native PRIVATE ${DECKBOY_SDL_TARGET})
else()
target_link_libraries(deckboy-native PRIVATE ${DECKBOY_SDL_LINK_LIBS})
endif()
if(DECKBOY_SDL_TTF_TARGET)
target_link_libraries(deckboy-native PRIVATE ${DECKBOY_SDL_TTF_TARGET})
else()
target_link_libraries(deckboy-native PRIVATE ${DECKBOY_SDL_TTF_LINK_LIBS})
endif()
# The bundled `terrarium` companion exe was RETIRED in v0.81.5.
#
# It existed so the Konami egg could launch a windowed sim and capture it via
# gdigrab. That has been unnecessary since v0.78.4, when the sim moved
# in-process as pattern://terrarium — nothing has needed the exe since. It also
# built against the old forked copy of the sim, which is exactly the file this
# release replaced with a clean vendored upstream, so keeping it would have
# meant maintaining two divergent copies of Terrarium inside Deckboy.
#
# The real standalone app lives in its own repo (Utopian-Academy/terrarium).
if(UNIX AND NOT APPLE)
target_link_libraries(deckboy-native PRIVATE dl)
endif()
if(UNIX AND NOT APPLE AND DECKBOY_XTEST_INCLUDE_DIR
AND DECKBOY_XTEST_LIBRARY AND DECKBOY_X11_LIBRARY)
target_include_directories(deckboy-native PRIVATE ${DECKBOY_XTEST_INCLUDE_DIR})
target_link_libraries(deckboy-native PRIVATE
${DECKBOY_XTEST_LIBRARY} ${DECKBOY_X11_LIBRARY})
target_compile_definitions(deckboy-native PRIVATE DECKBOY_HAS_XTEST=1)
message(STATUS "Browser cue input: XTEST enabled (Linux pages can be clicked and scrolled)")
elseif(UNIX AND NOT APPLE)
message(STATUS "Browser cue input: XTEST not found - Linux browser cues will not take input")
endif()
target_compile_definitions(deckboy-native PRIVATE
$<$<CONFIG:Debug>:DECKBOY_DEBUG=1>
$<$<BOOL:${WIN32}>:NOMINMAX>
$<$<BOOL:${WIN32}>:WIN32_LEAN_AND_MEAN>
$<$<BOOL:${WIN32}>:SDL_MAIN_HANDLED>
)
if(MSVC)
target_compile_options(deckboy-native PRIVATE /bigobj)
# Two warnings promoted out of level 4, where nobody was ever going to see
# them, because both have already cost real time here:
#
# C4456-C4459 a name that hides another. Whoever edits the inner scope has
# no indication the outer one exists, which is how the wrong
# variable gets used. A duplicated block whose second copy
# shadowed the first meant a fix applied to half the cases.
# C4189 a local that is initialised and never read -- the leftover of
# an approach that was replaced, still reading as though it
# matters, and it gave a later loop something to shadow.
#
# Level 1 so they appear in an ordinary build, not just under /W4, whose
# other 380 warnings are int-to-float conversions into SDL's float APIs and
# would bury these. tools/audit_warnings.py is the gate.
target_compile_options(deckboy-native PRIVATE
/w14456 /w14457 /w14458 /w14459 /w14189)
else()
# The same two, as GCC and Clang spell them. -Wshadow=local rather than
# -Wshadow: the full form also fires on a local that shadows a member, and
# this codebase's App class has hundreds of members.
target_compile_options(deckboy-native PRIVATE -Wunused-variable)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(deckboy-native PRIVATE -Wshadow=local)
else()
target_compile_options(deckboy-native PRIVATE -Wshadow)
endif()
endif()
if(WIN32)
target_link_libraries(deckboy-native PRIVATE ws2_32 shell32)
endif()