cmake: GNU GCC: Set base compile options target by target

Signed-off-by: Ronald Cron <ronald.cron@arm.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 642ded8..1c6e8ab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -212,36 +212,42 @@
 set(CMAKE_C_EXTENSIONS OFF)
 set(CMAKE_C_STANDARD 99)
 
-if(CMAKE_COMPILER_IS_GNU)
+function(set_base_compile_options target)
+    if(CMAKE_COMPILER_IS_GNU)
+        set_gnu_base_compile_options(${target})
+    endif()
+endfunction(set_base_compile_options)
+
+function(set_gnu_base_compile_options target)
     # some warnings we want are not available with old GCC versions
     # note: starting with CMake 2.8 we could use CMAKE_C_COMPILER_VERSION
     execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
                     OUTPUT_VARIABLE GCC_VERSION)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings -Wmissing-prototypes")
+    target_compile_options(${target} PRIVATE -Wall -Wextra -Wwrite-strings -Wmissing-prototypes)
     if (GCC_VERSION VERSION_GREATER 3.0 OR GCC_VERSION VERSION_EQUAL 3.0)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat=2 -Wno-format-nonliteral")
+        target_compile_options(${target} PRIVATE -Wformat=2 -Wno-format-nonliteral)
     endif()
     if (GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wvla")
+        target_compile_options(${target} PRIVATE -Wvla)
     endif()
     if (GCC_VERSION VERSION_GREATER 4.5 OR GCC_VERSION VERSION_EQUAL 4.5)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wlogical-op")
+        target_compile_options(${target} PRIVATE -Wlogical-op)
     endif()
     if (GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
+        target_compile_options(${target} PRIVATE -Wshadow)
     endif()
     if (GCC_VERSION VERSION_GREATER 5.0)
         CHECK_C_COMPILER_FLAG("-Wformat-signedness" C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS)
         if(C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS)
-            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-signedness")
+            target_compile_options(${target} PRIVATE -Wformat-signedness)
         endif()
     endif()
     if (GCC_VERSION VERSION_GREATER 7.0 OR GCC_VERSION VERSION_EQUAL 7.0)
-      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-overflow=2 -Wformat-truncation")
+      target_compile_options(${target} PRIVATE -Wformat-overflow=2 -Wformat-truncation)
     endif()
-    set(CMAKE_C_FLAGS_RELEASE     "-O2")
-    set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
-    set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
+    target_compile_options(${target} PRIVATE $<$<CONFIG:Release>:-O2>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:Debug>:-O0 -g3>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:Coverage>:-O0 -g3 --coverage>)
     # Old GCC versions hit a performance problem with test_suite_pkwrite
     # "Private keey write check EC" tests when building with Asan+UBSan
     # and -O3: those tests take more than 100x time than normal, with
@@ -250,23 +256,22 @@
     # GCC 7.5 and above on Ubuntu 18.04 appear fine.
     # To avoid the performance problem, we use -O2 when GCC version is lower than 7.0.
     # It doesn't slow down much even with modern compiler versions.
+    target_compile_options(${target} PRIVATE $<$<CONFIG:ASan>:-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all>)
     if (GCC_VERSION VERSION_LESS 7.0)
-        message(STATUS "USING O2")
-        set(CMAKE_C_FLAGS_ASAN        "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O2")
+        target_compile_options(${target} PRIVATE $<$<CONFIG:ASan>:-O2>)
     else()
-        message(STATUS "USING O3")
-        set(CMAKE_C_FLAGS_ASAN        "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
+        target_compile_options(${target} PRIVATE $<$<CONFIG:ASan>:-O3>)
     endif()
-    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")
-    set(CMAKE_C_FLAGS_TSAN        "-fsanitize=thread -O3")
-    set(CMAKE_C_FLAGS_TSANDBG     "-fsanitize=thread -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
-    set(CMAKE_C_FLAGS_CHECK       "-Os")
-    set(CMAKE_C_FLAGS_CHECKFULL   "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
+    target_compile_options(${target} PRIVATE $<$<CONFIG:ASanDbg>:-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:TSan>:-fsanitize=thread -O3>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:TSanDbg>:-fsanitize=thread -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:Check>:-Os>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:CheckFull>:-Os -Wcast-qual>)
 
     if(MBEDTLS_FATAL_WARNINGS)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+        target_compile_options(${target} PRIVATE -Werror)
     endif(MBEDTLS_FATAL_WARNINGS)
-endif(CMAKE_COMPILER_IS_GNU)
+endfunction(set_gnu_base_compile_options)
 
 if(CMAKE_COMPILER_IS_CLANG)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings -Wmissing-prototypes -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral")
@@ -351,6 +356,7 @@
          ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c
          ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/drivers/*.c)
     add_library(mbedtls_test OBJECT ${MBEDTLS_TEST_FILES})
+    set_base_compile_options(mbedtls_test)
     if(GEN_FILES)
         add_custom_command(
             OUTPUT
@@ -396,6 +402,7 @@
     file(GLOB MBEDTLS_TEST_HELPER_FILES
          ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_helpers/*.c)
     add_library(mbedtls_test_helpers OBJECT ${MBEDTLS_TEST_HELPER_FILES})
+    set_base_compile_options(mbedtls_test_helpers)
     target_include_directories(mbedtls_test_helpers
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 0415c65..f6776ed 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -153,20 +153,24 @@
 
 if(USE_STATIC_MBEDTLS_LIBRARY)
     add_library(${mbedx509_static_target} STATIC ${src_x509})
+    set_base_compile_options(${mbedx509_static_target})
     set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509)
     target_link_libraries(${mbedx509_static_target} PUBLIC ${libs} ${mbedcrypto_static_target})
 
     add_library(${mbedtls_static_target} STATIC ${src_tls})
+    set_base_compile_options(${mbedtls_static_target})
     set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls)
     target_link_libraries(${mbedtls_static_target} PUBLIC ${libs} ${mbedx509_static_target})
 endif(USE_STATIC_MBEDTLS_LIBRARY)
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(${mbedx509_target} SHARED ${src_x509})
+    set_base_compile_options(${mbedx509_target})
     set_target_properties(${mbedx509_target} PROPERTIES VERSION 4.0.0 SOVERSION 7)
     target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
 
     add_library(${mbedtls_target} SHARED ${src_tls})
+    set_base_compile_options(${mbedtls_target})
     set_target_properties(${mbedtls_target} PROPERTIES VERSION 4.0.0 SOVERSION 21)
     target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
 endif(USE_SHARED_MBEDTLS_LIBRARY)
diff --git a/programs/aes/CMakeLists.txt b/programs/aes/CMakeLists.txt
index 4d4c890..b6dde71 100644
--- a/programs/aes/CMakeLists.txt
+++ b/programs/aes/CMakeLists.txt
@@ -5,6 +5,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${mbedcrypto_target} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
diff --git a/programs/cipher/CMakeLists.txt b/programs/cipher/CMakeLists.txt
index effaf8a..7d4e452 100644
--- a/programs/cipher/CMakeLists.txt
+++ b/programs/cipher/CMakeLists.txt
@@ -5,6 +5,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${mbedcrypto_target} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
diff --git a/programs/fuzz/CMakeLists.txt b/programs/fuzz/CMakeLists.txt
index f5358ff..44fff9a 100644
--- a/programs/fuzz/CMakeLists.txt
+++ b/programs/fuzz/CMakeLists.txt
@@ -40,6 +40,7 @@
     endif()
 
     add_executable(${exe} ${exe_sources})
+    set_base_compile_options(${exe})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 
     if (NOT FUZZINGENGINE_LIB)
diff --git a/programs/hash/CMakeLists.txt b/programs/hash/CMakeLists.txt
index 0ad974d..c27c4e7 100644
--- a/programs/hash/CMakeLists.txt
+++ b/programs/hash/CMakeLists.txt
@@ -7,6 +7,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${mbedcrypto_target} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
diff --git a/programs/pkey/CMakeLists.txt b/programs/pkey/CMakeLists.txt
index defbe28..9caec87 100644
--- a/programs/pkey/CMakeLists.txt
+++ b/programs/pkey/CMakeLists.txt
@@ -6,6 +6,7 @@
 
 foreach(exe IN LISTS executables_mbedtls)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${mbedtls_target} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
@@ -34,6 +35,7 @@
 
 foreach(exe IN LISTS executables_mbedcrypto)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${mbedcrypto_target} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
diff --git a/programs/psa/CMakeLists.txt b/programs/psa/CMakeLists.txt
index cfc983c..707de43 100644
--- a/programs/psa/CMakeLists.txt
+++ b/programs/psa/CMakeLists.txt
@@ -29,6 +29,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${mbedcrypto_target} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
diff --git a/programs/random/CMakeLists.txt b/programs/random/CMakeLists.txt
index f0c7825..a83bf9e 100644
--- a/programs/random/CMakeLists.txt
+++ b/programs/random/CMakeLists.txt
@@ -6,6 +6,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${mbedcrypto_target} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
diff --git a/programs/ssl/CMakeLists.txt b/programs/ssl/CMakeLists.txt
index 02010d8..6919a8e 100644
--- a/programs/ssl/CMakeLists.txt
+++ b/programs/ssl/CMakeLists.txt
@@ -40,6 +40,7 @@
     endif()
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
         ${extra_sources})
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${libs} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
     if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
@@ -53,6 +54,7 @@
 
 if(THREADS_FOUND)
     add_executable(ssl_pthread_server ssl_pthread_server.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(ssl_pthread_server)
     target_include_directories(ssl_pthread_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
     target_link_libraries(ssl_pthread_server ${libs} ${CMAKE_THREAD_LIBS_INIT})
     list(APPEND executables ssl_pthread_server)
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index 928ab49..83bc9bf 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -29,6 +29,7 @@
         WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
     )
     add_executable(cpp_dummy_build "${cpp_dummy_build_cpp}")
+    set_base_compile_options(cpp_dummy_build)
     target_include_directories(cpp_dummy_build
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../include
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tf-psa-crypto/include
@@ -39,6 +40,7 @@
 if(USE_SHARED_MBEDTLS_LIBRARY AND
    NOT ${CMAKE_SYSTEM_NAME} MATCHES "[Ww][Ii][Nn]")
     add_executable(dlopen "dlopen.c")
+    set_base_compile_options(dlopen)
     target_include_directories(dlopen
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../include
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tf-psa-crypto/include
@@ -82,6 +84,7 @@
     endif()
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
         ${extra_sources})
+    set_base_compile_options(${exe})
     target_include_directories(${exe}
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
     target_include_directories(${exe}
diff --git a/programs/util/CMakeLists.txt b/programs/util/CMakeLists.txt
index 9ceb13f..ac713dc 100644
--- a/programs/util/CMakeLists.txt
+++ b/programs/util/CMakeLists.txt
@@ -11,6 +11,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${libs} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt
index a09813c..a31bada 100644
--- a/programs/x509/CMakeLists.txt
+++ b/programs/x509/CMakeLists.txt
@@ -14,6 +14,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(${exe})
     target_link_libraries(${exe} ${libs} ${CMAKE_THREAD_LIBS_INIT})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a9d5c84..d19c261 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -156,6 +156,7 @@
     add_executable(test_suite_${data_name} test_suite_${data_name}.c
                    $<TARGET_OBJECTS:mbedtls_test>
                    $<TARGET_OBJECTS:mbedtls_test_helpers>)
+    set_base_compile_options(test_suite_${data_name})
     add_dependencies(test_suite_${data_name} ${dependency})
     target_link_libraries(test_suite_${data_name} ${libs})
     # Include test-specific header files from ./include and private header
diff --git a/tf-psa-crypto/TF-PSA-Crypto.cmake b/tf-psa-crypto/TF-PSA-Crypto.cmake
index 66024b8..d8e13c8 100644
--- a/tf-psa-crypto/TF-PSA-Crypto.cmake
+++ b/tf-psa-crypto/TF-PSA-Crypto.cmake
@@ -177,48 +177,66 @@
 set(CMAKE_C_EXTENSIONS OFF)
 set(CMAKE_C_STANDARD 99)
 
-if(CMAKE_COMPILER_IS_GNU)
+function(set_base_compile_options target)
+    if(CMAKE_COMPILER_IS_GNU)
+        set_gnu_base_compile_options(${target})
+    endif()
+endfunction(set_base_compile_options)
+
+function(set_gnu_base_compile_options target)
     # some warnings we want are not available with old GCC versions
     # note: starting with CMake 2.8 we could use CMAKE_C_COMPILER_VERSION
     execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
                     OUTPUT_VARIABLE GCC_VERSION)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings -Wmissing-prototypes")
+    target_compile_options(${target} PRIVATE -Wall -Wextra -Wwrite-strings -Wmissing-prototypes)
     if (GCC_VERSION VERSION_GREATER 3.0 OR GCC_VERSION VERSION_EQUAL 3.0)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat=2 -Wno-format-nonliteral")
+        target_compile_options(${target} PRIVATE -Wformat=2 -Wno-format-nonliteral)
     endif()
     if (GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wvla")
+        target_compile_options(${target} PRIVATE -Wvla)
     endif()
     if (GCC_VERSION VERSION_GREATER 4.5 OR GCC_VERSION VERSION_EQUAL 4.5)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wlogical-op")
+        target_compile_options(${target} PRIVATE -Wlogical-op)
     endif()
     if (GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
+        target_compile_options(${target} PRIVATE -Wshadow)
     endif()
     if (GCC_VERSION VERSION_GREATER 5.0)
         CHECK_C_COMPILER_FLAG("-Wformat-signedness" C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS)
         if(C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS)
-            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-signedness")
+            target_compile_options(${target} PRIVATE -Wformat-signedness)
         endif()
     endif()
     if (GCC_VERSION VERSION_GREATER 7.0 OR GCC_VERSION VERSION_EQUAL 7.0)
-      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-overflow=2 -Wformat-truncation")
+      target_compile_options(${target} PRIVATE -Wformat-overflow=2 -Wformat-truncation)
     endif()
-
-    set(CMAKE_C_FLAGS_RELEASE     "-O2")
-    set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
-    set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
-    set(CMAKE_C_FLAGS_ASAN        "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
-    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")
-    set(CMAKE_C_FLAGS_TSAN        "-fsanitize=thread -O3")
-    set(CMAKE_C_FLAGS_TSANDBG     "-fsanitize=thread -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
-    set(CMAKE_C_FLAGS_CHECK       "-Os")
-    set(CMAKE_C_FLAGS_CHECKFULL   "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
+    target_compile_options(${target} PRIVATE $<$<CONFIG:Release>:-O2>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:Debug>:-O0 -g3>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:Coverage>:-O0 -g3 --coverage>)
+    # Old GCC versions hit a performance problem with test_suite_pkwrite
+    # "Private keey write check EC" tests when building with Asan+UBSan
+    # and -O3: those tests take more than 100x time than normal, with
+    # test_suite_pkwrite taking >3h on the CI. Observed with GCC 5.4 on
+    # Ubuntu 16.04 x86_64 and GCC 6.5 on Ubuntu 18.04 x86_64.
+    # GCC 7.5 and above on Ubuntu 18.04 appear fine.
+    # To avoid the performance problem, we use -O2 when GCC version is lower than 7.0.
+    # It doesn't slow down much even with modern compiler versions.
+    target_compile_options(${target} PRIVATE $<$<CONFIG:ASan>:-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all>)
+    if (GCC_VERSION VERSION_LESS 7.0)
+        target_compile_options(${target} PRIVATE $<$<CONFIG:ASan>:-O2>)
+    else()
+        target_compile_options(${target} PRIVATE $<$<CONFIG:ASan>:-O3>)
+    endif()
+    target_compile_options(${target} PRIVATE $<$<CONFIG:ASanDbg>:-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:TSan>:-fsanitize=thread -O3>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:TSanDbg>:-fsanitize=thread -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:Check>:-Os>)
+    target_compile_options(${target} PRIVATE $<$<CONFIG:CheckFull>:-Os -Wcast-qual>)
 
     if(TF_PSA_CRYPTO_FATAL_WARNINGS)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+        target_compile_options(${target} PRIVATE -Werror)
     endif(TF_PSA_CRYPTO_FATAL_WARNINGS)
-endif(CMAKE_COMPILER_IS_GNU)
+endfunction(set_gnu_base_compile_options)
 
 if(CMAKE_COMPILER_IS_CLANG)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings -Wmissing-prototypes -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral")
@@ -300,6 +318,7 @@
          ${MBEDTLS_DIR}/tests/src/*.c
          ${MBEDTLS_DIR}/tests/src/drivers/*.c)
     add_library(mbedtls_test OBJECT ${MBEDTLS_TEST_FILES})
+    set_base_compile_options(mbedtls_test)
     if(GEN_FILES)
         add_custom_command(
             OUTPUT
diff --git a/tf-psa-crypto/core/CMakeLists.txt b/tf-psa-crypto/core/CMakeLists.txt
index 0917cae..b9225b3 100644
--- a/tf-psa-crypto/core/CMakeLists.txt
+++ b/tf-psa-crypto/core/CMakeLists.txt
@@ -91,6 +91,7 @@
 
 if(USE_STATIC_TF_PSA_CRYPTO_LIBRARY)
     add_library(${mbedcrypto_static_target} STATIC ${src_crypto})
+    set_base_compile_options(${mbedcrypto_static_target})
     set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto)
     target_link_libraries(${mbedcrypto_static_target} PUBLIC ${libs})
 
@@ -108,6 +109,7 @@
 if(USE_SHARED_TF_PSA_CRYPTO_LIBRARY)
     set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR})
     add_library(${mbedcrypto_target} SHARED ${src_crypto})
+    set_base_compile_options(${mbedcrypto_target})
     set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 4.0.0 SOVERSION 16)
     target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
 
diff --git a/tf-psa-crypto/drivers/builtin/CMakeLists.txt b/tf-psa-crypto/drivers/builtin/CMakeLists.txt
index 9ec1a87..3c1459a 100644
--- a/tf-psa-crypto/drivers/builtin/CMakeLists.txt
+++ b/tf-psa-crypto/drivers/builtin/CMakeLists.txt
@@ -54,6 +54,7 @@
 
 if(USE_STATIC_TF_PSA_CRYPTO_LIBRARY)
     add_library(${builtin_static_target} STATIC ${src_builtin})
+    set_base_compile_options(${builtin_static_target})
     target_link_libraries(${builtin_static_target} PUBLIC ${libs})
     if(TARGET ${everest_target})
         target_link_libraries(${builtin_static_target} PUBLIC ${everest_target})
@@ -66,6 +67,7 @@
 
 if(USE_SHARED_TF_PSA_CRYPTO_LIBRARY)
     add_library(${builtin_target} SHARED ${src_builtin})
+    set_base_compile_options(${builtin_target})
     target_link_libraries(${builtin_target} PUBLIC ${libs})
     if(TARGET ${everest_target})
         target_link_libraries(${builtin_target} PUBLIC ${everest_target})
diff --git a/tf-psa-crypto/drivers/everest/CMakeLists.txt b/tf-psa-crypto/drivers/everest/CMakeLists.txt
index e704859..5671200 100644
--- a/tf-psa-crypto/drivers/everest/CMakeLists.txt
+++ b/tf-psa-crypto/drivers/everest/CMakeLists.txt
@@ -5,6 +5,7 @@
   library/x25519.c
   library/Hacl_Curve25519_joined.c)
 
+set_base_compile_options(${everest_target})
 target_include_directories(${everest_target}
   PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
          $<BUILD_INTERFACE:${MBEDTLS_DIR}/include>
diff --git a/tf-psa-crypto/drivers/p256-m/CMakeLists.txt b/tf-psa-crypto/drivers/p256-m/CMakeLists.txt
index ede2831..af046da 100644
--- a/tf-psa-crypto/drivers/p256-m/CMakeLists.txt
+++ b/tf-psa-crypto/drivers/p256-m/CMakeLists.txt
@@ -4,6 +4,8 @@
     p256-m_driver_entrypoints.c
     p256-m/p256-m.c)
 
+set_base_compile_options(${p256m_target})
+
 target_include_directories(${p256m_target}
   PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
          $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/p256-m>
diff --git a/tf-psa-crypto/tests/CMakeLists.txt b/tf-psa-crypto/tests/CMakeLists.txt
index 0e84bab..9866e4f 100644
--- a/tf-psa-crypto/tests/CMakeLists.txt
+++ b/tf-psa-crypto/tests/CMakeLists.txt
@@ -294,6 +294,7 @@
 
     add_executable(test_suite_${data_name} test_suite_${data_name}.c
                    $<TARGET_OBJECTS:mbedtls_test>)
+    set_base_compile_options(test_suite_${data_name})
     add_dependencies(test_suite_${data_name} ${dependency})
     target_link_libraries(test_suite_${data_name} ${libs})
     # Include test-specific header files from ./include and private header