1# 2# CMake build system design considerations: 3# 4# - Include directories: 5# + Do not define include directories globally using the include_directories 6# command but rather at the target level using the 7# target_include_directories command. That way, it is easier to guarantee 8# that targets are built using the proper list of include directories. 9# + Use the PUBLIC and PRIVATE keywords to specify the scope of include 10# directories. That way, a target linking to a library (using the 11# target_link_libraries command) inherits from the library PUBLIC include 12# directories and not from the PRIVATE ones. 13# + Note: there is currently one remaining include_directories command in the 14# CMake files. It is related to ZLIB support which is planned to be removed. 15# When the support is removed, the associated include_directories command 16# will be removed as well as this note. 17# - MBEDTLS_TARGET_PREFIX: CMake targets are designed to be alterable by calling 18# CMake in order to avoid target name clashes, via the use of 19# MBEDTLS_TARGET_PREFIX. The value of this variable is prefixed to the 20# mbedtls, mbedx509, mbedcrypto and apidoc targets. 21# 22 23cmake_minimum_required(VERSION 2.8.12) 24 25# https://cmake.org/cmake/help/latest/policy/CMP0011.html 26# Setting this policy is required in CMake >= 3.18.0, otherwise a warning is generated. The OLD 27# policy setting is deprecated, and will be removed in future versions. 28cmake_policy(SET CMP0011 NEW) 29# https://cmake.org/cmake/help/latest/policy/CMP0012.html 30# Setting the CMP0012 policy to NEW is required for FindPython3 to work with CMake 3.18.2 31# (there is a bug in this particular version), otherwise, setting the CMP0012 policy is required 32# for CMake versions >= 3.18.3 otherwise a deprecated warning is generated. The OLD policy setting 33# is deprecated and will be removed in future versions. 34cmake_policy(SET CMP0012 NEW) 35 36if(TEST_CPP) 37 project("Mbed TLS" C CXX) 38else() 39 project("Mbed TLS" C) 40endif() 41 42# Set the project root directory. 43set(MBEDTLS_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 44 45option(USE_PKCS11_HELPER_LIBRARY "Build Mbed TLS with the pkcs11-helper library." OFF) 46option(ENABLE_ZLIB_SUPPORT "Build Mbed TLS with zlib library." OFF) 47 48option(ENABLE_PROGRAMS "Build Mbed TLS programs." ON) 49 50option(UNSAFE_BUILD "Allow unsafe builds. These builds ARE NOT SECURE." OFF) 51option(MBEDTLS_FATAL_WARNINGS "Compiler warnings treated as errors" ON) 52 53string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}") 54string(REGEX MATCH "GNU" CMAKE_COMPILER_IS_GNU "${CMAKE_C_COMPILER_ID}") 55string(REGEX MATCH "IAR" CMAKE_COMPILER_IS_IAR "${CMAKE_C_COMPILER_ID}") 56string(REGEX MATCH "MSVC" CMAKE_COMPILER_IS_MSVC "${CMAKE_C_COMPILER_ID}") 57 58# the test suites currently have compile errors with MSVC 59if(CMAKE_COMPILER_IS_MSVC) 60 option(ENABLE_TESTING "Build Mbed TLS tests." OFF) 61else() 62 option(ENABLE_TESTING "Build Mbed TLS tests." ON) 63endif() 64 65# Warning string - created as a list for compatibility with CMake 2.8 66set(WARNING_BORDER "*******************************************************\n") 67set(NULL_ENTROPY_WARN_L1 "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined!\n") 68set(NULL_ENTROPY_WARN_L2 "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES\n") 69set(NULL_ENTROPY_WARN_L3 "**** AND IS *NOT* SUITABLE FOR PRODUCTION USE\n") 70 71set(NULL_ENTROPY_WARNING "${WARNING_BORDER}" 72 "${NULL_ENTROPY_WARN_L1}" 73 "${NULL_ENTROPY_WARN_L2}" 74 "${NULL_ENTROPY_WARN_L3}" 75 "${WARNING_BORDER}") 76 77set(CTR_DRBG_128_BIT_KEY_WARN_L1 "**** WARNING! MBEDTLS_CTR_DRBG_USE_128_BIT_KEY defined!\n") 78set(CTR_DRBG_128_BIT_KEY_WARN_L2 "**** Using 128-bit keys for CTR_DRBG limits the security of generated\n") 79set(CTR_DRBG_128_BIT_KEY_WARN_L3 "**** keys and operations that use random values generated to 128-bit security\n") 80 81set(CTR_DRBG_128_BIT_KEY_WARNING "${WARNING_BORDER}" 82 "${CTR_DRBG_128_BIT_KEY_WARN_L1}" 83 "${CTR_DRBG_128_BIT_KEY_WARN_L2}" 84 "${CTR_DRBG_128_BIT_KEY_WARN_L3}" 85 "${WARNING_BORDER}") 86 87# Python 3 is only needed here to check for configuration warnings. 88if(NOT CMAKE_VERSION VERSION_LESS 3.15.0) 89 set(Python3_FIND_STRATEGY LOCATION) 90 find_package(Python3 COMPONENTS Interpreter) 91 if(Python3_Interpreter_FOUND) 92 set(MBEDTLS_PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) 93 endif() 94else() 95 find_package(PythonInterp 3) 96 if(PYTHONINTERP_FOUND) 97 set(MBEDTLS_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}) 98 endif() 99endif() 100if(MBEDTLS_PYTHON_EXECUTABLE) 101 102 # If 128-bit keys are configured for CTR_DRBG, display an appropriate warning 103 execute_process(COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY 104 RESULT_VARIABLE result) 105 if(${result} EQUAL 0) 106 message(WARNING ${CTR_DRBG_128_BIT_KEY_WARNING}) 107 endif() 108 109 # If NULL Entropy is configured, display an appropriate warning 110 execute_process(COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY 111 RESULT_VARIABLE result) 112 if(${result} EQUAL 0) 113 message(WARNING ${NULL_ENTROPY_WARNING}) 114 115 if(NOT UNSAFE_BUILD) 116 message(FATAL_ERROR "\ 117\n\ 118Warning! You have enabled MBEDTLS_TEST_NULL_ENTROPY. \ 119This option is not safe for production use and negates all security \ 120It is intended for development use only. \ 121\n\ 122To confirm you want to build with this option, re-run cmake with the \ 123option: \n\ 124 cmake -DUNSAFE_BUILD=ON ") 125 126 return() 127 endif() 128 endif() 129endif() 130 131# If this is the root project add longer list of available CMAKE_BUILD_TYPE values 132if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 133 set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} 134 CACHE STRING "Choose the type of build: None Debug Release Coverage ASan ASanDbg MemSan MemSanDbg Check CheckFull" 135 FORCE) 136endif() 137 138# Make MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE into PATHs 139set(MBEDTLS_CONFIG_FILE "" CACHE FILEPATH "Mbed TLS config file (overrides default).") 140set(MBEDTLS_USER_CONFIG_FILE "" CACHE FILEPATH "Mbed TLS user config file (appended to default).") 141 142# Create a symbolic link from ${base_name} in the binary directory 143# to the corresponding path in the source directory. 144# Note: Copies the file(s) on Windows. 145function(link_to_source base_name) 146 set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}") 147 set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}") 148 149 if (NOT EXISTS ${link}) 150 if (CMAKE_HOST_UNIX) 151 execute_process(COMMAND ln -s ${target} ${link} 152 RESULT_VARIABLE result 153 ERROR_VARIABLE output) 154 155 if (NOT ${result} EQUAL 0) 156 message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}") 157 endif() 158 else() 159 if (IS_DIRECTORY ${target}) 160 file(GLOB_RECURSE files FOLLOW_SYMLINKS RELATIVE ${target} "${target}/*") 161 foreach(file IN LISTS files) 162 if(NOT IS_DIRECTORY "${target}/${file}") 163 configure_file("${target}/${file}" "${link}/${file}" COPYONLY) 164 endif() 165 endforeach(file) 166 else() 167 configure_file(${target} ${link} COPYONLY) 168 endif() 169 endif() 170 endif() 171endfunction(link_to_source) 172 173string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}") 174 175include(CheckCCompilerFlag) 176 177if(CMAKE_COMPILER_IS_GNU) 178 # some warnings we want are not available with old GCC versions 179 # note: starting with CMake 2.8 we could use CMAKE_C_COMPILER_VERSION 180 execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion 181 OUTPUT_VARIABLE GCC_VERSION) 182 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings") 183 if (GCC_VERSION VERSION_GREATER 3.0 OR GCC_VERSION VERSION_EQUAL 3.0) 184 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat=2 -Wno-format-nonliteral") 185 endif() 186 if (GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3) 187 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wvla") 188 endif() 189 if (GCC_VERSION VERSION_GREATER 4.5 OR GCC_VERSION VERSION_EQUAL 4.5) 190 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wlogical-op") 191 endif() 192 if (GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8) 193 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow") 194 endif() 195 if (GCC_VERSION VERSION_GREATER 5.0) 196 CHECK_C_COMPILER_FLAG("-Wformat-signedness" C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS) 197 if(C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS) 198 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-signedness") 199 endif() 200 endif() 201 if (GCC_VERSION VERSION_GREATER 7.0 OR GCC_VERSION VERSION_EQUAL 7.0) 202 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-overflow=2 -Wformat-truncation") 203 endif() 204 set(CMAKE_C_FLAGS_RELEASE "-O2") 205 set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") 206 set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage") 207 set(CMAKE_C_FLAGS_ASAN "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3") 208 set(CMAKE_C_FLAGS_ASANDBG "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls") 209 set(CMAKE_C_FLAGS_CHECK "-Os") 210 set(CMAKE_C_FLAGS_CHECKFULL "${CMAKE_C_FLAGS_CHECK} -Wcast-qual") 211endif(CMAKE_COMPILER_IS_GNU) 212 213if(CMAKE_COMPILER_IS_CLANG) 214 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral") 215 set(CMAKE_C_FLAGS_RELEASE "-O2") 216 set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") 217 set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage") 218 set(CMAKE_C_FLAGS_ASAN "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3") 219 set(CMAKE_C_FLAGS_ASANDBG "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls") 220 set(CMAKE_C_FLAGS_MEMSAN "-fsanitize=memory -O3") 221 set(CMAKE_C_FLAGS_MEMSANDBG "-fsanitize=memory -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2") 222 set(CMAKE_C_FLAGS_CHECK "-Os") 223endif(CMAKE_COMPILER_IS_CLANG) 224 225if(CMAKE_COMPILER_IS_IAR) 226 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts") 227 set(CMAKE_C_FLAGS_RELEASE "-Ohz") 228 set(CMAKE_C_FLAGS_DEBUG "--debug -On") 229endif(CMAKE_COMPILER_IS_IAR) 230 231if(CMAKE_COMPILER_IS_MSVC) 232 # Strictest warnings, UTF-8 source and execution charset 233 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /utf-8") 234endif(CMAKE_COMPILER_IS_MSVC) 235 236if(MBEDTLS_FATAL_WARNINGS) 237 if(CMAKE_COMPILER_IS_MSVC) 238 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") 239 endif(CMAKE_COMPILER_IS_MSVC) 240 241 if(CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_GNU) 242 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") 243 if(UNSAFE_BUILD) 244 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=cpp") 245 set(CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} -Wno-error=cpp") 246 set(CMAKE_C_FLAGS_ASANDBG "${CMAKE_C_FLAGS_ASANDBG} -Wno-error=cpp") 247 endif(UNSAFE_BUILD) 248 endif(CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_GNU) 249 250 if (CMAKE_COMPILER_IS_IAR) 251 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warnings_are_errors") 252 endif(CMAKE_COMPILER_IS_IAR) 253endif(MBEDTLS_FATAL_WARNINGS) 254 255if(CMAKE_BUILD_TYPE STREQUAL "Coverage") 256 if(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG) 257 set(CMAKE_SHARED_LINKER_FLAGS "--coverage") 258 endif(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG) 259endif(CMAKE_BUILD_TYPE STREQUAL "Coverage") 260 261if(LIB_INSTALL_DIR) 262else() 263 set(LIB_INSTALL_DIR lib) 264endif() 265 266if(ENABLE_ZLIB_SUPPORT) 267 find_package(ZLIB) 268 269 if(ZLIB_FOUND) 270 include_directories(${ZLIB_INCLUDE_DIR}) 271 endif(ZLIB_FOUND) 272endif(ENABLE_ZLIB_SUPPORT) 273 274add_subdirectory(include) 275 276add_subdirectory(3rdparty) 277list(APPEND libs ${thirdparty_lib}) 278 279add_subdirectory(library) 280 281# 282# The C files in tests/src directory contain test code shared among test suites 283# and programs. This shared test code is compiled and linked to test suites and 284# programs objects as a set of compiled objects. The compiled objects are NOT 285# built into a library that the test suite and program objects would link 286# against as they link against the mbedcrypto, mbedx509 and mbedtls libraries. 287# The reason is that such library is expected to have mutual dependencies with 288# the aforementioned libraries and that there is as of today no portable way of 289# handling such dependencies (only toolchain specific solutions). 290# 291# Thus the below definition of the `mbedtls_test` CMake library of objects 292# target. This library of objects is used by tests and programs CMake files 293# to define the test executables. 294# 295if(ENABLE_TESTING OR ENABLE_PROGRAMS) 296 file(GLOB MBEDTLS_TEST_FILES 297 ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c 298 ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/drivers/*.c) 299 add_library(mbedtls_test OBJECT ${MBEDTLS_TEST_FILES}) 300 target_include_directories(mbedtls_test 301 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include 302 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include 303 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library) 304 305 file(GLOB MBEDTLS_TEST_HELPER_FILES 306 ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_helpers/*.c) 307 add_library(mbedtls_test_helpers OBJECT ${MBEDTLS_TEST_HELPER_FILES}) 308 target_include_directories(mbedtls_test_helpers 309 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include 310 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include 311 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library 312 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/everest/include) 313 314 # Pass-through MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE 315 if(MBEDTLS_CONFIG_FILE) 316 target_compile_definitions(mbedtls_test 317 PUBLIC MBEDTLS_CONFIG_FILE="${MBEDTLS_CONFIG_FILE}") 318 target_compile_definitions(mbedtls_test_helpers 319 PUBLIC MBEDTLS_CONFIG_FILE="${MBEDTLS_CONFIG_FILE}") 320 endif() 321 if(MBEDTLS_USER_CONFIG_FILE) 322 target_compile_definitions(mbedtls_test 323 PUBLIC MBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}") 324 target_compile_definitions(mbedtls_test_helpers 325 PUBLIC MBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}") 326 endif() 327endif() 328 329if(ENABLE_PROGRAMS) 330 add_subdirectory(programs) 331endif() 332 333ADD_CUSTOM_TARGET(${MBEDTLS_TARGET_PREFIX}apidoc 334 COMMAND doxygen mbedtls.doxyfile 335 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doxygen) 336 337if(ENABLE_TESTING) 338 enable_testing() 339 340 add_subdirectory(tests) 341 342 # additional convenience targets for Unix only 343 if(UNIX) 344 345 # For coverage testing: 346 # 1. Build with: 347 # cmake -D CMAKE_BUILD_TYPE=Coverage /path/to/source && make 348 # 2. Run the relevant tests for the part of the code you're interested in. 349 # For the reference coverage measurement, see 350 # tests/scripts/basic-build-test.sh 351 # 3. Run scripts/lcov.sh to generate an HTML report. 352 ADD_CUSTOM_TARGET(lcov 353 COMMAND scripts/lcov.sh 354 ) 355 356 ADD_CUSTOM_TARGET(memcheck 357 COMMAND sed -i.bak s+/usr/bin/valgrind+`which valgrind`+ DartConfiguration.tcl 358 COMMAND ctest -O memcheck.log -D ExperimentalMemCheck 359 COMMAND tail -n1 memcheck.log | grep 'Memory checking results:' > /dev/null 360 COMMAND rm -f memcheck.log 361 COMMAND mv DartConfiguration.tcl.bak DartConfiguration.tcl 362 ) 363 endif(UNIX) 364 365 # Make scripts needed for testing available in an out-of-source build. 366 if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) 367 link_to_source(scripts) 368 # Copy (don't link) DartConfiguration.tcl, needed for memcheck, to 369 # keep things simple with the sed commands in the memcheck target. 370 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/DartConfiguration.tcl 371 ${CMAKE_CURRENT_BINARY_DIR}/DartConfiguration.tcl COPYONLY) 372 endif() 373endif() 374