diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-03-02 10:58:26 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-03-02 10:58:26 +0900 |
| commit | 0bcf9e28fc6b41f75e78557295decfdcdb947b7a (patch) | |
| tree | f35fed4d182ee5dadeb91048a1bdba9da1d9063b | |
| parent | fdd92750fe7e65150b067bc5179e813e7b5e2312 (diff) | |
| download | mruby-0bcf9e28fc6b41f75e78557295decfdcdb947b7a.tar.gz mruby-0bcf9e28fc6b41f75e78557295decfdcdb947b7a.zip | |
Reorganize C++ exceptions; ref #3470
There are 3 levels of C++ exception handling:
* default - no C++ exception (use setjmp/longjmp)
* enable_cxx_exception (use C++ exceptions with C ABI)
* enable_cxx_abi (use C++ ABI including exceptions)
| -rw-r--r-- | doc/guides/compile.md | 29 | ||||
| -rw-r--r-- | include/mruby/throw.h | 6 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mruby/mrbgem.rake | 6 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/mrbgem.rake | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-error/mrbgem.rake | 2 | ||||
| -rw-r--r-- | src/mruby_core.rake | 4 | ||||
| -rw-r--r-- | src/vm.c | 4 | ||||
| -rw-r--r-- | tasks/mruby_build.rake | 32 |
8 files changed, 55 insertions, 32 deletions
diff --git a/doc/guides/compile.md b/doc/guides/compile.md index 9ca61c6fd..2aaf6f1fe 100644 --- a/doc/guides/compile.md +++ b/doc/guides/compile.md @@ -241,13 +241,15 @@ conf.enable_bintest ### C++ ABI -mruby can use C++ exception to raise exception internally. -By using C++ exception it can release C++ stack object correctly. +By default, mruby uses setjmp/longjmp to implement its +exceptions. But it doesn't release C++ stack object +correctly. To support mrbgems written in C++, mruby can be +configured to use C++ exception. There are two levels of C++ exception handling. The one is -C++ exception enabled (but still C files are compiled by C -compiler), and the other is C++ ABI mode where all files are -compiled by C++ compiler. +```enable_cxx_exception``` that enables C++ exception, but +uses C ABI. The other is ```enable_cxx_abi``` where all +files are compiled by C++ compiler. When you mix C++ code, C++ exception would be enabled automatically. If you need to enable C++ exception explicitly add the following: @@ -255,23 +257,16 @@ If you need to enable C++ exception explicitly add the following: conf.enable_cxx_exception ``` -If you need to enable C++ ABI mode explicitly add the following: -```ruby -conf.enable_cxx_abi -``` - #### C++ exception disabling. - -If you need to force C++ exception disable -(For example using a compiler option to disable C++ exception), -but still want to use C++ ABI mode, -add following: +If your compiler does not support C++ and you want to ensure +you don't use mrbgem written in C++, you can explicitly disable +C++ exception, add following: ```ruby conf.disable_cxx_exception ``` - -Note that it must be called before ```enable_cxx_abi``` or ```gem``` method. +and you will get an error when you try to use C++ gem. +Note that it must be called before ```enable_cxx_exception``` or ```gem``` method. ### Debugging mode diff --git a/include/mruby/throw.h b/include/mruby/throw.h index 010793027..5d3d214e7 100644 --- a/include/mruby/throw.h +++ b/include/mruby/throw.h @@ -7,8 +7,10 @@ #ifndef MRB_THROW_H #define MRB_THROW_H -#if defined(MRB_ENABLE_CXX_EXCEPTION) && !defined(__cplusplus) -#error Trying to use C++ exception handling in C code +#if defined(MRB_ENABLE_CXX_ABI) +# if !defined(__cplusplus) +# error Trying to use C++ exception handling in C code +# endif #endif #if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus) diff --git a/mrbgems/mruby-bin-mruby/mrbgem.rake b/mrbgems/mruby-bin-mruby/mrbgem.rake index ba7fad1fa..243b413eb 100644 --- a/mrbgems/mruby-bin-mruby/mrbgem.rake +++ b/mrbgems/mruby-bin-mruby/mrbgem.rake @@ -4,4 +4,10 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec| spec.summary = 'mruby command' spec.bins = %w(mruby) spec.add_dependency('mruby-compiler', :core => 'mruby-compiler') + spec.add_dependency('mruby-error', :core => 'mruby-error') + + if build.cxx_exception_enabled? + @objs << build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx") + @objs.delete_if { |v| v == objfile("#{spec.build_dir}/tools/mruby/mruby") } + end end diff --git a/mrbgems/mruby-compiler/mrbgem.rake b/mrbgems/mruby-compiler/mrbgem.rake index 3a22762fa..3bf6d6ae3 100644 --- a/mrbgems/mruby-compiler/mrbgem.rake +++ b/mrbgems/mruby-compiler/mrbgem.rake @@ -8,11 +8,11 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec| lex_def = "#{current_dir}/core/lex.def" core_objs = Dir.glob("#{current_dir}/core/*.c").map { |f| - next nil if build.cxx_abi_enabled? and f =~ /(codegen).c$/ + next nil if build.cxx_exception_enabled? and f =~ /(codegen).c$/ objfile(f.pathmap("#{current_build_dir}/core/%n")) }.compact - if build.cxx_abi_enabled? + if build.cxx_exception_enabled? core_objs << build.compile_as_cxx("#{current_build_dir}/core/y.tab.c", "#{current_build_dir}/core/y.tab.cxx", objfile("#{current_build_dir}/y.tab"), ["#{current_dir}/core"]) << diff --git a/mrbgems/mruby-error/mrbgem.rake b/mrbgems/mruby-error/mrbgem.rake index b8281b17e..30a4259a8 100644 --- a/mrbgems/mruby-error/mrbgem.rake +++ b/mrbgems/mruby-error/mrbgem.rake @@ -3,7 +3,7 @@ MRuby::Gem::Specification.new('mruby-error') do |spec| spec.author = 'mruby developers' spec.summary = 'extensional error handling' - if build.cxx_abi_enabled? + if build.cxx_exception_enabled? @objs << build.compile_as_cxx("#{spec.dir}/src/exception.c", "#{spec.build_dir}/src/exception.cxx") @objs.delete_if { |v| v == objfile("#{spec.build_dir}/src/exception") } end diff --git a/src/mruby_core.rake b/src/mruby_core.rake index abde441d5..4558493d9 100644 --- a/src/mruby_core.rake +++ b/src/mruby_core.rake @@ -4,11 +4,11 @@ MRuby.each_target do current_build_dir = "#{build_dir}/#{relative_from_root}" objs = Dir.glob("#{current_dir}/*.c").map { |f| - next nil if cxx_abi_enabled? and f =~ /(error|vm).c$/ + next nil if cxx_exception_enabled? and f =~ /(error|vm).c$/ objfile(f.pathmap("#{current_build_dir}/%n")) }.compact - if cxx_abi_enabled? + if cxx_exception_enabled? objs += %w(vm error).map { |v| compile_as_cxx "#{current_dir}/#{v}.c", "#{current_build_dir}/#{v}.cxx" } end self.libmruby << objs @@ -2583,3 +2583,7 @@ mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int sta return v; } + +#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus) +mrb_int mrb_jmpbuf::jmpbuf_id = 0; +#endif diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake index 46459cf6c..f5d4374d1 100644 --- a/tasks/mruby_build.rake +++ b/tasks/mruby_build.rake @@ -83,8 +83,9 @@ module MRuby @bins = [] @gems, @libmruby = MRuby::Gem::List.new, [] @build_mrbtest_lib_only = false - @cxx_abi_enabled = false + @cxx_exception_enabled = false @cxx_exception_disabled = false + @cxx_abi_enabled = false @enable_bintest = false @enable_test = false @toolchains = [] @@ -110,15 +111,28 @@ module MRuby end def disable_cxx_exception + if @cxx_exception_enabled or @cxx_abi_enabled + raise "cxx_exception already enabled" + end @cxx_exception_disabled = true end def enable_cxx_exception - @cxx_exception_disabled = false + return if @cxx_exception_enabled + return if @cxx_abi_enabled + if @cxx_exception_disabled + raise "cxx_exception disabled" + end + @cxx_exception_enabled = true compilers.each { |c| c.defines += %w(MRB_ENABLE_CXX_EXCEPTION) c.flags << c.cxx_exception_flag } + linker.command = cxx.command if toolchains.find { |v| v == 'gcc' } + end + + def cxx_exception_enabled? + @cxx_exception_enabled end def cxx_abi_enabled? @@ -127,9 +141,13 @@ module MRuby def enable_cxx_abi return if @cxx_abi_enabled - unless @cxx_exception_disabled - enable_cxx_exception + if @cxx_exception_enabled + raise "cxx_exception already enabled" end + compilers.each { |c| + c.defines += %w(MRB_ENABLE_CXX_EXCEPTION MRB_ENABLE_CXX_ABI) + c.flags << c.cxx_compile_flag + } compilers.each { |c| c.flags << c.cxx_compile_flag } linker.command = cxx.command if toolchains.find { |v| v == 'gcc' } @cxx_abi_enabled = true @@ -146,15 +164,13 @@ module MRuby #define __STDC_CONSTANT_MACROS #define __STDC_LIMIT_MACROS -#ifndef MRB_ENABLE_CXX_EXCEPTION +#ifndef MRB_ENABLE_CXX_ABI extern "C" { #endif #include "#{src}" -#ifndef MRB_ENABLE_CXX_EXCEPTION +#ifndef MRB_ENABLE_CXX_ABI } #endif - -#{src == "#{MRUBY_ROOT}/src/error.c"? 'mrb_int mrb_jmpbuf::jmpbuf_id = 0;' : ''} EOS end |
