blob: d557eb01a28d580814f72f88f21d1b881e8d6180 [file] [log] [blame]
Imre Kised98e9c2019-10-15 16:17:55 +02001#
Imre Kis590cd9c2020-01-08 16:51:57 +01002# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
Imre Kised98e9c2019-10-15 16:17:55 +02003#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6
Imre Kis1d2fbdd2019-12-13 11:42:08 +01007#[===[.rst:
8UnitTest CMake module
9---------------------
Imre Kised98e9c2019-10-15 16:17:55 +020010
Imre Kis1d2fbdd2019-12-13 11:42:08 +010011Control flow
12^^^^^^^^^^^^
13
141. 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
222. Checking if ``c-picker`` command is available
23
24
25Variables
26^^^^^^^^^
27
28The module sets the following variables while it's checking its prerequisites.
29
30.. cmake:variable:: CLANG_LIBRARY_PATH
31
32libclang directory for c-picker
33
34.. cmake:variable:: CPICKER_COMMAND
35
36Path of c-picker executable which is part of the c-picker pip package.
37
38
39Functions
40^^^^^^^^^
41
42#]===]
43
44include_guard(DIRECTORY)
Imre Kisc625d492020-02-10 16:36:22 +010045
46set(CLANG_LIBRARY_PATH_HELP "libclang directory for c-picker")
47
48if (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()
56else()
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()
65endif()
66
67message(STATUS "CLANG_LIBRARY_PATH has been set to ${CLANG_LIBRARY_PATH}")
68
69# Checking c-picker
70find_program(CPICKER_COMMAND "c-picker")
71if (NOT CPICKER_COMMAND)
72 message(FATAL_ERROR "Please install c-picker using pip")
73endif()
74
Imre Kis1d2fbdd2019-12-13 11:42:08 +010075#[===[.rst:
76.. cmake:command:: unit_test_add_suite
Imre Kised98e9c2019-10-15 16:17:55 +020077
Imre Kis1d2fbdd2019-12-13 11:42:08 +010078 .. 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 Kis590cd9c2020-01-08 16:51:57 +0100140function(unit_test_add_suite)
Imre Kisc8458e72020-02-10 16:51:32 +0100141 set(_OPTIONS_ARGS)
Imre Kis590cd9c2020-01-08 16:51:57 +0100142 set(_ONE_VALUE_ARGS NAME)
Imre Kise32a1032020-01-08 17:53:15 +0100143 set(_MULTI_VALUE_ARGS SOURCES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS DEPENDS)
Imre Kised98e9c2019-10-15 16:17:55 +0200144 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
Imre Kised98e9c2019-10-15 16:17:55 +0200145
Imre Kisc46907d2019-12-15 00:28:39 +0100146 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 Kis590cd9c2020-01-08 16:51:57 +0100152 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 Kise32a1032020-01-08 17:53:15 +0100155 set(TEST_DEPENDS ${_MY_PARAMS_DEPENDS})
Imre Kised98e9c2019-10-15 16:17:55 +0200156
157 add_executable(${TEST_NAME} ${UNIT_TEST_COMMON_SOURCES})
158
Imre Kis590cd9c2020-01-08 16:51:57 +0100159 foreach(TEST_SOURCE ${_MY_PARAMS_SOURCES})
Imre Kised98e9c2019-10-15 16:17:55 +0200160 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 Kisc0d4b442019-12-03 23:52:26 +0100175 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 Kised98e9c2019-10-15 16:17:55 +0200178 OUTPUT_VARIABLE CPICKER_DEPENDENCIES
179 )
180
181 # Adding custom command for invoking c-picker
182 add_custom_command(
183 OUTPUT ${CPICKER_OUTPUT}
Imre Kisc0d4b442019-12-03 23:52:26 +0100184 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 Kised98e9c2019-10-15 16:17:55 +0200187 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 Kis590cd9c2020-01-08 16:51:57 +0100196 target_include_directories(${TEST_NAME} PRIVATE ${TEST_INCLUDE_DIRECTORIES})
197 target_compile_definitions(${TEST_NAME} PRIVATE ${TEST_COMPILE_DEFINITIONS})
Imre Kise32a1032020-01-08 17:53:15 +0100198 if (TEST_DEPENDS)
199 add_dependencies(${TEST_NAME} ${TEST_DEPENDS})
200 endif()
Imre Kised98e9c2019-10-15 16:17:55 +0200201 add_test(${TEST_NAME} ${TEST_NAME})
202endfunction()