|
| 1 | +# Building HIDAPI using CMake |
| 2 | + |
| 3 | +To build HIDAPI with CMake, it has to be [installed](#installing-cmake)/available in the system. |
| 4 | + |
| 5 | +Make sure you've checked [prerequisites](BUILD.md#prerequisites) and installed all required dependencies. |
| 6 | + |
| 7 | +HIDAPI CMake build system allows you to build HIDAPI in two generally different ways: |
| 8 | +1) As a [standalone package/library](#standalone-package-build); |
| 9 | +2) As [part of a larger CMake project](#hidapi-as-a-subdirectory). |
| 10 | + |
| 11 | +**TL;DR**: if you're experienced developer and have been working with CMake projects or have been written some of your own - |
| 12 | +most of this document may not be of interest for you; just check variables names, its default values and the target names. |
| 13 | + |
| 14 | +## Installing CMake |
| 15 | + |
| 16 | +CMake can be installed either using your system's package manager, |
| 17 | +or by downloading an installer/prebuilt version from the [official website](https://cmake.org/download/). |
| 18 | + |
| 19 | +On most \*nix systems, the prefered way to install CMake is via package manager, |
| 20 | +e.g. `sudo apt install cmake`. |
| 21 | + |
| 22 | +On Windows CMake could be provided by your development environment (e.g. by Visual Studio Installer or MinGW installer), |
| 23 | +or you may install it system-wise using the installer from the official website. |
| 24 | + |
| 25 | +On macOS CMake may be installed by Homebrew/MacPorts or using the installer from the official website. |
| 26 | + |
| 27 | +## Standalone package build |
| 28 | + |
| 29 | +To build HIDAPI as a standalone package, you follow [general steps](https://cmake.org/runningcmake/) of building any CMake project. |
| 30 | + |
| 31 | +An example of building HIDAPI with CMake: |
| 32 | +```sh |
| 33 | +# precondition: create a <build dir> somewhere on the filesystem (preferably outside of the HIDAPI source) |
| 34 | +# this is the place where all intermediate/build files are going to be located |
| 35 | +cd <build dir> |
| 36 | +# configure the build |
| 37 | +cmake <HIDAPI source dir> |
| 38 | +# build it! |
| 39 | +cmake --build . |
| 40 | +# install library; by default installs into /usr/local/ |
| 41 | +cmake --build . --target install |
| 42 | +# NOTE: you need to run install command as root, to be able to install into /usr/local/ |
| 43 | +``` |
| 44 | +Such invocation will use the default (as per CMake magic) compiler/build environment available in your system. |
| 45 | + |
| 46 | +You may pass some additional CMake variables to control the build configuration as `-D<CMake Variable>=value`. |
| 47 | +E.g.: |
| 48 | +```sh |
| 49 | +# install command now would install things into /usr |
| 50 | +cmake <HIDAPI source dir> -DCMAKE_INSTALL_PREFIX=/usr |
| 51 | +``` |
| 52 | + |
| 53 | +<details> |
| 54 | + <summary>Using a specific CMake generator</summary> |
| 55 | + |
| 56 | +An example of using `Ninja` as a CMake generator: |
| 57 | + |
| 58 | +```sh |
| 59 | +cd <build dir> |
| 60 | +# configure the build |
| 61 | +cmake -GNinja <HIDAPI source dir> |
| 62 | +# we know, that CMake has generated build files for Ninja, |
| 63 | +# so we can use `ninja` directly, instead of `cmake --build .` |
| 64 | +ninja |
| 65 | +# install library |
| 66 | +ninja install |
| 67 | +``` |
| 68 | + |
| 69 | +`-G` here specifies a native build system CMake would generate build files for. |
| 70 | +Check [CMake Documentation](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) for a list of available generators (system-specific). |
| 71 | + |
| 72 | +</details><br> |
| 73 | + |
| 74 | +Some of the [standard](https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html) CMake variables you may want to use to configure a build: |
| 75 | + |
| 76 | +- [`CMAKE_INSTALL_PREFIX`](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html) - prefix where `install` target would install the library(ies); |
| 77 | +- [`CMAKE_BUILD_TYPE`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html) - standard possible values: `Debug`, `Release`, `RelWithDebInfo`, `MinSizeRel`; Defaults to `Release` for HIDAPI, if not specified; |
| 78 | +- [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html) - when set to TRUE, HIDAPI is built as a shared library, otherwise build statically; Defaults to `TRUE` for HIDAPI, if not specified; |
| 79 | + |
| 80 | +<details> |
| 81 | + <summary>macOS-specific variables</summary> |
| 82 | + |
| 83 | + - [`CMAKE_FRAMEWORK`](https://cmake.org/cmake/help/latest/variable/CMAKE_FRAMEWORK.html) - (since CMake 3.15) when set to TRUE, HIDAPI is built as a framework library, otherwise build as a regular static/shared library; Defaults to `FALSE` for HIDAPI, if not specified; |
| 84 | + - [`CMAKE_OSX_DEPLOYMENT_TARGET`](https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_DEPLOYMENT_TARGET.html) - minimum version of the target platform (e.g. macOS or iOS) on which the target binaries are to be deployed; defaults to a maximum supported target platform by currently used XCode/Toolchain; |
| 85 | + |
| 86 | +</details><br> |
| 87 | + |
| 88 | +HIDAPI-specific CMake variables: |
| 89 | + |
| 90 | +- `HIDAPI_BUILD_HIDTEST` - when set to TRUE, build a small test application `hidtest`; |
| 91 | + |
| 92 | +<details> |
| 93 | + <summary>Linux-specific variables</summary> |
| 94 | + |
| 95 | + - `HIDAPI_WITH_HIDRAW` - when set to TRUE, build HIDRAW-based implementation of HIDAPI (`hidapi-hidraw`), otherwise don't build it; defaults to TRUE; |
| 96 | + - `HIDAPI_WITH_LIBUSB` - when set to TRUE, build LIBUSB-based implementation of HIDAPI (`hidapi-libusb`), otherwise don't build it; defaults to TRUE; |
| 97 | + |
| 98 | + **NOTE**: at least one of `HIDAPI_WITH_HIDRAW` or `HIDAPI_WITH_LIBUSB` has to be set to TRUE. |
| 99 | + |
| 100 | +</details><br> |
| 101 | + |
| 102 | +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/)). |
| 103 | + |
| 104 | +_NOTE_: HIDAPI packages built by CMake can be used with `pkg-config`, as if built with [Autotools](BUILD.autotools.md). |
| 105 | + |
| 106 | +### MSVC and Ninja |
| 107 | +It is possible to build a CMake project (including HIDAPI) using MSVC compiler and Ninja (for medium and larger projects it is so much faster than msbuild). |
| 108 | + |
| 109 | +For that: |
| 110 | +1) Open cmd.exe; |
| 111 | +2) Setup MSVC build environment variables, e.g.: `vcvarsall.bat x64`, where: |
| 112 | + - `vcvarsall.bat` is an environment setup script of your MSVC toolchain installation;<br>For MSVC 2019 Community edition it is located at: `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\`; |
| 113 | + - `x64` -a target architecture to build; |
| 114 | +3) Follow general build steps, and use `Ninja` as a generator. |
| 115 | + |
| 116 | +### Using HIDAPI in a CMake project |
| 117 | + |
| 118 | +When HIDAPI is used as a standalone package (either installed into the system or built manually and installed elsewhere), the simplest way to use it is as showed in the example: |
| 119 | + |
| 120 | +```cmake |
| 121 | +project(my_application) |
| 122 | +
|
| 123 | +add_executable(my_application main.c) |
| 124 | +
|
| 125 | +find_package(hidapi REQUIRED) |
| 126 | +target_link_libraries(my_application PRIVATE hidapi::hidapi) |
| 127 | +``` |
| 128 | + |
| 129 | +If HIDAPI isn't installed in your system, or `find_package` cannot find HIDAPI by default for any other reasons, |
| 130 | +the recommended way manually specify which HIDAPI package to use is via `hidapi_ROOT` CMake variable, e.g.: |
| 131 | +`-Dhidapi_ROOT=<path to HIDAPI installation prefix>`. |
| 132 | + |
| 133 | +_NOTE_: usage of `hidapi_ROOT` is only possible (and recommended) with CMake 3.12 and higher. For older versions of CMake you'd need to specify [`CMAKE_PREFIX_PATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html#variable:CMAKE_PREFIX_PATH) instead. |
| 134 | + |
| 135 | +Check with [`find_package`](https://cmake.org/cmake/help/latest/command/find_package.html) documentation if you need more details. |
| 136 | + |
| 137 | +Available CMake targets after successful `find_package(hidapi)`: |
| 138 | +- `hidapi::hidapi` - indented to be used in most cases; |
| 139 | +- `hidapi::include` - if you need only to include `<hidapi.h>` but not link against the library; |
| 140 | +- `hidapi::winapi` - same as `hidapi::hidapi` on Windows; available only on Windows; |
| 141 | +- `hidapi::darwin` - same as `hidapi::hidapi` on macOS; available only on macOS; |
| 142 | +- `hidapi::libusb` - available when libusb backend is used/available; |
| 143 | +- `hidapi::hidraw` - available when hidraw backend is used/available on Linux; |
| 144 | + |
| 145 | +**NOTE**: on Linux often both `hidapi::libusb` and `hidapi::hidraw` backends are available; in that case `hidapi::hidapi` is an alias for **`hidapi::hidraw`**. The motivation is that `hidraw` backend is a native Linux kernel implementation of HID protocol, and supports various HID devices (USB, Bluetooth, I2C, etc.). If `hidraw` backend isn't built at all (`hidapi::libusb` is the only target) - `hidapi::hidapi` is an alias for `hidapi::libusb`. |
| 146 | +If you're developing a cross-platform application and you are sure you need to use `libusb` backend on Linux, the simple way to achieve this is: |
| 147 | +```cmake |
| 148 | +if(TARGET hidapi::libusb) |
| 149 | + target_link_libraries(my_project PRIVATE hidapi::libusb) |
| 150 | +else() |
| 151 | + target_link_libraries(my_project PRIVATE hidapi::hidapi) |
| 152 | +endif() |
| 153 | +``` |
| 154 | + |
| 155 | +## HIDAPI as a subdirectory |
| 156 | + |
| 157 | +HIDAPI can be easily used as a subdirectory of a larger CMake project: |
| 158 | +```cmake |
| 159 | +# root CMakeLists.txt |
| 160 | +cmake_minimum_required(VERSION 3.4.3 FATAL_ERROR) |
| 161 | +
|
| 162 | +add_subdirectory(hidapi) |
| 163 | +add_subdirectory(my_application) |
| 164 | +
|
| 165 | +# my_application/CMakeLists.txt |
| 166 | +project(my_application) |
| 167 | +
|
| 168 | +add_executable(my_application main.c) |
| 169 | +
|
| 170 | +# NOTE: no `find_package` is required, since HIDAPI targets are already a part of the project tree |
| 171 | +target_link_libraries(my_application PRIVATE hidapi::hidapi) |
| 172 | +``` |
| 173 | +Lets call this "larger project" a "host project". |
| 174 | + |
| 175 | +All of the variables described in [standalone build](#standalone-package-build) section can be used to control HIDAPI build in case of a subdirectory, e.g.: |
| 176 | +```cmake |
| 177 | +set(HIDAPI_WITH_LIBUSB FALSE) # surely will be used only on Linux |
| 178 | +set(BUILD_SHARED_LIBS FALSE) # HIDAPI as static library on all platforms |
| 179 | +add_subdirectory(hidapi) |
| 180 | +``` |
| 181 | + |
| 182 | +There is two important differences in the behavior of HIDAPI CMake build system when CMake is built as standalone package vs subdirectory build: |
| 183 | + |
| 184 | +1) In _standalone build_ a number of standard and HIDAPI-specific variables are marked as _cache variables_ or _options_. |
| 185 | +This is done for convenience: when you're building HIDAPI as a standalone package and using tools like `cmake-gui` - those are highlighted as variables that can be changed and has some short description/documentation. E.g.: |
| 186 | +<br> |
| 187 | +E.g.2:<br> |
| 188 | +<br> |
| 189 | +When HIDAPI is built as a _subdirectory_ - **_none of the variables are marked for cache or as options_** by HIDAPI. |
| 190 | +This is done to let the host project's developer decide what is important (what needs to be highlighted) and what's not. |
| 191 | + |
| 192 | +2) The default behavior/default value for some of the variables is a bit different: |
| 193 | + - by default, none of HIDAPI targets are [installed](https://cmake.org/cmake/help/latest/command/install.html); if required, HIDAPI targets can be installed by host project _after_ including HIDAPI subdirectory (requires CMake 3.13 or later); **or**, the default installation can be enabled by setting `HIDAPI_INSTALL_TARGETS` variable _before_ including HIDAPI subdirectory. |
| 194 | + HIDAPI uses [GNUInstallDirs](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html) to specify install locations. Variables like `CMAKE_INSTALL_LIBDIR` can be used to control HIDAPI's installation locations. E.g.: |
| 195 | + ```cmake |
| 196 | + # enable the installation if you need it |
| 197 | + set(HIDAPI_INSTALL_TARGETS ON) |
| 198 | + # (optionally) change default installation locations if it makes sense for your target platform, etc. |
| 199 | + set(CMAKE_INSTALL_LIBDIR "lib64") |
| 200 | + add_subdirectory(hidapi) |
| 201 | + ``` |
| 202 | + - HIDAPI prints its version during the configuration when built as a standalone package; to enable this for subdirectory builds - set `HIDAPI_PRINT_VERSION` to TRUE before including HIDAPI; |
| 203 | + |
| 204 | +Available CMake targets after `add_subdirectory(hidapi)` _are the same as in case of [standalone build](#standalone-package-build)_, and a few additional ones: |
| 205 | +- `hidapi_include` - the interface library; `hidapi::hidapi` is an alias of it; |
| 206 | +- `hidapi_winapi` - library target on Windows; `hidapi::winapi` is an alias of it; |
| 207 | +- `hidapi_darwin` - library target on macOS; `hidapi::darwin` is an alias of it; |
| 208 | +- `hidapi_libusb` - library target for libusb backend; `hidapi::libusb` is an alias of it; |
| 209 | +- `hidapi_hidraw` - library target for hidraw backend; `hidapi::hidraw` is an alias of it; |
| 210 | +- `hidapi-libusb` - an alias of `hidapi_libusb` for compatibility with raw library name; |
| 211 | +- `hidapi-hidraw` - an alias of `hidapi_hidraw` for compatibility with raw library name; |
| 212 | +- `hidapi` - an alias of `hidapi_winapi` or `hidapi_darwin` on Windows or macOS respectfully. |
| 213 | + |
| 214 | +Advanced: |
| 215 | +- Why would I need additional targets described in this section above, if I already have alias targets compatible with `find_package`? |
| 216 | + - an example: |
| 217 | + ```cmake |
| 218 | + add_subdirectory(hidapi) |
| 219 | + if(TARGET hidapi_libusb) |
| 220 | + # see libusb/hid.c for usage of `NO_ICONV` |
| 221 | + target_compile_definitions(hidapi_libusb PRIVATE NO_ICONV) |
| 222 | + endif() |
| 223 | + ``` |
0 commit comments