|
| 1 | +# cmake Support in QP/C++ |
| 2 | + |
| 3 | +This branch adds comprehensive cmake support to QP/C++ |
| 4 | + |
| 5 | +## Quick Start |
| 6 | + |
| 7 | +create your project with a root `CMakeLists.txt` file, following this blueprint. |
| 8 | +1. copy [qpcpp_sdk_import.cmake](https://github.com/QuantumLeaps/3rd_party/cmake/qpcpp_sdk_import.cmake) into your project. Make sure, it can be found by `cmake` as an included script |
| 9 | +2. Setup your 1<sup>st</sup> `CMakeLists.txt`: |
| 10 | +``` |
| 11 | +# use a recent CMake version |
| 12 | +cmake_minimum_required(VERSION 3.23 FATAL_ERROR) |
| 13 | +cmake_policy(VERSION 3.23...3.28) |
| 14 | +cmake_policy(SET CMP0083 NEW) |
| 15 | +cmake_policy(SET CMP0105 NEW) |
| 16 | +cmake_policy(SET CMP0116 NEW) |
| 17 | +cmake_policy(SET CMP0128 NEW) |
| 18 | +
|
| 19 | +# include general project config & import qpcpp |
| 20 | +set(QPCPP_SDK_PATH ${CMAKE_SOURCE_DIR}/Source/qpcpp-sdk) |
| 21 | +# set(QPCPP_FETCH_FROM_GIT ON) |
| 22 | +# set(QPCPP_FETCH_FROM_GIT_PATH ${CMAKE_SOURCE_DIR}/Source/qpcpp-sdk) |
| 23 | +include(qpcpp_sdk_import) |
| 24 | +
|
| 25 | +# default image/project name is trafficlight |
| 26 | +# Give a special name via -DIMAGE=<image> |
| 27 | +# the main project |
| 28 | +project(myProject |
| 29 | + VERSION "1.0.0"" |
| 30 | + DESCRIPTION "my 1st qpcpp project" |
| 31 | + LANGUAGES C CXX) |
| 32 | +
|
| 33 | +# the project target(s) |
| 34 | +add_executable(qpcppApp main.cpp qpcppApp.cpp) |
| 35 | +
|
| 36 | +include(${QPCPP_SDK_PATH}/qpcpp_sdk_init.cmake) |
| 37 | +set(QPCPP_PROJECT qpcPrj) |
| 38 | +set(QPCPP_CFG_KERNEL QV) |
| 39 | +set(QPCPP_CFG_GUI TRUE) |
| 40 | +set(QPCPP_CFG_PORT win32) |
| 41 | +qpcpp_sdk_init() |
| 42 | +
|
| 43 | +target_link_libraries(qpcppApp PRIVATE qpcpp) |
| 44 | +``` |
| 45 | +3. configure your project with |
| 46 | + `cmake -B Build .` |
| 47 | +4. build |
| 48 | + `cmake --build Build` |
| 49 | + |
| 50 | +## Usage |
| 51 | +### `qpcpp_sdk_import.cmake` |
| 52 | +This file prepares your project for integrating qpcpp. |
| 53 | +Before adding this file to your project with `include(qpcpp_sdk_import)` make sure to set `CMAKE_MODULE_PATH` accordingly. |
| 54 | + |
| 55 | +To configure the integration of qpcpp you can provide information either with cmake variables or via environment variables of the very same names. |
| 56 | + |
| 57 | +* Mandatory variables (only one of the two must be set) |
| 58 | + - `QPCPP_SDK_PATH` - set this variable to point to the full path of an already installed qpcpp instance. |
| 59 | + - `QPCPP_FETCH_FROM_GIT` - set this variable to ON or TRUE, if no pre-installed qpcpp directory exists. QPCPP |
| 60 | + will then be downloaded from git automatically. The download URL is pre-defined in `qpcpp_sdk_import.cmake` |
| 61 | +* Optional variables |
| 62 | + - `QPCPP_FETCH_FROM_GIT_PATH` - set this variable to download qpcpp from git (`QPCPP_FETCH_FROM_GIT`) into the |
| 63 | + specified directory |
| 64 | + - `QPCPP_URL`- set this variable to the URL to download qpcpp from. This must point to a remote git |
| 65 | + repository |
| 66 | + |
| 67 | +### `qpcpp_sdk_init.cmake` |
| 68 | +This file is situated in the root directory of qpcpp. It performs a pre-initialization of the qpcpp package and provides the function `qpcpp_sdk_init`. Call this function from your project's `CMakeLists.txt` file to perform the final integration of qpcpp into your project. To configure qpcpp to your projects requirements set these variables before calling `qpcpp_sdk_init()` |
| 69 | + |
| 70 | +* `QPCPP_CFG_KERNEL` - STRING: set this variable to the QPCPP kernel for your project. Valid values are QV, QK or QXK. Default: QV |
| 71 | +* `QPCPP_CFG_PORT` - STRING: set this variable to reflect the target platform of your project. Default: host system. Valid values are: |
| 72 | + + `arm-cm`, `arm-cr` - Arm CortexM or CortexR micro controllers. Tested with GNU cross compiler environments. |
| 73 | + + `freertos`, `esp-idf`, `emb-os`, `threadx`, `uc-os2` - real time OS |
| 74 | + + `msp430`, `pic32` - TI MSP430 or PIC32 micro controllers |
| 75 | + + `riscv`- Risc V µC |
| 76 | + + `qep-only`, `qube` - test environments |
| 77 | + + `win32`, `posix` - host environments MS Windows, Linux (Posix compatible systems) |
| 78 | +* `QPCPP-CFG-GUI` - BOOL: set this Boolean variable to ON/TRUE, if GUI support (win32) shall be compiled in. Default: OFF |
| 79 | +* `QPCPP_CFG_UNIT_TEST` - BOOL: set this to ON/TRUE to support qutest, if build configuration `Spy` is active. Default: OFF |
| 80 | +* `QPCPP_CFG_VERBOSE` - BOOL: set this to enable more verbosity in message output. Default: OFF |
| 81 | + |
| 82 | +### General usage hints |
| 83 | +1. Set `QPCPP_SDK_PATH` or `QPCPP_FETCH_FROM_GIT` either in your `CMakeLists.txt` file or as an environment variable. |
| 84 | +2. Optionally set the configuration variable(s) |
| 85 | +3. Include `qpcpp_sdk_import` __before__ defining the cmake `project()` |
| 86 | +4. Define the project |
| 87 | +5. Define the cmake target (executable or library) |
| 88 | +6. Include `qpcpp_sdk_init.cmake` |
| 89 | +7. configure the qpc SDK |
| 90 | +8. call `qpcpp_sdk_init` |
| 91 | +9. Add the qpcpp library to your cmake target: |
| 92 | + `target_link_libraries(<target>> PRIVATE qpcpp)` |
| 93 | + |
| 94 | +Generate and build your cmake project |
| 95 | + |
| 96 | +## Generation and building hints |
| 97 | +* Generate with configuration support |
| 98 | + The recommendation is to use a multi-configuration cmake generator like `"Ninja Multi-Config"` and set the cmake variable `CMAKE_CONFIGURATION_TYPES` to `"Debug;Release;Spy"`. |
| 99 | + Then you can build with `cmake --build <build directory> --config=<config>. |
| 100 | +* Use `CMakePresets.json` |
| 101 | + Define the build configurations for your projects in a presets definitions file. |
| 102 | + Refer to the [CMakePresets.json manual](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html) for further details. |
| 103 | + Then you generate with `cmake --preset=<preset> .` from your project directory. The build then can be started with `cmake --build --preset=<preset>`. |
| 104 | + |
| 105 | +### QPC configurations support |
| 106 | +Many `qpcpp` examples provide 3 build configurations: |
| 107 | +* `Debug` - build with debug support and debug symbols. Most optimizations are turned off |
| 108 | +* `Release` - build without debug support. Activate optimizations instead |
| 109 | +* `Spy` - build like `Debug`. Additionally activate support for `QSpy`. |
| 110 | + |
| 111 | +These configurations are also supported by qpcpp with cmake. Different possibilities exist to activate those. |
| 112 | + |
| 113 | +### `qp_config.h` support |
| 114 | +Some build configurations require the inclusion of `qp_config.h`. To achieve this, the QPC macro `QP_CONFIG` should be set, when compiling the |
| 115 | +`qpcpp` source files. The include search paths also needs to be set accordingly in order for the preprocessor to be able to find the correct include |
| 116 | +file. |
| 117 | + |
| 118 | +As `qp_config.hpp` is a project related file, which - in most cases - resides outside the `qpcpp` source code tree, the decision is to handle the |
| 119 | +above mentioned topic within the root project's `CMakeLists.txt` file instead of integrating this topic into a rather complicated configuration |
| 120 | +of `qpcpp` itself. |
| 121 | + |
| 122 | +An example can be found in the [cmake dpp example](https://github.com/QuantumLeaps/qpcpp-examples/tree/main/posix-win32-cmake/dpp). Have a look into |
| 123 | +the example's [CMakeLists.txt](https://github.com/QuantumLeaps/qpcpp-examples/blob/main/posix-win32-cmake/dpp/CMakeLists.txt). |
| 124 | + |
| 125 | +You will find the reference to the `qpc` library, followed by the project's specific setup for `qp_config.h` like this: |
| 126 | +``` |
| 127 | +# set up qpcpp library |
| 128 | +target_link_libraries(dpp |
| 129 | + PRIVATE |
| 130 | + qpcpp |
| 131 | +) |
| 132 | +# should a 'qp_config.h' configuration file be used and is it available |
| 133 | +# edit the HINTS in the 'find_file()' call according to your project settings |
| 134 | +if(USE_QP_CONFIG) |
| 135 | + find_file(QP_CONFIG qp_config.h HINTS ${CMAKE_CURRENT_SOURCE_DIR}) # try to identify 'qp_config.h' |
| 136 | + if(QP_CONFIG) # found 'qp_config.h' |
| 137 | + cmake_path(GET QP_CONFIG PARENT_PATH QP_CONFIG_DIR) # extract the path from the FQFN |
| 138 | + target_compile_definitions(qpcpp # add -DQP_CONFIG to the qpcpp build |
| 139 | + PUBLIC |
| 140 | + QP_CONFIG |
| 141 | + ) |
| 142 | + target_include_directories(qpcpp # add the path to 'qp_config.h' to the list of include paths for qpcpp |
| 143 | + PUBLIC |
| 144 | + ${QP_CONFIG_DIR} |
| 145 | + ) |
| 146 | + else() # 'qp_config.h' requested but not find - try to configure and build anyways |
| 147 | + message(WARNING "File 'qp_config.h' not found!") |
| 148 | + endif() |
| 149 | +endif() |
| 150 | +``` |
| 151 | + |
| 152 | +### Multi configuration generators |
| 153 | +The most easy way to make use of the different configurations is to use a multi config generator like `Ninja Multi-Config` or `MS Visual Studio`. |
| 154 | +Using one of such generators enables to generate the build system using `cmake` and afterwards simply selecting the desired build configuration like |
| 155 | +`cmake --build <Build Directory> --config=<Debug|Release|Spy>` |
| 156 | + |
| 157 | +To support this, the `cmake` variables |
| 158 | +* `CMAKE_C_FLAGS_<CONFIGURATION>` |
| 159 | +* `CMAKE_CXX_FLAGS_<CONFIGURATION>` |
| 160 | +* `CMAKE_ASM_FLAGS_<CONFIGURATION>` |
| 161 | +* `CMAKE_EXE_LINKER_FLAGS_<CONFIGURATION>` |
| 162 | + |
| 163 | +have to be set for all configurations. The desired place to hold these settings is the `toolchain` file of the compilation toolchain in use. |
| 164 | +If no `toolchain` file is used, the `cmake` default configuration provides settings for the `Debug` and `Release` configuration fot the host |
| 165 | +compiler setup. The `Spy` configuration will be added by the qpcpp `CMakeLists.txt` file. |
| 166 | + |
| 167 | +### Single configuration generators |
| 168 | +For single configuration generators like `Makefile` or `Ninja`, specific build configurations need to configured. One for each configuration. |
| 169 | +When generationg the build system, set the `cmake` variable `CMAKE_BUILD_TYPE` to the desired configuration (`Debug`, `Release` or `Spy`). |
| 170 | + |
| 171 | +Everything said above concerning the `CMAKE_<LANG>_FLAGS_<CONFIGURATION>` variables, also applies here. |
0 commit comments