From 266a2f9ce9ec7844101e805a2399c446d8ad834b Mon Sep 17 00:00:00 2001 From: Matthias Janetschek Date: Wed, 7 Oct 2026 13:29:53 +0200 Subject: [PATCH] Fix the Linux build of the qt6 branch, compile QML to bytecode only - Remove Core5Compat (unused, not part of the Steam Frame's system Qt). - Request GuiPrivate explicitly (required since Qt 6.10 for QRhi); temporary until rendering moves to public API. - Compile QML to bytecode only: C++ generated from QML uses private Qt API that only matches the exact Qt version it was built with. - Pick the OpenVR library per architecture (linux64, linuxarm64, win64) for linking and for the copy next to the binary; RPATH $ORIGIN. - Link libXtst, needed by input_sender_X11.cpp. - Include d3d11.h and handle QRhi::D3D11 only on Windows. - Replace leftover easylogging LOG(INFO) calls with qInfo(). Co-Authored-By: Claude Opus 5.5 --- CMakeLists.txt | 45 +++++++++++++++---- docs/steamframe/PROGRESS.md | 28 ++++++++++++ src/overlaycontroller.cpp | 25 ++++++++--- src/tabcontrollers/ChaperoneTabController.cpp | 2 +- .../MoveCenterTabController.cpp | 3 +- 5 files changed, 86 insertions(+), 17 deletions(-) create mode 100644 docs/steamframe/PROGRESS.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 9893508..ed08717 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,12 @@ set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) #find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core) #find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Gui Multimedia Qml Quick WebSockets Widgets QuickControls2 QuickDialogs2 Svg) #find_package(Qt${QT_VERSION_MAJOR} OPTIONAL_COMPONENTS DBus) -find_package(Qt6 REQUIRED COMPONENTS Gui Multimedia Qml Quick WebSockets Widgets QuickControls2 QuickDialogs2 Svg Qml Core5Compat) +# Core5Compat removed: nothing uses it, and the Steam Frame's system Qt +# doesn't ship it. +# GuiPrivate: QRhi (overlaycontroller.cpp) needs it. Since Qt 6.10 private +# modules must be requested explicitly. Temporary: it goes away when rendering +# switches to public API (docs/steamframe/DESIGN.md, section 3). +find_package(Qt6 REQUIRED COMPONENTS Gui Multimedia Qml Quick WebSockets Widgets QuickControls2 QuickDialogs2 Svg Qml GuiPrivate) find_package(Vulkan REQUIRED) qt_standard_project_setup(REQUIRES 6.8) @@ -246,6 +251,15 @@ qt_add_executable(AdvancedSettings ) #src/res/resources.qrc +# Compile QML to bytecode only, not to C++. C++ generated from QML calls Qt's +# private API (QQmlPrivate::AOTCompiledContext), which only matches the exact +# Qt version it was built with. Bytecode keeps the binary on public API, so it +# runs on another Qt 6 patch release, e.g. the Steam Frame's system Qt. +# Must be set before qt_add_qml_module() reads it. +set_target_properties(AdvancedSettings PROPERTIES + QT_QMLCACHEGEN_ARGUMENTS --only-bytecode +) + qt_add_qml_module(AdvancedSettings URI AdvancedSettings QML_FILES @@ -264,6 +278,12 @@ target_include_directories(AdvancedSettings PUBLIC # Avoid collision between executable name and QML module directory (QTBUG-98568). if(NOT WIN32 AND NOT APPLE) set_property(TARGET AdvancedSettings PROPERTY OUTPUT_NAME AdvancedSettings_app) + # libopenvr_api.so is copied next to the executable (see "openvrApiCopy"); + # $ORIGIN makes the loader look there, in the build tree and in packages. + set_target_properties(AdvancedSettings PROPERTIES + BUILD_RPATH "$ORIGIN" + INSTALL_RPATH "$ORIGIN" + ) endif() target_compile_definitions(AdvancedSettings PRIVATE @@ -282,16 +302,20 @@ target_compile_definitions(AdvancedSettings PRIVATE # NO_DEFAULT_PATH # NO_CMAKE_FIND_ROOT_PATH) +# Directory of the OpenVR library for the target platform. Linux distinguishes +# x86_64 (linux64) from aarch64 (linuxarm64, e.g. the Steam Frame). if (WIN32) - target_link_directories(AdvancedSettings PRIVATE - ${CMAKE_SOURCE_DIR}/third-party/openvr/lib/win64 - ) + set(OPENVR_LIB_DIR ${CMAKE_SOURCE_DIR}/third-party/openvr/lib/win64) +elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)$") + set(OPENVR_LIB_DIR ${CMAKE_SOURCE_DIR}/third-party/openvr/lib/linuxarm64) +else () + set(OPENVR_LIB_DIR ${CMAKE_SOURCE_DIR}/third-party/openvr/lib/linux64) endif () +target_link_directories(AdvancedSettings PRIVATE ${OPENVR_LIB_DIR}) target_link_libraries(AdvancedSettings PRIVATE Qt::Gui - Qt6::Core5Compat - # For QRhi + # For QRhi; temporary, see find_package(Qt6 ...) above. Qt::GuiPrivate Qt::Multimedia Qt::Qml @@ -377,7 +401,7 @@ if (WIN32) else () add_custom_command(TARGET AdvancedSettings POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${CMAKE_SOURCE_DIR}/third-party/openvr/lib/linux64/libopenvr_api.so" "${COPY_DEST_DIR}/libopenvr_api.so" + "${OPENVR_LIB_DIR}/libopenvr_api.so" "${COPY_DEST_DIR}/libopenvr_api.so" ) endif () @@ -430,7 +454,12 @@ elseif (UNIX) src/keyboard_input/input_sender_X11.cpp ) find_package(X11 REQUIRED) - target_link_libraries(AdvancedSettings PRIVATE ${X11_LIBRARIES}) + # input_sender_X11.cpp uses the XTest extension (XTestFakeKeyEvent, + # XTestGrabControl), which lives in its own library. + if (NOT X11_XTest_FOUND) + message(FATAL_ERROR "libXtst (X11 XTest extension) not found") + endif () + target_link_libraries(AdvancedSettings PRIVATE ${X11_LIBRARIES} ${X11_XTest_LIB}) elseif (NOT APPLE AND noX11) target_sources(AdvancedSettings PRIVATE src/keyboard_input/input_sender_dummy.cpp diff --git a/docs/steamframe/PROGRESS.md b/docs/steamframe/PROGRESS.md new file mode 100644 index 0000000..811e9f8 --- /dev/null +++ b/docs/steamframe/PROGRESS.md @@ -0,0 +1,28 @@ +# Steam Frame port: progress + +## Iteration 1 + +### Step 1: build fixes, bytecode-only QML (2026-10-07) + +**Changes:** +- **`CMakeLists.txt`:** + - `Core5Compat` removed (unused, not on the Frame). + - `GuiPrivate` requested explicitly. This is temporary, until step 3 replaces QRhi. + - `QT_QMLCACHEGEN_ARGUMENTS --only-bytecode`. + - OpenVR library directory per architecture (`linux64` / `linuxarm64` / `win64`), for + linking and for the copy next to the binary. + - `RPATH $ORIGIN`. + - `libXtst` linked. +- **`overlaycontroller.cpp`:** `d3d11.h` and `case QRhi::D3D11` only under `_WIN32`. +- **Logging:** 8 active easylogging `LOG(INFO)` calls became `qInfo()` + (`overlaycontroller.cpp` 6, `ChaperoneTabController.cpp` 1, + `MoveCenterTabController.cpp` 1). Commented-out `LOG` lines are left unchanged. +- Only changed lines are formatted (`git clang-format`). + +**Results (x86_64, Arch, Qt 6.11.1, GCC):** +- The build succeeds, with 1463 compiler warnings, as in `qt6`. +- `objdump -T`: 7 `Qt_6_PRIVATE_API` symbols, all `QRhi…` (step 3). The + `QQmlPrivate::AOTCompiledContext` symbols are gone (bytecode-only QML). +- `libopenvr_api.so` is resolved from the binary's directory (`ldd`). +- Not started: without a running SteamVR the start hangs in OpenVR init (expected; tested + on the Frame in step 5). diff --git a/src/overlaycontroller.cpp b/src/overlaycontroller.cpp index b90c208..f13e741 100644 --- a/src/overlaycontroller.cpp +++ b/src/overlaycontroller.cpp @@ -30,7 +30,10 @@ #include #include #include -#include +// Direct3D exists only on Windows. +#ifdef _WIN32 +# include +#endif // application namespace namespace advsettings @@ -521,21 +524,25 @@ void OverlayController::SetWidget( QQuickItem* quickItem, auto ctrlRole = info.second; if ( vr::TrackedDeviceClass_HMD == ctrlRole ) { - LOG(INFO) << "HMD is: " << ovr_system_wrapper::getDeviceName(device); + qInfo() << "HMD is: " + << ovr_system_wrapper::getDeviceName( device ); continue; } if ( vr::TrackedControllerRole_LeftHand == ctrlRole ) { - LOG(INFO) << "Controller (L) is: " << ovr_system_wrapper::getDeviceName(device); + qInfo() << "Controller (L) is: " + << ovr_system_wrapper::getDeviceName( device ); continue; } if ( vr::TrackedControllerRole_RightHand == ctrlRole ) { - LOG(INFO) << "Controller (R) is: " << ovr_system_wrapper::getDeviceName(device); + qInfo() << "Controller (R) is: " + << ovr_system_wrapper::getDeviceName( device ); continue; } } - LOG(INFO)<< "Initilizaion is complete--------------------------------------------------"; + qInfo() << "Initilizaion is " + "complete--------------------------------------------------"; } void OverlayController::OnRenderRequest() @@ -560,6 +567,8 @@ void OverlayController::SetOverlayFromQRhiTexture( QRhiTexture& tex ) vrTex.eColorSpace = vr::ColorSpace_Auto; } break; +// Direct3D exists only on Windows. +#ifdef _WIN32 case QRhi::D3D11: { vrTex.handle = reinterpret_cast( tex.nativeTexture().object ); @@ -568,6 +577,7 @@ void OverlayController::SetOverlayFromQRhiTexture( QRhiTexture& tex ) } break; +#endif #if QT_CONFIG( vulkan ) case QRhi::Vulkan: { @@ -1425,7 +1435,7 @@ void OverlayController::RotateUniverseCenter( // } vr::HmdMatrix34_t curPos; auto calState = vr::VRChaperone()->GetCalibrationState(); - LOG( INFO ) << "Calibration State on Rotate is: " << calState; + qInfo() << "Calibration State on Rotate is: " << calState; if ( universe == vr::TrackingUniverseStanding ) { vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose( @@ -1440,7 +1450,8 @@ void OverlayController::RotateUniverseCenter( { //TODO 8/3/26, will see if this causes issues //should exclusively happen with openxr - LOG(INFO) << "rotating on undefined tracking universe probably openxr"; + qInfo() + << "rotating on undefined tracking universe probably openxr"; vr::VRChaperoneSetup()->GetLiveSeatedZeroPoseToRawTrackingPose(&curPos); } diff --git a/src/tabcontrollers/ChaperoneTabController.cpp b/src/tabcontrollers/ChaperoneTabController.cpp index 710d7a1..c1f3db2 100644 --- a/src/tabcontrollers/ChaperoneTabController.cpp +++ b/src/tabcontrollers/ChaperoneTabController.cpp @@ -1500,7 +1500,7 @@ void ChaperoneTabController::createNewAutosaveProfile() true, true, true ); - LOG(INFO) <<"Chaperone Automatic Chaperone Profile Saved"; + qInfo() << "Chaperone Automatic Chaperone Profile Saved"; } void ChaperoneTabController::applyAutosavedProfile() diff --git a/src/tabcontrollers/MoveCenterTabController.cpp b/src/tabcontrollers/MoveCenterTabController.cpp index 8a802a2..d074978 100644 --- a/src/tabcontrollers/MoveCenterTabController.cpp +++ b/src/tabcontrollers/MoveCenterTabController.cpp @@ -1109,7 +1109,8 @@ void MoveCenterTabController::zeroOffsets() parent->m_chaperoneTabController.createNewAutosaveProfile(); m_initComplete = true; m_chaperoneBasisAcquired = true; - LOG( INFO ) << "Chaperone Initilization Complete, Space Drag Now Enabled"; + qInfo() << "Chaperone Initilization Complete, Space Drag " + "Now Enabled"; } //} // else