diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 910edcaf..545f1b37 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -3,121 +3,122 @@ name: Build and test OpenVR driver on: [ push, pull_request, workflow_dispatch ] jobs: + setup-matrix: + name: Setup build matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.setup-matrix.outputs.matrix }} + steps: + - id: setup-matrix + shell: bash + run: | + cat < matrix.json + { + "include": [ + {"os": "windows-2025", "name": "win64"}, + {"os": "ubuntu-latest", "name": "x64-linux"}, + {"os": "ubuntu-24.04-arm", "name": "aarch64-linux"} + ] + } + EOF + echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT + build: name: Build (${{ matrix.os }}) + needs: [setup-matrix] runs-on: ${{ matrix.os }} strategy: fail-fast: false - matrix: - os: [windows-latest, ubuntu-latest, ubuntu-24.04-arm] - include: - - os: windows-latest - triplet: x64-windows-static-md - name: win64 - target: ALL_BUILD - release_dir: Release # dir of driver binaries within env.CMAKE_BUILD_DIR, VS multi-config uses / subfolder - - os: ubuntu-latest - triplet: x64-linux - name: x64-linux - target: all - release_dir: "" # makefile single config won't have subfolder - - os: ubuntu-24.04-arm - triplet: arm64-linux - name: aarch64-linux - target: all - release_dir: "" # makefile single config won't have subfolder + matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} env: # Indicates the CMake build directory where project files and binaries are being produced. CMAKE_BUILD_DIR: ${{ github.workspace }}/build - # Indicates the location of the vcpkg as a Git submodule of the project repository. - VCPKG_ROOT: ${{ github.workspace }}/vcpkg steps: - uses: actions/checkout@v6 with: submodules: true - - uses: lukka/get-cmake@latest - - name: Get submodule commit hashes - id: submodule_hashes - run: git submodule foreach --recursive git rev-parse HEAD > submodule_hashes.txt - - - name: Restore vcpkg and its artifacts + id: get-submodule-commit-hashes + run: git submodule foreach --recursive git rev-parse HEAD > submodule-hashes.txt + + - name: Generate cache key + id: gen-cache-key + shell: bash + run: | + echo "cache-key=${{ matrix.os }}-${{ hashFiles('submodule-hashes.txt') }}-${{ hashFiles('CMakeLists.txt') }}" >> $GITHUB_OUTPUT + + - name: Set up CPM cache + id: setup-cpm-cache uses: actions/cache@v5 with: - # The first path is where vcpkg generates artifacts while consuming the vcpkg.json manifest file. - # The second path is the location of vcpkg (it contains the vcpkg executable and data files). - # The other paths starting with "!" are exclusions: they contain termporary files generated during the build of the installed packages. - path: | - ${{ env.CMAKE_BUILD_DIR }}/vcpkg_installed/ - ${{ env.VCPKG_ROOT }} - !${{ env.VCPKG_ROOT }}/buildtrees - !${{ env.VCPKG_ROOT }}/packages - !${{ env.VCPKG_ROOT }}/downloads - # The key is composed in a way that it gets properly invalidated: this must happen whenever vcpkg/submodule Git commit id changes, or the list of packages changes. In this case a cache miss must happen and a new entry with a new key with be pushed to GitHub the cache service. - # The key includes: hash of the vcpkg.json file, the hash of the vcpkg Git commit id, and the used vcpkg's triplet. The vcpkg's commit id would suffice, but computing an hash out it does not harm. - # Note: given a key, the cache content is immutable. If a cache entry has been created improperly, in order the recreate the right content the key must be changed as well, and it must be brand new (i.e. not existing already). - key: ${{ matrix.triplet }}-${{ hashFiles( '**/vcpkg.json', '**/CMakeLists.txt' ) }}-${{ hashFiles( 'submodule_hashes.txt' )}} + path: ~/cpm-cache + key: cpm-${{ steps.gen-cache-key.outputs.cache-key }} + restore-keys: | + cpm-${{ matrix.os }}- - - if: matrix.os == 'windows-latest' - name: Set up vcpkg for Windows - run: ${{ env.VCPKG_ROOT }}/bootstrap-vcpkg.bat - - - if: matrix.os != 'windows-latest' - name: Set up vcpkg for Unix - run: ${{ env.VCPKG_ROOT }}/bootstrap-vcpkg.sh - - - name: Configure CMake - run: cmake -S "${{github.workspace}}" -B "${{env.CMAKE_BUILD_DIR}}" -DVCPKG_TARGET_TRIPLET=${{matrix.triplet}} -DCMAKE_BUILD_TYPE=Release - - - name: Build - run: cmake --build "${{env.CMAKE_BUILD_DIR}}" --config Release --target "${{ matrix.target }}" -j 6 -- + - uses: hendrikmuhs/ccache-action@v1.2 + id: setup-ccache + with: + key: ccache-${{ steps.gen-cache-key.outputs.cache-key }} + restore-keys: | + ccache-${{ matrix.os }}- + + - if: matrix.os == 'windows-2025' + name: Configure and build on Windows + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + cmake -S "${{ github.workspace }}" -B "${{ env.CMAKE_BUILD_DIR }}" -G Ninja ^ + -DCPM_SOURCE_CACHE=%USERPROFILE%\cpm-cache ^ + -DCMAKE_C_COMPILER_LAUNCHER=ccache ^ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ^ + -DSLIMEVR_BUILD_TESTS=ON ^ + -DCMAKE_BUILD_TYPE=Release + cmake --build "${{ env.CMAKE_BUILD_DIR }}" --config Release -j6 + + - if: matrix.os != 'windows-2025' + name: Configure and build on Unix + run: | + cmake -S "${{ github.workspace }}" -B "${{ env.CMAKE_BUILD_DIR }}" -G Ninja \ + -DCPM_SOURCE_CACHE=~/cpm-cache \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DSLIMEVR_BUILD_TESTS=ON \ + -DCMAKE_BUILD_TYPE=Release + cmake --build "${{ env.CMAKE_BUILD_DIR }}" --config Release -j6 - name: Upload driver uses: actions/upload-artifact@v7 with: name: slimevr-openvr-driver-${{ matrix.name }} - path: ${{ env.CMAKE_BUILD_DIR }}/${{ matrix.release_dir }}/driver + path: ${{ env.CMAKE_BUILD_DIR }}/driver - name: Upload tests uses: actions/upload-artifact@v7 with: name: tests-${{ matrix.name }} - path: ${{ env.CMAKE_BUILD_DIR }}/${{ matrix.release_dir }}/tests* + path: ${{ env.CMAKE_BUILD_DIR }}/tests* test: name: Run tests (${{ matrix.os }}) - needs: build - runs-on: ${{ matrix.os }} + needs: [setup-matrix, build] strategy: fail-fast: false - matrix: - os: [windows-latest, ubuntu-latest, ubuntu-24.04-arm] - include: - - os: windows-latest - triplet: x64-windows-static-md - name: win64 - target: ALL_BUILD - - os: ubuntu-latest - triplet: x64-linux - name: x64-linux - target: all - - os: ubuntu-24.04-arm - triplet: arm64-linux - name: aarch64-linux - target: all + matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} + runs-on: ${{ matrix.os }} steps: - name: Download build artifact uses: actions/download-artifact@v8 with: name: tests-${{ matrix.name }} path: ${{ github.workspace }} - - if: matrix.os == 'windows-latest' + - if: matrix.os == 'windows-2025' name: Run tests on Windows working-directory: ${{ github.workspace }}/ run: .\tests.exe - - if: matrix.os != 'windows-latest' + - if: matrix.os != 'windows-2025' name: Run tests on Unix working-directory: ${{ github.workspace }}/ run: chmod +x ./tests && ./tests diff --git a/.gitmodules b/.gitmodules index df7de3c3..bf5392b9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "libraries/linalg"] path = libraries/linalg url = https://github.com/sgorsten/linalg.git -[submodule "vcpkg"] - path = vcpkg - url = https://github.com/Microsoft/vcpkg.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 89b57717..477081eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,42 +1,23 @@ -cmake_minimum_required(VERSION 3.8.0) +cmake_minimum_required(VERSION 3.19) -#if (NOT DEFINED VCPKG_TARGET_TRIPLET) - if(WIN32) - set(VCPKG_TARGET_TRIPLET "x64-windows-static-md") - endif() -#endif() - -set (CMAKE_CXX_STANDARD 20) +# PIE is required +include(CheckPIESupported) +check_pie_supported() -# If the toolchain is already defined, do not attempt to find it -if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) - # If the VCPKG_ROOT environment variable is not defined, try to automatically define it from AppData/home - if(NOT DEFINED ENV{VCPKG_ROOT}) - if(WIN32) - file(READ "$ENV{LOCALAPPDATA}/vcpkg/vcpkg.path.txt" VCPKG_ROOT) - elseif(UNIX) - file(READ "$ENV{HOME}/.vcpkg/vcpkg.path.txt" VCPKG_ROOT) - endif() - - set(VCPKG_PATH "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") - else() - set(VCPKG_PATH "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") - endif() - - if(EXISTS "${VCPKG_PATH}") - message("vcpkg CMake toolchain was found at \"${VCPKG_PATH}\"") - set(CMAKE_TOOLCHAIN_FILE "${VCPKG_PATH}") - else() - message(FATAL_ERROR "vcpkg could not be found") - endif() -endif() +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project(SlimeVR-OpenVR-Driver VERSION 0.2.0) set_property(GLOBAL PROPERTY USE_FOLDERS ON) set(DRIVER_NAME "slimevr") -include(CTest) -enable_testing() +option(SLIMEVR_BUILD_TESTS "Build tests" OFF) + +if (SLIMEVR_BUILD_TESTS) + include(CTest) + enable_testing() +endif() # OpenVR set(OPENVR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/openvr/headers") @@ -62,22 +43,24 @@ elseif(APPLE) set(PLATFORM_NAME "osx") endif() -# Protobuf -# Installation: -# Please refer to this readme to install protobuf in your system: https://github.com/protocolbuffers/protobuf/blob/master/src/README.md -# WARNING: CLang has an arror building protobuf messages, use MSVC 2019 -set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "") -find_package(Protobuf CONFIG REQUIRED) -protobuf_generate_cpp(PROTO_SRC PROTO_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/bridge/ProtobufMessages.proto") -SET_SOURCE_FILES_PROPERTIES(${PROTO_SRC} ${PROTO_INCL} PROPERTIES GENERATED TRUE) +include(cmake/CPM.cmake) -find_package(simdjson CONFIG REQUIRED) - -# libuv -find_package(uvw CONFIG REQUIRED) +CPMAddPackage(URI "gh:protocolbuffers/protobuf@31.1" + OPTIONS "protobuf_BUILD_TESTS OFF" "protobuf_MSVC_STATIC_RUNTIME OFF") +CPMAddPackage(URI "gh:simdjson/simdjson@4.6.4") +CPMAddPackage(URI "gh:libuv/libuv@1.52.1") +CPMAddPackage(URI "gh:skypjack/uvw#bf9c298ea6598e78913c6cd186211412ddac04d6") +if (SLIMEVR_BUILD_TESTS) + CPMAddPackage(URI "gh:catchorg/Catch2@3.15.0") +endif() -# Catch2 -find_package(Catch2 3 REQUIRED) +include("${protobuf_SOURCE_DIR}/cmake/protobuf-generate.cmake") +protobuf_generate( + LANGUAGE cpp + PROTOS "${CMAKE_CURRENT_SOURCE_DIR}/src/bridge/ProtobufMessages.proto" + IMPORT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/bridge" + OUT_VAR PROTO_GENERATED_FILES +) # Project set(DEPS_INCLUDES @@ -90,16 +73,17 @@ set(DEPS_LIBS protobuf::libprotobuf protobuf::libprotobuf-lite simdjson::simdjson + libuv::libuv uvw::uvw ) # compile into a static lib file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") file(GLOB_RECURSE HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp") -add_library("${PROJECT_NAME}_static" STATIC ${SOURCES} ${PROTO_HEADER} ${PROTO_SRC}) +add_library("${PROJECT_NAME}_static" STATIC ${SOURCES} ${PROTO_GENERATED_FILES}) target_link_libraries("${PROJECT_NAME}_static" PUBLIC ${DEPS_LIBS}) -set_property(TARGET "${PROJECT_NAME}_static" PROPERTY CXX_STANDARD 20) -include_directories("${PROJECT_NAME}_static" PUBLIC ${DEPS_INCLUDES} ${Protobuf_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) +set_target_properties("${PROJECT_NAME}_static" PROPERTIES CXX_STANDARD 20) +target_include_directories("${PROJECT_NAME}_static" PUBLIC ${DEPS_INCLUDES} ${Protobuf_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) if(UNIX) target_compile_options("${PROJECT_NAME}_static" PRIVATE "-fPIC") target_link_libraries("${PROJECT_NAME}_static" PUBLIC atomic) @@ -107,21 +91,26 @@ endif() # compile driver file(GLOB_RECURSE DRIVER_MAIN "${CMAKE_CURRENT_SOURCE_DIR}/src/DriverFactory.cpp") -add_library("${PROJECT_NAME}" SHARED ${DRIVER_MAIN} ${HEADERS} ${PROTO_HEADER}) +add_library("${PROJECT_NAME}" SHARED ${DRIVER_MAIN} ${HEADERS}) +target_include_directories("${PROJECT_NAME}" PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries("${PROJECT_NAME}" PUBLIC "${PROJECT_NAME}_static") -set_property(TARGET "${PROJECT_NAME}" PROPERTY CXX_STANDARD 20) +set_target_properties("${PROJECT_NAME}" PROPERTIES CXX_STANDARD 20) # compile tests -function(build_tests target_name test_dir) +function(build_tests target_name test_dir executable_name) file(GLOB TESTS "${CMAKE_CURRENT_SOURCE_DIR}/${test_dir}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/${test_dir}/*.hpp") file(GLOB TESTS_COMMON "${CMAKE_CURRENT_SOURCE_DIR}/test/common/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/test/common/*.hpp") add_executable(${target_name} ${TESTS} ${TESTS_COMMON} ${HEADERS} ${PROTO_HEADER}) target_link_libraries(${target_name} PUBLIC "${PROJECT_NAME}_static" Catch2::Catch2WithMain) - set_property(TARGET ${target_name} PROPERTY CXX_STANDARD 20) + set_target_properties(${target_name} PROPERTIES CXX_STANDARD 20 OUTPUT_NAME "${executable_name}") endfunction() -build_tests(tests "test") -build_tests(tests_integration "test/integration") -add_test(NAME tests COMMAND "tests") + +if (SLIMEVR_BUILD_TESTS) + build_tests("${PROJECT_NAME}-Tests" "test" "tests") + build_tests("${PROJECT_NAME}-Tests-Integration" "test/integration" "tests_integration") + add_test(NAME "Driver tests" COMMAND "${PROJECT_NAME}-Tests") + add_test(NAME "Driver tests (with real server)" COMMAND "${PROJECT_NAME}-Tests-Integration") +endif() # IDE Config source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/src" PREFIX "Header Files" FILES ${HEADERS}) diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake new file mode 100644 index 00000000..a4d79344 --- /dev/null +++ b/cmake/CPM.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: MIT +# +# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors + +set(CPM_DOWNLOAD_VERSION 0.42.3) +set(CPM_HASH_SUM "a609e875fd532b067174250f6abbc3dac22fe2d64869783fb1e80bda1625c844") + +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +endif() + +# Expand relative path. This is important if the provided path contains a tilde (~) +get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) + +file(DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} +) + +include(${CPM_DOWNLOAD_LOCATION}) diff --git a/vcpkg b/vcpkg deleted file mode 160000 index 2fa7118f..00000000 --- a/vcpkg +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2fa7118fb2ce0c27ab73e08ab1991f4cb67af880 diff --git a/vcpkg.json b/vcpkg.json deleted file mode 100644 index 7268cbf8..00000000 --- a/vcpkg.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "slimevr-openvr-driver", - "version": "0.2.0", - "dependencies": [ - "protobuf", - "simdjson", - "uvw", - "catch2" - ], - "builtin-baseline": "2fa7118fb2ce0c27ab73e08ab1991f4cb67af880" -}