From 5c5c840a7f37b445f9e0d25fdc11932a28bea13f Mon Sep 17 00:00:00 2001 From: Ihor Dutchak Date: Thu, 21 May 2026 10:49:19 +0300 Subject: [PATCH] cmake: add HIDAPI_BUILD_AS_CXX to compile sources as C++ Add an opt-in CMake variable HIDAPI_BUILD_AS_CXX that, when set to TRUE, attaches LANGUAGE CXX to each backend's C source file so it is compiled with the C++ compiler instead of the C compiler. Useful as a portability check, to confirm hidapi sources remain compatible with consumers that embed them into a C++ translation unit. The variable is intentionally not declared as a CMake option(), so it is not surfaced in cmake-gui or `cmake -L` output. It is documented under "Testing-only variables" in BUILD.cmake.md. Wire it through every backend (linux, libusb, mac, netbsd, windows). For the windows backend, both hid.c and hidapi_descriptor_reconstruct.c are re-tagged. Three small mac/hid.c adjustments are required for Apple Clang to accept the source as C++: - cast CFTypeRef to CFNumberRef at CFNumberGetValue() (C allows implicit void*-to-pointer conversion; C++ does not); - mark BUF_LEN const so the stack buffer is a non-VLA array; - cast calloc()'s return value when assigning to cur_dev->path. CI: enable HIDAPI_BUILD_AS_CXX=ON on the ubuntu-cmake, macos-cmake and windows-cmake jobs to guard against regressions. The MSVC variant also sets CMAKE_CXX_STANDARD=20 so the designated initialisers in the Windows backend compile as ISO C++ (g++ and Clang accept them as a GNU extension in their default mode). Assisted-by: Claude:claude-opus-4.7 --- .github/workflows/builds.yml | 26 ++++++++++++++++++++++++++ BUILD.cmake.md | 7 +++++++ libusb/CMakeLists.txt | 3 +++ linux/CMakeLists.txt | 3 +++ mac/CMakeLists.txt | 3 +++ mac/hid.c | 6 +++--- netbsd/CMakeLists.txt | 3 +++ src/CMakeLists.txt | 6 ++++++ windows/CMakeLists.txt | 3 +++ 9 files changed, 57 insertions(+), 3 deletions(-) diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 83ebe190a..8f61dc3f0 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -90,6 +90,15 @@ jobs: cd build/static_test make install + - name: Check C++ portability build + run: | + rm -rf build/cxx + cmake -B build/cxx -S hidapisrc \ + -DCMAKE_BUILD_TYPE=Release \ + -DHIDAPI_BUILD_AS_CXX=ON \ + "-DCMAKE_CXX_FLAGS=-Wall -Wextra -Werror" + cmake --build build/cxx + - name: Check Meson build run: | meson setup build_meson hidapisrc @@ -154,6 +163,15 @@ jobs: cd build/static_test make install + - name: Check C++ portability build + run: | + rm -rf build/cxx + cmake -B build/cxx -S hidapisrc \ + -DCMAKE_BUILD_TYPE=Release \ + -DHIDAPI_BUILD_AS_CXX=ON \ + "-DCMAKE_CXX_FLAGS=-Wall -Wextra -Werror -Wformat-signedness" + cmake --build build/cxx + - name: Check Meson build run: | meson setup build_meson hidapisrc @@ -206,6 +224,14 @@ jobs: working-directory: build/msvc run: ctest -C RelWithDebInfo --no-compress-output --output-on-failure + - name: Configure CMake MSVC C++ + shell: cmd + run: | + cmake -B build\msvc_cxx -S hidapisrc -DCMAKE_BUILD_TYPE=Release -DHIDAPI_BUILD_AS_CXX=ON -DCMAKE_CXX_STANDARD=20 "-DCMAKE_CXX_FLAGS=%MSVC_COMPILE_FLAGS%" + - name: Build CMake MSVC C++ + working-directory: build/msvc_cxx + run: cmake --build . --config Release + - name: Configure CMake NMake MSVC shell: cmd run: | diff --git a/BUILD.cmake.md b/BUILD.cmake.md index 573f910de..cf500e915 100644 --- a/BUILD.cmake.md +++ b/BUILD.cmake.md @@ -101,6 +101,13 @@ currently this option is only available on Windows, since only Windows backend h
+
+ Testing-only variables + + - `HIDAPI_BUILD_AS_CXX` - when set to TRUE, the HIDAPI C source files are compiled with a C++ compiler instead of a C compiler. Useful to confirm that HIDAPI's sources stay compatible with consumers that include them into a C++ translation unit. Not intended for production builds; defaults to FALSE. + +

