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 <benoit.leforestier@gmail.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e78978..ccff722 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -105,6 +105,28 @@
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(
- $<$<COMPILE_LANGUAGE:CXX>:-std=c++11>
+ $<$<COMPILE_LANGUAGE:CXX>:-std=${STD_CPP_DIALECT}>
$<$<COMPILE_LANGUAGE:CXX>:-fcheck-new>
$<$<COMPILE_LANGUAGE:CXX>:-ffunction-sections>
$<$<COMPILE_LANGUAGE:CXX>:-fdata-sections>
- $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
- $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
$<$<COMPILE_LANGUAGE:ASM>:-xassembler-with-cpp>
$<$<COMPILE_LANGUAGE:ASM>:-D_ASMLANGUAGE>
)
+if(NOT CONFIG_RTTI)
+zephyr_compile_options(
+ $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
+)
+endif()
+
+if(NOT CONFIG_EXCEPTIONS)
+zephyr_compile_options(
+ $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
+)
+endif()
+
if(NOT CONFIG_NATIVE_APPLICATION)
zephyr_ld_options(
-nostartfiles
@@ -141,6 +173,12 @@
)
endif()
+if(CONFIG_LIB_CPLUSPLUS)
+zephyr_ld_options(
+ -lstdc++
+)
+endif()
+
# ==========================================================================
#
# cmake -DW=... settings
diff --git a/include/kernel.h b/include/kernel.h
index 4d1825c..30e449f 100644
--- a/include/kernel.h
+++ b/include/kernel.h
@@ -4846,61 +4846,6 @@
}
#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 <tracing.h>
#include <syscalls/kernel.h>
diff --git a/misc/Kconfig b/misc/Kconfig
index c53f730..105fea9 100644
--- a/misc/Kconfig
+++ b/misc/Kconfig
@@ -111,6 +111,7 @@
help
Run a linker address generation validity checker at the end of the
build.
+
endmenu
menu "Compiler Options"
@@ -175,11 +176,6 @@
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 76feac7..d51b582 100644
--- a/subsys/Kconfig
+++ b/subsys/Kconfig
@@ -9,6 +9,8 @@
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 5daacc8..84046f3 100644
--- a/subsys/cpp/CMakeLists.txt
+++ b/subsys/cpp/CMakeLists.txt
@@ -4,4 +4,5 @@
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 0000000..ee13e73
--- /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 0000000..29f6b64
--- /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 <new>
+#endif // CONFIG_LIB_CPLUSPLUS
+#include <kernel.h>
+
+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