From f00e789f9ba603e864bb68ac9e21bccd0e39761c Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Wed, 11 Mar 2020 04:09:31 +0100 Subject: [PATCH] [c++] Add option to use C++ Exceptions and RTTI --- ext/gcc/module.lb | 30 +++++++++++++ src/modm/platform/core/cortex/linker.macros | 2 +- src/modm/platform/core/cortex/module.lb | 2 + tools/build_script_generator/common.py | 50 +++++++++++++++++---- tools/build_script_generator/module.lb | 11 ++++- 5 files changed, 85 insertions(+), 10 deletions(-) diff --git a/ext/gcc/module.lb b/ext/gcc/module.lb index 17e3280660..4c66f309dc 100644 --- a/ext/gcc/module.lb +++ b/ext/gcc/module.lb @@ -39,6 +39,16 @@ def prepare(module, options): name="use_modm_assert", default=True, description="Assert on exception in stdlib. Set to False to save flash.")) + elif is_cortex_m: + module.add_option( + BooleanOption( + name="exceptions", default=False, + description=descr_exceptions)) + module.add_option( + BooleanOption( + name="rtti", default=False, + description=descr_rtti)) + module.depends(":architecture:assert", ":architecture:memory") @@ -62,3 +72,23 @@ def build(env): env.copy("libcabi_cortex.cpp", "libcabi.cpp") env.copy("cxxabi_cortex.cpp", "cxxabi.cpp") env.copy("newdelete_cortex.cpp", "newdelete.cpp") + +# ============================ Option Descriptions ============================ + +descr_exceptions = """# C++ Exceptions + +Enables the full use of C++ exception handling. + +!!! warning "Check your code size" + The inclusion of the stack unwind tables will increase your code size quite + a bit. Check whether your target has enough code memory this! +""" + +descr_rtti = """# C++ Runtime Type Information + +Enables the full use of C++ runtime type information. + +!!! warning "Check your code size" + The inclusion of the RTTI tables will increase your code size quite + a bit. Check whether your target has enough code memory this! +""" diff --git a/src/modm/platform/core/cortex/linker.macros b/src/modm/platform/core/cortex/linker.macros index 7879517ddd..ff9cf2480f 100644 --- a/src/modm/platform/core/cortex/linker.macros +++ b/src/modm/platform/core/cortex/linker.macros @@ -215,7 +215,7 @@ TOTAL_STACK_SIZE = MAIN_STACK_SIZE + PROCESS_STACK_SIZE; %% endif } >{{memory}} -%% if 0 +%% if with_cpp_exceptions .ARM.extab : ALIGN(4) { *(.ARM.extab* .gnu.linkonce.armextab.*) diff --git a/src/modm/platform/core/cortex/module.lb b/src/modm/platform/core/cortex/module.lb index 3f018447eb..b8643eeef7 100644 --- a/src/modm/platform/core/cortex/module.lb +++ b/src/modm/platform/core/cortex/module.lb @@ -134,6 +134,8 @@ def common_linkerscript(env): env.collector_values(":platform:cortex-m:linkerscript.table_extern.copy")]), "linkerscript_extern_heap": "\n".join([m.strip() for m in env.collector_values(":platform:cortex-m:linkerscript.table_extern.heap")]), + + "with_cpp_exceptions": env.get(":stdc++:exceptions", False), } properties.update(common_memories(env)) return properties diff --git a/tools/build_script_generator/common.py b/tools/build_script_generator/common.py index b51949213e..afa7fdd287 100644 --- a/tools/build_script_generator/common.py +++ b/tools/build_script_generator/common.py @@ -13,6 +13,7 @@ import os, re import itertools from collections import defaultdict +from enum import IntFlag common_build_flags = { "ccflags": ("Compiler flags for both C and C++ sources", @@ -181,8 +182,23 @@ def common_collect_flags_for_scope(env, scope_filter=None): return flags -def common_compiler_flags(compiler, target): +class CompilerFeature(IntFlag): + CPP_EXCEPTIONS = 1 + CPP_RTTI = 2 + +def common_compiler_flags(compiler, target, features=None): + """ + Returns the compile flags for a given compiler, target and set of features + in the form: `flags[name(.profile)] = list(compiler flags)`. + + :param compiler: Currently supports only "GCC" + :param target: the target identifier + :param features: CompilerFeatures IntFlags + :returns: compiler flags dictionary + """ + if features is None: features = CompilerFeature(0); flags = defaultdict(list) + # flags for C **and** C++ flags["ccflags"] = [ "-W", @@ -250,6 +266,26 @@ def common_compiler_flags(compiler, target): "-std=c++17", # "-pedantic", ] + # C++ exceptions? + if features & CompilerFeature.CPP_EXCEPTIONS: + flags["cxxflags"] += [ + "-fexceptions", + "-funwind-tables", + ] + else: + flags["cxxflags"] += [ + "-fno-exceptions", + "-fno-unwind-tables", + ] + # C++ RTTI? + if features & CompilerFeature.CPP_RTTI: + flags["cxxflags"] += [ + "-frtti" + ] + else: + flags["cxxflags"] += [ + "-fno-rtti" + ] # flags only for Assembly flags["asflags"] = [ "-g3", @@ -300,9 +336,6 @@ def common_compiler_flags(compiler, target): "-Wdouble-promotion", ] flags["cxxflags"] += [ - "-fno-exceptions", - "-fno-unwind-tables", - "-fno-rtti", "-fno-threadsafe-statics", "-fuse-cxa-atexit", ] @@ -312,12 +345,16 @@ def common_compiler_flags(compiler, target): "-Wl,-wrap,_free_r", "-Wl,-wrap,_malloc_r", "-Wl,-wrap,_realloc_r", - "--specs=nano.specs", "--specs=nosys.specs", "-nostartfiles", "-L{linkdir}", "-Tlinkerscript.ld", ] + # Newlib Nano does not support C++ exceptions at all + if not (features & CompilerFeature.CPP_EXCEPTIONS): + flags["linkflags"] += [ + "--specs=nano.specs", + ] elif core.startswith("avr"): # avr-gcc only accepts certain device strings for its -mmcu flag @@ -330,9 +367,6 @@ def common_compiler_flags(compiler, target): "-mmcu={}".format(mmcu), ] flags["cxxflags"] += [ - "-fno-exceptions", - "-fno-unwind-tables", - "-fno-rtti", "-fno-threadsafe-statics", ] flags["linkflags"] += [ diff --git a/tools/build_script_generator/module.lb b/tools/build_script_generator/module.lb index 7e301fc9d6..52a4d7c4ef 100644 --- a/tools/build_script_generator/module.lb +++ b/tools/build_script_generator/module.lb @@ -129,8 +129,17 @@ def build(env): if env.has_collector(":build:path.openocd"): env.collect(":build:path.openocd", "modm/openocd") + # Assemble require compile features + if env[":target"].identifier.platform == "hosted": + compiler_features = CompilerFeature.CPP_EXCEPTIONS | CompilerFeature.CPP_RTTI + else: + compiler_features = CompilerFeature(0) + if env.get(":stdc++:exceptions", False): + compiler_features |= CompilerFeature.CPP_EXCEPTIONS + if env.get(":stdc++:rtti", False): + compiler_features |= CompilerFeature.CPP_RTTI # Add compiler flags to metadata - for flag, values in common_compiler_flags("gcc", env[":target"]).items(): + for flag, values in common_compiler_flags("gcc", env[":target"], compiler_features).items(): env.collect(flag, *values) def post_build(env):