+ To see all most-useful CMake variables available for HIDAPI, one of the most convenient ways is too use [`cmake-gui`](https://cmake.org/cmake/help/latest/manual/cmake-gui.1.html) tool ([example](https://cmake.org/runningcmake/)). _NOTE_: HIDAPI packages built by CMake can be used with `pkg-config`, as if built with [Autotools](BUILD.autotools.md). diff --git a/libusb/CMakeLists.txt b/libusb/CMakeLists.txt index 2228bd6c0..62efd3c1e 100644 --- a/libusb/CMakeLists.txt +++ b/libusb/CMakeLists.txt @@ -4,6 +4,9 @@ add_library(hidapi_libusb ${HIDAPI_PUBLIC_HEADERS} hid.c ) +if(HIDAPI_BUILD_AS_CXX) + set_source_files_properties(hid.c PROPERTIES LANGUAGE CXX) +endif() target_link_libraries(hidapi_libusb PUBLIC hidapi_include) if(TARGET usb-1.0) diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index dda5c8176..07251a250 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -2,6 +2,9 @@ add_library(hidapi_hidraw ${HIDAPI_PUBLIC_HEADERS} hid.c ) +if(HIDAPI_BUILD_AS_CXX) + set_source_files_properties(hid.c PROPERTIES LANGUAGE CXX) +endif() target_link_libraries(hidapi_hidraw PUBLIC hidapi_include) find_package(Threads REQUIRED) diff --git a/mac/CMakeLists.txt b/mac/CMakeLists.txt index 8acd649c7..046a6eef4 100644 --- a/mac/CMakeLists.txt +++ b/mac/CMakeLists.txt @@ -4,6 +4,9 @@ add_library(hidapi_darwin ${HIDAPI_PUBLIC_HEADERS} hid.c ) +if(HIDAPI_BUILD_AS_CXX) + set_source_files_properties(hid.c PROPERTIES LANGUAGE CXX) +endif() find_package(Threads REQUIRED) diff --git a/mac/hid.c b/mac/hid.c index a91bc1902..4ef045536 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -339,7 +339,7 @@ static bool try_get_ioregistry_int_property(io_service_t service, CFStringRef pr if (ref) { if (CFGetTypeID(ref) == CFNumberGetTypeID()) { - result = CFNumberGetValue(ref, kCFNumberSInt32Type, out_val); + result = CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, out_val); } CFRelease(ref); @@ -544,7 +544,7 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, { unsigned short dev_vid; unsigned short dev_pid; - int BUF_LEN = 256; + const int BUF_LEN = 256; wchar_t buf[BUF_LEN]; CFTypeRef transport_prop; @@ -586,7 +586,7 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, so for (max) "path" string 'DevSrvsID:18446744073709551615' we would need 9+1+20+1=31 bytes buffer, but allocate 32 for simple alignment */ const size_t path_len = 32; - cur_dev->path = calloc(1, path_len); + cur_dev->path = (char *) calloc(1, path_len); if (cur_dev->path != NULL) { snprintf(cur_dev->path, path_len, "DevSrvsID:%llu", entry_id); } diff --git a/netbsd/CMakeLists.txt b/netbsd/CMakeLists.txt index 9be903c67..e5688f316 100644 --- a/netbsd/CMakeLists.txt +++ b/netbsd/CMakeLists.txt @@ -2,6 +2,9 @@ add_library(hidapi_netbsd ${HIDAPI_PUBLIC_HEADERS} hid.c ) +if(HIDAPI_BUILD_AS_CXX) + set_source_files_properties(hid.c PROPERTIES LANGUAGE CXX) +endif() target_link_libraries(hidapi_netbsd PUBLIC hidapi_include) find_package(Threads REQUIRED) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e663c3fd6..c5f4def97 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,12 @@ endif() if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE) set(CMAKE_POSITION_INDEPENDENT_CODE ON) endif() +if(NOT DEFINED HIDAPI_BUILD_AS_CXX) + set(HIDAPI_BUILD_AS_CXX FALSE) +endif() +if(HIDAPI_BUILD_AS_CXX) + enable_language(CXX) +endif() get_directory_property(IS_EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL) if(IS_EXCLUDE_FROM_ALL) diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index d230c703b..005978366 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -18,6 +18,9 @@ add_library(hidapi_winapi ${HIDAPI_PUBLIC_HEADERS} ${SOURCES} ) +if(HIDAPI_BUILD_AS_CXX) + set_source_files_properties(hid.c hidapi_descriptor_reconstruct.c PROPERTIES LANGUAGE CXX) +endif() target_link_libraries(hidapi_winapi PUBLIC hidapi_include )