From 26e0f9a9e1267858848cbad0a145b87a4c07b2c6 Mon Sep 17 00:00:00 2001 From: Benoit Leforestier Date: Tue, 23 Oct 2018 18:20:51 +0200 Subject: [PATCH] Build: Improve C++ support Can choose the C++ standard (C++98/11/14/17/2a) Can link with standard C++ library (libstdc++) Add support of C++ exceptions Add support of C++ RTTI Add C++ options to subsys/cpp/Kconfig Implements new and delete using k_malloc and k_free if CONFIG_HEAP_MEM_POOL_SIZE is defined Signed-off-by: Benoit Leforestier --- CMakeLists.txt | 44 +++++++++++++- include/kernel.h | 55 ------------------ misc/Kconfig | 6 +- subsys/Kconfig | 2 + subsys/cpp/CMakeLists.txt | 1 + subsys/cpp/Kconfig | 70 ++++++++++++++++++++++ subsys/cpp/cpp_new.cpp | 118 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 233 insertions(+), 63 deletions(-) create mode 100644 subsys/cpp/Kconfig create mode 100644 subsys/cpp/cpp_new.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e78978f4ae..ccff722a319 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,28 @@ else() assert(0 "Unreachable code. Expected optimization level to have been chosen. See misc/Kconfig.") endif() +# Dialects of C++, corresponding to the multiple published ISO standards. +# Which standard it implements can be selected using the -std= command-line option. +set_ifndef(DIALECT_STD_CPP98 "c++98") +set_ifndef(DIALECT_STD_CPP11 "c++11") +set_ifndef(DIALECT_STD_CPP14 "c++14") +set_ifndef(DIALECT_STD_CPP17 "c++17") +set_ifndef(DIALECT_STD_CPP2A "c++2a") + +if(CONFIG_STD_CPP98) + set(STD_CPP_DIALECT ${DIALECT_STD_CPP98}) +elseif(CONFIG_STD_CPP11) + set(STD_CPP_DIALECT ${DIALECT_STD_CPP11}) # Default +elseif(CONFIG_STD_CPP14) + set(STD_CPP_DIALECT ${DIALECT_STD_CPP14}) +elseif(CONFIG_STD_CPP17) + set(STD_CPP_DIALECT ${DIALECT_STD_CPP17}) +elseif(CONFIG_STD_CPP2A) + set(STD_CPP_DIALECT ${DIALECT_STD_CPP2A}) +else() + assert(0 "Unreachable code. Expected C++ standard to have been chosen. See misc/Kconfig.") +endif() + zephyr_compile_options( ${OPTIMIZATION_FLAG} # Usually -Os -g # TODO: build configuration enough? @@ -120,17 +142,27 @@ zephyr_compile_options( ) zephyr_compile_options( - $<$:-std=c++11> + $<$:-std=${STD_CPP_DIALECT}> $<$:-fcheck-new> $<$:-ffunction-sections> $<$:-fdata-sections> - $<$:-fno-rtti> - $<$:-fno-exceptions> $<$:-xassembler-with-cpp> $<$:-D_ASMLANGUAGE> ) +if(NOT CONFIG_RTTI) +zephyr_compile_options( + $<$:-fno-rtti> +) +endif() + +if(NOT CONFIG_EXCEPTIONS) +zephyr_compile_options( + $<$:-fno-exceptions> +) +endif() + if(NOT CONFIG_NATIVE_APPLICATION) zephyr_ld_options( -nostartfiles @@ -141,6 +173,12 @@ zephyr_ld_options( ) endif() +if(CONFIG_LIB_CPLUSPLUS) +zephyr_ld_options( + -lstdc++ +) +endif() + # ========================================================================== # # cmake -DW=... settings diff --git a/include/kernel.h b/include/kernel.h index 4d1825c9c19..30e449f1b6d 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -4846,61 +4846,6 @@ extern void _arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, } #endif -#if defined(CONFIG_CPLUSPLUS) && defined(__cplusplus) -/* - * Define new and delete operators. - * At this moment, the operators do nothing since objects are supposed - * to be statically allocated. - */ -inline void operator delete(void *ptr) -{ - (void)ptr; -} - -inline void operator delete[](void *ptr) -{ - (void)ptr; -} - -inline void *operator new(size_t size) -{ - (void)size; - return NULL; -} - -inline void *operator new[](size_t size) -{ - (void)size; - return NULL; -} - -/* Placement versions of operator new and delete */ -inline void operator delete(void *ptr1, void *ptr2) -{ - (void)ptr1; - (void)ptr2; -} - -inline void operator delete[](void *ptr1, void *ptr2) -{ - (void)ptr1; - (void)ptr2; -} - -inline void *operator new(size_t size, void *ptr) -{ - (void)size; - return ptr; -} - -inline void *operator new[](size_t size, void *ptr) -{ - (void)size; - return ptr; -} - -#endif /* defined(CONFIG_CPLUSPLUS) && defined(__cplusplus) */ - #include #include diff --git a/misc/Kconfig b/misc/Kconfig index c53f7306b5f..105fea9fb66 100644 --- a/misc/Kconfig +++ b/misc/Kconfig @@ -111,6 +111,7 @@ config CHECK_LINK_MAP help Run a linker address generation validity checker at the end of the build. + endmenu menu "Compiler Options" @@ -175,11 +176,6 @@ config COMPILER_OPT and can be used to change compiler optimization, warning and error messages, and so on. -config CPLUSPLUS - bool "Enable C++ support for the application" - help - This option enables the use of applications built with C++. - endmenu menu "Build Options" diff --git a/subsys/Kconfig b/subsys/Kconfig index 76feac7a1a9..d51b582b232 100644 --- a/subsys/Kconfig +++ b/subsys/Kconfig @@ -9,6 +9,8 @@ source "subsys/bluetooth/Kconfig" source "subsys/console/Kconfig" +source "subsys/cpp/Kconfig" + source "subsys/debug/Kconfig" source "subsys/disk/Kconfig" diff --git a/subsys/cpp/CMakeLists.txt b/subsys/cpp/CMakeLists.txt index 5daacc8a2ce..84046f347de 100644 --- a/subsys/cpp/CMakeLists.txt +++ b/subsys/cpp/CMakeLists.txt @@ -4,4 +4,5 @@ zephyr_sources_ifdef(CONFIG_CPLUSPLUS cpp_init_array.c cpp_ctors.c cpp_dtors.c + cpp_new.cpp ) diff --git a/subsys/cpp/Kconfig b/subsys/cpp/Kconfig new file mode 100644 index 00000000000..ee13e731eb8 --- /dev/null +++ b/subsys/cpp/Kconfig @@ -0,0 +1,70 @@ +# Kconfig - C++ configuration options + +# +# Copyright (c) 2018 B. Leforestier +# +# SPDX-License-Identifier: Apache-2.0 +# + +menu "C++ Options" + +config CPLUSPLUS + bool "Enable C++ support for the application" + help + This option enables the use of applications built with C++. + +choice + prompt "C++ Standard" + default STD_CPP11 + help + C++ Standards. + +config STD_CPP98 + bool "C++ 98" + help + 1998 C++ standard as modified by the 2003 technical corrigendum + and some later defect reports. + +config STD_CPP11 + bool "C++ 11" + help + 2011 C++ standard, previously known as C++0x. + +config STD_CPP14 + bool "C++ 14" + help + 2014 C++ standard. + +config STD_CPP17 + bool "C++ 17" + help + 2017 C++ standard, previously known as C++0x. + +config STD_CPP2A + bool "C++ 2a" + help + Next revision of the C++ standard, which is expected to be published in 2020. + +endchoice + +config LIB_CPLUSPLUS + depends on CPLUSPLUS + bool "Link with STD C++ library" + help + Link with STD C++ Library. + +config EXCEPTIONS + depends on CPLUSPLUS + select LIB_CPLUSPLUS + bool "Enable C++ exceptions support" + help + This option enables support of C++ exceptions. + +config RTTI + depends on CPLUSPLUS + select LIB_CPLUSPLUS + bool "Enable C++ RTTI support" + help + This option enables support of C++ RTTI. + +endmenu diff --git a/subsys/cpp/cpp_new.cpp b/subsys/cpp/cpp_new.cpp new file mode 100644 index 00000000000..29f6b6414ec --- /dev/null +++ b/subsys/cpp/cpp_new.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if defined(CONFIG_LIB_CPLUSPLUS) +#include +#endif // CONFIG_LIB_CPLUSPLUS +#include + +void* operator new(size_t size) +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + void* ptr = k_malloc(size); +#if defined(__cpp_exceptions) && defined(CONFIG_LIB_CPLUSPLUS) + if (!ptr) + throw std::bad_alloc(); +#endif + return ptr; +#else + ARG_UNUSED(size); + return NULL; +#endif +} + +void* operator new[](size_t size) +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + void* ptr = k_malloc(size); +#if defined(__cpp_exceptions) && defined(CONFIG_LIB_CPLUSPLUS) + if (!ptr) + throw std::bad_alloc(); +#endif + return ptr; +#else + ARG_UNUSED(size); + return NULL; +#endif +} + +void operator delete(void* ptr) noexcept +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + k_free(ptr); +#else + ARG_UNUSED(ptr); +#endif +} + +void operator delete[](void* ptr) noexcept +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + k_free(ptr); +#else + ARG_UNUSED(ptr); +#endif +} + +#if defined(CONFIG_LIB_CPLUSPLUS) +void* operator new(size_t size, const std::nothrow_t&) noexcept +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + return k_malloc(size); +#else + ARG_UNUSED(size); + return NULL; +#endif +} + +void* operator new[](size_t size, const std::nothrow_t&) noexcept +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + return k_malloc(size); +#else + ARG_UNUSED(size); + return NULL; +#endif +} + +void operator delete(void* ptr, const std::nothrow_t&) noexcept +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + k_free(ptr); +#else + ARG_UNUSED(ptr); +#endif +} + +void operator delete[](void* ptr, const std::nothrow_t&) noexcept +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + k_free(ptr); +#else + ARG_UNUSED(ptr); +#endif +} +#endif // CONFIG_LIB_CPLUSPLUS + +#if (__cplusplus > 201103L) +void operator delete(void* ptr, size_t) noexcept +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + k_free(ptr); +#else + ARG_UNUSED(ptr); +#endif +} + +void operator delete[](void* ptr, size_t) noexcept +{ +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) + k_free(ptr); +#else + ARG_UNUSED(ptr); +#endif +} +#endif // __cplusplus > 201103L