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>
This commit is contained in:
Benoit Leforestier 2018-10-23 18:20:51 +02:00 committed by Anas Nashif
commit 26e0f9a9e1
7 changed files with 233 additions and 63 deletions

View file

@ -105,6 +105,28 @@ else()
assert(0 "Unreachable code. Expected optimization level to have been chosen. See misc/Kconfig.") assert(0 "Unreachable code. Expected optimization level to have been chosen. See misc/Kconfig.")
endif() 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( zephyr_compile_options(
${OPTIMIZATION_FLAG} # Usually -Os ${OPTIMIZATION_FLAG} # Usually -Os
-g # TODO: build configuration enough? -g # TODO: build configuration enough?
@ -120,17 +142,27 @@ zephyr_compile_options(
) )
zephyr_compile_options( zephyr_compile_options(
$<$<COMPILE_LANGUAGE:CXX>:-std=c++11> $<$<COMPILE_LANGUAGE:CXX>:-std=${STD_CPP_DIALECT}>
$<$<COMPILE_LANGUAGE:CXX>:-fcheck-new> $<$<COMPILE_LANGUAGE:CXX>:-fcheck-new>
$<$<COMPILE_LANGUAGE:CXX>:-ffunction-sections> $<$<COMPILE_LANGUAGE:CXX>:-ffunction-sections>
$<$<COMPILE_LANGUAGE:CXX>:-fdata-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>:-xassembler-with-cpp>
$<$<COMPILE_LANGUAGE:ASM>:-D_ASMLANGUAGE> $<$<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) if(NOT CONFIG_NATIVE_APPLICATION)
zephyr_ld_options( zephyr_ld_options(
-nostartfiles -nostartfiles
@ -141,6 +173,12 @@ zephyr_ld_options(
) )
endif() endif()
if(CONFIG_LIB_CPLUSPLUS)
zephyr_ld_options(
-lstdc++
)
endif()
# ========================================================================== # ==========================================================================
# #
# cmake -DW=... settings # cmake -DW=... settings

View file

@ -4846,61 +4846,6 @@ extern void _arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
} }
#endif #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 <tracing.h>
#include <syscalls/kernel.h> #include <syscalls/kernel.h>

View file

@ -111,6 +111,7 @@ config CHECK_LINK_MAP
help help
Run a linker address generation validity checker at the end of the Run a linker address generation validity checker at the end of the
build. build.
endmenu endmenu
menu "Compiler Options" menu "Compiler Options"
@ -175,11 +176,6 @@ config COMPILER_OPT
and can be used to change compiler optimization, warning and error and can be used to change compiler optimization, warning and error
messages, and so on. 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 endmenu
menu "Build Options" menu "Build Options"

View file

@ -9,6 +9,8 @@ source "subsys/bluetooth/Kconfig"
source "subsys/console/Kconfig" source "subsys/console/Kconfig"
source "subsys/cpp/Kconfig"
source "subsys/debug/Kconfig" source "subsys/debug/Kconfig"
source "subsys/disk/Kconfig" source "subsys/disk/Kconfig"

View file

@ -4,4 +4,5 @@ zephyr_sources_ifdef(CONFIG_CPLUSPLUS
cpp_init_array.c cpp_init_array.c
cpp_ctors.c cpp_ctors.c
cpp_dtors.c cpp_dtors.c
cpp_new.cpp
) )

70
subsys/cpp/Kconfig Normal file
View file

@ -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

118
subsys/cpp/cpp_new.cpp Normal file
View file

@ -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