Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 1 | # |
Imre Kis | 590cd9c | 2020-01-08 16:51:57 +0100 | [diff] [blame] | 2 | # Copyright (c) 2019-2020, Arm Limited. All rights reserved. |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 3 | # |
| 4 | # SPDX-License-Identifier: BSD-3-Clause |
| 5 | # |
| 6 | |
Imre Kis | 1d2fbdd | 2019-12-13 11:42:08 +0100 | [diff] [blame^] | 7 | #[===[.rst: |
| 8 | UnitTest CMake module |
| 9 | --------------------- |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 10 | |
Imre Kis | 1d2fbdd | 2019-12-13 11:42:08 +0100 | [diff] [blame^] | 11 | Control flow |
| 12 | ^^^^^^^^^^^^ |
| 13 | |
| 14 | 1. Setting :cmake:variable:`CLANG_LIBRARY_PATH` |
| 15 | |
| 16 | 1. Using :cmake:variable:`CLANG_LIBRARY_PATH` CMake variable |
| 17 | |
| 18 | 2. Using ``CLANG_LIBRARY_PATH`` environment variable |
| 19 | |
| 20 | 3. Trying to find by ``find_package`` function which calls :cmake:module:`FindLibClang`. |
| 21 | |
| 22 | 2. Checking if ``c-picker`` command is available |
| 23 | |
| 24 | |
| 25 | Variables |
| 26 | ^^^^^^^^^ |
| 27 | |
| 28 | The module sets the following variables while it's checking its prerequisites. |
| 29 | |
| 30 | .. cmake:variable:: CLANG_LIBRARY_PATH |
| 31 | |
| 32 | libclang directory for c-picker |
| 33 | |
| 34 | .. cmake:variable:: CPICKER_COMMAND |
| 35 | |
| 36 | Path of c-picker executable which is part of the c-picker pip package. |
| 37 | |
| 38 | |
| 39 | Functions |
| 40 | ^^^^^^^^^ |
| 41 | |
| 42 | #]===] |
| 43 | |
| 44 | include_guard(DIRECTORY) |
Imre Kis | c625d49 | 2020-02-10 16:36:22 +0100 | [diff] [blame] | 45 | |
| 46 | set(CLANG_LIBRARY_PATH_HELP "libclang directory for c-picker") |
| 47 | |
| 48 | if (DEFINED CLANG_LIBRARY_PATH) |
| 49 | message(STATUS "Using CLANG_LIBRARY_PATH from CMake variable (command line or cache)") |
| 50 | |
| 51 | if (DEFINED ENV{CLANG_LIBRARY_PATH}) |
| 52 | if (NOT (${CLANG_LIBRARY_PATH} STREQUAL $ENV{CLANG_LIBRARY_PATH})) |
| 53 | message(WARNING "Both CLANG_LIBRARY_PATH CMake and environment variables are set but have different values") |
| 54 | endif() |
| 55 | endif() |
| 56 | else() |
| 57 | if (DEFINED ENV{CLANG_LIBRARY_PATH}) |
| 58 | message(STATUS "Setting CLANG_LIBRARY_PATH based on environment variable") |
| 59 | set(CLANG_LIBRARY_PATH $ENV{CLANG_LIBRARY_PATH} CACHE PATH ${CLANG_LIBRARY_PATH_HELP}) |
| 60 | else() |
| 61 | message(STATUS "Setting CLANG_LIBRARY_PATH based on find_package") |
| 62 | find_package(LibClang REQUIRED) |
| 63 | set(CLANG_LIBRARY_PATH ${LibClang_LIBRARY_DIRS} CACHE PATH ${CLANG_LIBRARY_PATH_HELP}) |
| 64 | endif() |
| 65 | endif() |
| 66 | |
| 67 | message(STATUS "CLANG_LIBRARY_PATH has been set to ${CLANG_LIBRARY_PATH}") |
| 68 | |
| 69 | # Checking c-picker |
| 70 | find_program(CPICKER_COMMAND "c-picker") |
| 71 | if (NOT CPICKER_COMMAND) |
| 72 | message(FATAL_ERROR "Please install c-picker using pip") |
| 73 | endif() |
| 74 | |
Imre Kis | 1d2fbdd | 2019-12-13 11:42:08 +0100 | [diff] [blame^] | 75 | #[===[.rst: |
| 76 | .. cmake:command:: unit_test_add_suite |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 77 | |
Imre Kis | 1d2fbdd | 2019-12-13 11:42:08 +0100 | [diff] [blame^] | 78 | .. code-block:: cmake |
| 79 | |
| 80 | unit_test_add_suite( |
| 81 | NAME test_name |
| 82 | SOURCES source_files |
| 83 | INCLUDE_DIRECTORIES include_directories |
| 84 | COMPILE_DEFINITIONS defines |
| 85 | DEPENDS dependencies |
| 86 | ) |
| 87 | |
| 88 | The ``unit_test_add_suite`` CMake function provides a convenient interface for |
| 89 | defining unit test suites. Basically its input is the test source files, include |
| 90 | paths and macro definitions and it internally does all the necessary steps to |
| 91 | have the test binary registered in CTest as a result. |
| 92 | |
| 93 | Control flow: |
| 94 | |
| 95 | 1. Adding new executable named ``NAME`` |
| 96 | |
| 97 | 2. Iterating throught ``SOURCES`` |
| 98 | |
| 99 | 1. If it's a normal source file add to the executable's source list |
| 100 | 2. If it's a YAML file add as a c-picker custom command and add the generated |
| 101 | file to the executable's source list |
| 102 | |
| 103 | 3. Setting include directories |
| 104 | |
| 105 | 4. Setting defines |
| 106 | |
| 107 | 5. Adding extra dependencies of the test build |
| 108 | |
| 109 | 6. Adding executable to the system as a test |
| 110 | |
| 111 | Inputs: |
| 112 | |
| 113 | ``NAME`` |
| 114 | Unique name of the test suite |
| 115 | |
| 116 | ``SOURCES`` (multi, optional) |
| 117 | Source files |
| 118 | |
| 119 | ``INCLUDE_DIRECTORIES`` (multi, optional) |
| 120 | Include directories |
| 121 | |
| 122 | ``COMPILE_DEFINITIONS`` (multi, optional) |
| 123 | Defines |
| 124 | |
| 125 | ``DEPENDS`` (multi, optional) |
| 126 | Extra targets as dependencies of the test build |
| 127 | |
| 128 | Global dependencies: |
| 129 | |
| 130 | ``CPICKER_CACHE_PATH`` |
| 131 | Root directory of the c-picker generated files |
| 132 | |
| 133 | ``UNIT_TEST_COMMON_SOURCES`` |
| 134 | Common source files for every test build |
| 135 | |
| 136 | ``CTest`` |
| 137 | Built-in testing module of CMake |
| 138 | |
| 139 | #]===] |
Imre Kis | 590cd9c | 2020-01-08 16:51:57 +0100 | [diff] [blame] | 140 | function(unit_test_add_suite) |
Imre Kis | c8458e7 | 2020-02-10 16:51:32 +0100 | [diff] [blame] | 141 | set(_OPTIONS_ARGS) |
Imre Kis | 590cd9c | 2020-01-08 16:51:57 +0100 | [diff] [blame] | 142 | set(_ONE_VALUE_ARGS NAME) |
Imre Kis | e32a103 | 2020-01-08 17:53:15 +0100 | [diff] [blame] | 143 | set(_MULTI_VALUE_ARGS SOURCES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS DEPENDS) |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 144 | cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 145 | |
Imre Kis | c46907d | 2019-12-15 00:28:39 +0100 | [diff] [blame] | 146 | if(NOT DEFINED BUILD_TESTING) |
| 147 | message(FATAL_ERROR |
| 148 | "add_unit_test_suite(): " |
| 149 | "CTest module should be included in the root CMakeLists.txt before calling this function.") |
| 150 | endif() |
| 151 | |
Imre Kis | 590cd9c | 2020-01-08 16:51:57 +0100 | [diff] [blame] | 152 | set(TEST_NAME ${_MY_PARAMS_NAME}) |
| 153 | set(TEST_INCLUDE_DIRECTORIES ${_MY_PARAMS_INCLUDE_DIRECTORIES}) |
| 154 | set(TEST_COMPILE_DEFINITIONS ${_MY_PARAMS_COMPILE_DEFINITIONS}) |
Imre Kis | e32a103 | 2020-01-08 17:53:15 +0100 | [diff] [blame] | 155 | set(TEST_DEPENDS ${_MY_PARAMS_DEPENDS}) |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 156 | |
| 157 | add_executable(${TEST_NAME} ${UNIT_TEST_COMMON_SOURCES}) |
| 158 | |
Imre Kis | 590cd9c | 2020-01-08 16:51:57 +0100 | [diff] [blame] | 159 | foreach(TEST_SOURCE ${_MY_PARAMS_SOURCES}) |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 160 | get_filename_component(TEST_SOURCE_EXTENSION ${TEST_SOURCE} EXT) |
| 161 | |
| 162 | if (${TEST_SOURCE_EXTENSION} STREQUAL ".yml") |
| 163 | # Building output file name: tests/a/b/test.yml -> ${CPICKER_CACHE_PATH}/a/b/test.c |
| 164 | get_filename_component(TEST_SOURCE_DIR ${TEST_SOURCE} DIRECTORY) |
| 165 | file(RELATIVE_PATH CPICKER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests ${TEST_SOURCE_DIR}) |
| 166 | get_filename_component(TEST_SOURCE_NAME ${TEST_SOURCE} NAME_WE) |
| 167 | set(CPICKER_OUTPUT ${CPICKER_CACHE_PATH}/${TEST_NAME}/${CPICKER_SOURCE_DIR}/${TEST_SOURCE_NAME}.c) |
| 168 | |
| 169 | # Creating output directory |
| 170 | get_filename_component(OUTPUT_DIRECTORY ${CPICKER_OUTPUT} DIRECTORY) |
| 171 | file(MAKE_DIRECTORY ${OUTPUT_DIRECTORY}) |
| 172 | |
| 173 | # Fetching referenced source files as the dependencies of the generated file |
| 174 | execute_process( |
Imre Kis | c0d4b44 | 2019-12-03 23:52:26 +0100 | [diff] [blame] | 175 | COMMAND |
| 176 | ${CMAKE_COMMAND} -E env CLANG_LIBRARY_PATH=${CLANG_LIBRARY_PATH} |
| 177 | ${CPICKER_COMMAND} --config ${TEST_SOURCE} --root ${TF_A_PATH} --print-dependencies |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 178 | OUTPUT_VARIABLE CPICKER_DEPENDENCIES |
| 179 | ) |
| 180 | |
| 181 | # Adding custom command for invoking c-picker |
| 182 | add_custom_command( |
| 183 | OUTPUT ${CPICKER_OUTPUT} |
Imre Kis | c0d4b44 | 2019-12-03 23:52:26 +0100 | [diff] [blame] | 184 | COMMAND |
| 185 | ${CMAKE_COMMAND} -E env CLANG_LIBRARY_PATH=${CLANG_LIBRARY_PATH} |
| 186 | ${CPICKER_COMMAND} --config ${TEST_SOURCE} --root ${TF_A_PATH} > ${CPICKER_OUTPUT} |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 187 | DEPENDS ${TEST_SOURCE} ${CPICKER_DEPENDENCIES} |
| 188 | COMMENT "Generating c-picker output ${CPICKER_OUTPUT}" |
| 189 | ) |
| 190 | set(TEST_SOURCE ${CPICKER_OUTPUT}) |
| 191 | endif() |
| 192 | |
| 193 | target_sources(${TEST_NAME} PRIVATE ${TEST_SOURCE}) |
| 194 | endforeach() |
| 195 | |
Imre Kis | 590cd9c | 2020-01-08 16:51:57 +0100 | [diff] [blame] | 196 | target_include_directories(${TEST_NAME} PRIVATE ${TEST_INCLUDE_DIRECTORIES}) |
| 197 | target_compile_definitions(${TEST_NAME} PRIVATE ${TEST_COMPILE_DEFINITIONS}) |
Imre Kis | e32a103 | 2020-01-08 17:53:15 +0100 | [diff] [blame] | 198 | if (TEST_DEPENDS) |
| 199 | add_dependencies(${TEST_NAME} ${TEST_DEPENDS}) |
| 200 | endif() |
Imre Kis | ed98e9c | 2019-10-15 16:17:55 +0200 | [diff] [blame] | 201 | add_test(${TEST_NAME} ${TEST_NAME}) |
| 202 | endfunction() |