cmake_minimum_required(VERSION 3.20) project(beyond_proximity LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Driver name must match manifest "name" field with driver_ prefix # Manifest name: "BeyondProximity" -> DLL: "driver_BeyondProximity.dll" set(DRIVER_NAME "driver_BeyondProximity") set(TARGET_NAME "BeyondProximity") # OpenVR SDK paths (vendored) set(OPENVR_ROOT "${CMAKE_SOURCE_DIR}/extern/openvr") set(OPENVR_INCLUDE_DIR "${OPENVR_ROOT}/headers") # 64-bit only if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(OPENVR_LIB "${OPENVR_ROOT}/lib/win64/openvr_api.lib") set(ARCH_TARGET "win64") else() message(FATAL_ERROR "Only 64-bit builds are supported") endif() # Output directly to driver package structure set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/driver/${TARGET_NAME}/bin/${ARCH_TARGET}") # Flatten per-config output directories (avoid Release/Debug subdirectories) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") # HIDAPI - vendored, built as static library set(BUILD_SHARED_LIBS FALSE CACHE BOOL "" FORCE) add_subdirectory(extern/hidapi) # Driver shared library add_library(${DRIVER_NAME} SHARED src/driver/hmd_driver_factory.cpp src/driver/device_provider.h src/driver/device_provider.cpp src/driver/driverlog.h src/driver/driverlog.cpp src/hid/hid_device.h src/hid/hid_device.cpp src/hid/proximity_algorithm.h src/hid/proximity_algorithm.cpp src/hid/user_signature.h src/hid/user_signature.cpp ) target_include_directories(${DRIVER_NAME} PRIVATE ${OPENVR_INCLUDE_DIR}) target_link_libraries(${DRIVER_NAME} PRIVATE ${OPENVR_LIB} hidapi::hidapi ) # IPD persistence via lighthouse_console (can be disabled if Beyond Utility handles persistence) option(ENABLE_IPD_PERSIST "Enable IPD persistence to lighthouse config on shutdown" ON) if(ENABLE_IPD_PERSIST) target_compile_definitions(${DRIVER_NAME} PRIVATE ENABLE_IPD_PERSIST) endif() # Phase 14 + 15: Backglow LED subsystem (v3.0) # USB serial to WLED ESP32-C3 (MagWLED-1 prototype) and DDP-over-WiFi fallback. # All sources live under src/led/ and are guarded by ENABLE_BACKGLOW (D-22). # user32 = RegisterDeviceNotification (Phase 14). # ws2_32 = Winsock UDP for DDP transport + raw-socket HTTP probe (Phase 15, TRNS-02). # setupapi = SetupDiGetClassDevs VID/PID enumeration (Phase 15, LHWD-04). option(ENABLE_BACKGLOW "Enable backglow LED subsystem (USB serial + WiFi DDP to WLED ESP32-C3)" ON) if(ENABLE_BACKGLOW) target_sources(${DRIVER_NAME} PRIVATE src/led/led_transport.h src/led/wled_serial.h src/led/wled_serial.cpp src/led/wled_tpm2.h src/led/wled_tpm2.cpp src/led/led_controller.h src/led/led_controller.cpp src/led/wled_ddp.h src/led/wled_ddp.cpp src/led/com_port_scan.h src/led/com_port_scan.cpp ) target_compile_definitions(${DRIVER_NAME} PRIVATE ENABLE_BACKGLOW) target_link_libraries(${DRIVER_NAME} PRIVATE user32 # RegisterDeviceNotification (Phase 14) ws2_32 # Winsock UDP + raw-socket HTTP for DDP (Phase 15) setupapi # SetupDi VID/PID enumeration (Phase 15) ) message(STATUS "ENABLE_BACKGLOW=ON -- building LED subsystem (USB + DDP)") else() message(STATUS "ENABLE_BACKGLOW=OFF -- skipping LED subsystem") endif() # Phase 16: VRChat OSC Bridge daemon (v3.0) # Separate Windows executable that receives VRChat avatar OSC parameters and # forwards per-LED + Bri commands to the driver via \\.\pipe\beyond_proximity_ctl. # Wrapped in ENABLE_BACKGLOW so builds without backglow still succeed (D-25). # Links: # ws2_32 = Winsock UDP (OSC recv) + TCP (OSCQuery HTTP responder) # iphlpapi = GetAdaptersAddresses, used by mjansson/mdns on Windows if(ENABLE_BACKGLOW) add_executable(beyond_backglow_ctl src/backglow_ctl/main.cpp src/backglow_ctl/daemon_log.cpp src/backglow_ctl/osc_server.cpp src/backglow_ctl/param_map.cpp src/backglow_ctl/pipe_client.cpp src/backglow_ctl/startup_anim.cpp src/backglow_ctl/oscquery_http.cpp src/backglow_ctl/mdns_advertise.cpp # extern/mdns/mdns.h is header-only (function bodies inline); mdns.c is # a standalone example executable, not a library TU. No separate compile needed. ) target_include_directories(beyond_backglow_ctl PRIVATE ${CMAKE_SOURCE_DIR}/extern/oscpp/include ${CMAKE_SOURCE_DIR}/extern/mdns ) target_link_libraries(beyond_backglow_ctl PRIVATE ws2_32 iphlpapi ) target_compile_definitions(beyond_backglow_ctl PRIVATE _WIN32_WINNT=0x0A00) set_target_properties(beyond_backglow_ctl PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/driver/${TARGET_NAME}/bin/win64" ) message(STATUS "Phase 16: beyond_backglow_ctl target configured") endif() # Copy driver assets (manifest, resources) to build output add_custom_command(TARGET ${DRIVER_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/driver/${TARGET_NAME}" "${CMAKE_BINARY_DIR}/driver/${TARGET_NAME}" ) # Debug control CLI tool (named pipe client) # No OpenVR or HIDAPI dependency -- pure Win32 add_executable(beyond_prox_ctl src/ctl/main.cpp ) # Spike proximity monitor (OpenVR client app for observing proximity state) add_executable(beyond_spike_monitor src/spike/proximity_monitor.cpp ) target_include_directories(beyond_spike_monitor PRIVATE ${OPENVR_INCLUDE_DIR}) target_link_libraries(beyond_spike_monitor PRIVATE ${OPENVR_LIB}) # Client apps need openvr_api.dll at runtime (driver DLL does not -- loaded by vrserver) add_custom_command(TARGET beyond_spike_monitor POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OPENVR_ROOT}/bin/win64/openvr_api.dll" "$" ) # Phase 14.1 spike: pure-function harness (throwaway, remove in 14-02) add_executable(backglow_spike_harness src/spike/backglow_spike/harness.cpp ) # Phase 14.1 spike: hardware CLI (throwaway, remove in 14-02) add_executable(backglow_serial_spike src/spike/backglow_spike/serial_spike.cpp ) target_link_libraries(backglow_serial_spike PRIVATE user32) # --- Git version for installer --- find_package(Git QUIET) if(GIT_FOUND) execute_process( COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) endif() if(NOT GIT_VERSION) set(GIT_VERSION "v0.0.0-dev") endif() message(STATUS "BeyondProximity version: ${GIT_VERSION}") # --- Installer target (requires Inno Setup 6) --- find_program(ISCC_EXECUTABLE NAMES ISCC PATHS "C:/Program Files (x86)/Inno Setup 6" "C:/Program Files/Inno Setup 6" DOC "Inno Setup command-line compiler" ) if(ISCC_EXECUTABLE) set(INSTALLER_OUTPUT_DIR "${CMAKE_BINARY_DIR}/installer") file(MAKE_DIRECTORY ${INSTALLER_OUTPUT_DIR}) add_custom_target(package COMMAND ${ISCC_EXECUTABLE} "/DMyAppVersion=${GIT_VERSION}" "/DDriverBuildDir=${CMAKE_BINARY_DIR}/driver/${TARGET_NAME}" "/DDriverSourceDir=${CMAKE_SOURCE_DIR}/driver/${TARGET_NAME}" "/O${INSTALLER_OUTPUT_DIR}" "/FBeyondProximity-Setup-${GIT_VERSION}" "${CMAKE_SOURCE_DIR}/installer/BeyondProximity.iss" DEPENDS ${DRIVER_NAME} COMMENT "Building installer: BeyondProximity-Setup-${GIT_VERSION}.exe" VERBATIM ) else() message(WARNING "ISCC.exe not found. Install Inno Setup 6 from https://jrsoftware.org/isdl.php to enable the 'package' target.") endif()