Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linker failures when building mruby as C++ #5818

Closed
lopopolo opened this issue Oct 24, 2022 · 5 comments
Closed

Linker failures when building mruby as C++ #5818

lopopolo opened this issue Oct 24, 2022 · 5 comments

Comments

@lopopolo
Copy link
Contributor

I am attempting to compile mruby as C++ with clang to make use of the MRB_USE_CXX_EXCEPTION compile time macro.

I am encountering several linker failures. Spot checking some of these errors, they appear to be functions defined in a .c implementation file without a corresponding header declaration, which are then declared in another .c implementation file.

If a function is to be declared in a .c implementation file without a header, I believe the declaration needs to be surrounded with:

#ifdef __cplusplus
extern "C" {
#endif
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self); 
#ifdef __cplusplus
}
#endif

Additionally, most (all?) mrbgems implementation files are not wrapped with extern "C" blocks which means the dynamically generated code to init and finalize mrbgems will not link.

Example

mrb_f_send

Implementation

mruby/src/vm.c

Lines 671 to 675 in 1bec339

mrb_value
mrb_f_send(mrb_state *mrb, mrb_value self)
{
mrb_sym name;
mrb_value block, *regs;

Function Declarations

mruby/src/class.c

Lines 2894 to 2895 in 1bec339

/* implementation of #send method */
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);

/* implementation of #send method */
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);

Linker Failures

Error log
  = note: Undefined symbols for architecture x86_64:
            "mrb_f_send(mrb_state*, mrb_value)", referenced from:
                mrb_init_class(mrb_state*) in libartichoke_backend-e554f197f1f28d74.rlib(class.o)
               (found _mrb_f_send in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(vm.o), declaration possibly missing extern "C")
            "mrb_ci_bidx(mrb_callinfo*)", referenced from:
                _mrb_get_args in libartichoke_backend-e554f197f1f28d74.rlib(class.o)
               (found _mrb_ci_bidx in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(vm.o), declaration possibly missing extern "C")
            "mrb_ci_nregs(mrb_callinfo*)", referenced from:
                mark_context_stack(mrb_state*, mrb_context*) in libartichoke_backend-e554f197f1f28d74.rlib(gc.o)
                gc_gray_counts(mrb_state*, mrb_gc*, RBasic*) in libartichoke_backend-e554f197f1f28d74.rlib(gc.o)
               (found _mrb_ci_nregs in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(vm.o), declaration possibly missing extern "C")
            "mrb_free_symtbl(mrb_state*)", referenced from:
                _mrb_close in libartichoke_backend-e554f197f1f28d74.rlib(state.o)
               (found _mrb_free_symtbl in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(artichoke_backend-e554f197f1f28d74.3o8b47riikvcw61n.rcgu.o), declaration possibly missing extern "C")
            "mrb_init_symtbl(mrb_state*)", referenced from:
                mrb_init_core(mrb_state*) in libartichoke_backend-e554f197f1f28d74.rlib(init.o)
               (found _mrb_init_symtbl in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(artichoke_backend-e554f197f1f28d74.3o8b47riikvcw61n.rcgu.o), declaration possibly missing extern "C")
            "mrb_init_mrbgems(mrb_state*)", referenced from:
                init_mrbgems(mrb_state*, void*) in libartichoke_backend-e554f197f1f28d74.rlib(state.o)
               (found _mrb_init_mrbgems in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(gem_init.o), declaration possibly missing extern "C")
            "artichoke_exc_throw(mrb_state*, mrb_value)", referenced from:
                _mrb_exc_raise in libartichoke_backend-e554f197f1f28d74.rlib(error.o)
                mrb_core_init_abort(mrb_state*) in libartichoke_backend-e554f197f1f28d74.rlib(error.o)
               (found _artichoke_exc_throw in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(artichoke_backend-e554f197f1f28d74.30fsnmw1u664pw99.rcgu.o), declaration possibly missing extern "C")
            "mrb_mod_module_eval(mrb_state*, mrb_value)", referenced from:
                mrb_init_class(mrb_state*) in libartichoke_backend-e554f197f1f28d74.rlib(class.o)
               (found _mrb_mod_module_eval in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(vm.o), declaration possibly missing extern "C")
            "mrb_obj_instance_eval(mrb_state*, mrb_value)", referenced from:
                mrb_init_class(mrb_state*) in libartichoke_backend-e554f197f1f28d74.rlib(class.o)
               (found _mrb_obj_instance_eval in /Users/lopopolo/dev/artichoke/artichoke/target/debug/deps/libartichoke_backend-e554f197f1f28d74.rlib(vm.o), declaration possibly missing extern "C")
            "_mrb_exc_set", referenced from:
                _mrb_vm_exec in libartichoke_backend-e554f197f1f28d74.rlib(vm.o)
                argnum_error(mrb_state*, long long) in libartichoke_backend-e554f197f1f28d74.rlib(vm.o)
                localjump_error(mrb_state*, localjump_error_kind) in libartichoke_backend-e554f197f1f28d74.rlib(vm.o)
                check_target_class(mrb_state*) in libartichoke_backend-e554f197f1f28d74.rlib(vm.o)
            "_mrb_format_float", referenced from:
                _mrb_float_to_str in libartichoke_backend-e554f197f1f28d74.rlib(numeric.o)
            "_mrb_method_added", referenced from:
                _mrb_vm_exec in libartichoke_backend-e554f197f1f28d74.rlib(vm.o)
            "_mrb_method_missing", referenced from:
                prepare_missing(mrb_state*, mrb_value, unsigned int, RClass**, unsigned int, unsigned short*, mrb_value, int) in libartichoke_backend-e554f197f1f28d74.rlib(vm.o)
            "_mrb_mruby_class_ext_gem_final", referenced from:
                _artichoke_mrbgem_mruby_class_ext_gem_final in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_class_ext_gem_init", referenced from:
                _artichoke_mrbgem_mruby_class_ext_gem_init in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_eval_gem_final", referenced from:
                _artichoke_mrbgem_mruby_eval_gem_final in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_eval_gem_init", referenced from:
                _artichoke_mrbgem_mruby_eval_gem_init in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_fiber_gem_final", referenced from:
                _artichoke_mrbgem_mruby_fiber_gem_final in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_fiber_gem_init", referenced from:
                _artichoke_mrbgem_mruby_fiber_gem_init in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_metaprog_gem_final", referenced from:
                _artichoke_mrbgem_mruby_metaprog_gem_final in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_metaprog_gem_init", referenced from:
                _artichoke_mrbgem_mruby_metaprog_gem_init in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_method_gem_final", referenced from:
                _artichoke_mrbgem_mruby_method_gem_final in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_method_gem_init", referenced from:
                _artichoke_mrbgem_mruby_method_gem_init in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_pack_gem_final", referenced from:
                _artichoke_mrbgem_mruby_pack_gem_final in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_pack_gem_init", referenced from:
                _artichoke_mrbgem_mruby_pack_gem_init in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_proc_ext_gem_final", referenced from:
                _artichoke_mrbgem_mruby_proc_ext_gem_final in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_proc_ext_gem_init", referenced from:
                _artichoke_mrbgem_mruby_proc_ext_gem_init in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_sprintf_gem_final", referenced from:
                _artichoke_mrbgem_mruby_sprintf_gem_final in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_mruby_sprintf_gem_init", referenced from:
                _artichoke_mrbgem_mruby_sprintf_gem_init in libartichoke_backend-e554f197f1f28d74.rlib(mrbgems.o)
            "_mrb_obj_missing", referenced from:
                prepare_missing(mrb_state*, mrb_value, unsigned int, RClass**, unsigned int, unsigned short*, mrb_value, int) in libartichoke_backend-e554f197f1f28d74.rlib(vm.o)
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)
@matz
Copy link
Member

matz commented Oct 29, 2022

Hmm, those functions are internal functions so that they should not be accessed from outside libmruby.a.
It is probably caused by the situation specific to artichoke. We should investigate the issue further.

@dearblue
Copy link
Contributor

dearblue commented Nov 1, 2022

I think that direct compilation as C++ is limited to the conf.enable_cxx_abi equivalent (with MRB_USE_CXX_EXCEPTION and MRB_USE_CXX_ABI).

https://github.com/artichoke/artichoke/blob/lopopolo/c-unwind-mrb_raise-panic/artichoke-backend/build.rs is conf.enable_cxx_ exception equivalent (with MRB_USE_CXX_EXCEPTION only), it appears to compile everything in mruby directly as C++.

The mruby build system normally compiles as C, even with conf.enable_cxx_exception.
Only files that use the MRB_TRY() or MRB_THROW() macro functions need to be compiled as C++, but may not be compiled as C++ directly.
For example, for the mruby/src/vm.c file, the file mruby/build/<TARGET>/src/vm-cxx.cxx is generated and compiled indirectly via #include.


The following is a possible solution on the artichoke side.

Change the build system of artichoke to mimic part of the mruby build system.
Normally compile as C, and only compile necessary files as C++ via wrapper files.

Files that need C++ compilation can be checked with git grep.

% git grep --name-only -w -e MRB_TRY --or -e MRB_THROW -- '*.c'
mrbgems/mruby-compiler/core/codegen.c
mrbgems/mruby-compiler/core/y.tab.c
src/error.c
src/gc.c
src/vm.c

@lopopolo
Copy link
Contributor Author

lopopolo commented Nov 2, 2022

thanks for the context @dearblue. When using conf.enable_cxx_exception are the C sources compiled with -fexceptions? If not, I believe unwinding over C functions is UB. This is why I was intending to compile mruby all as C++.

@dearblue
Copy link
Contributor

dearblue commented Nov 2, 2022

When using conf.enable_cxx_exception are the C sources compiled with -fexceptions?

Yes, I checked the command with rake -v and -fexceptions was added.

The conf.enable_cxx_exception method adds the necessary flags for each compiler.
https://github.com/mruby/mruby/blob/3.1.0/lib/mruby/build.rb#L208

The actual flags for each compiler are defined in the tool chain.
(gcc/clang) https://github.com/mruby/mruby/blob/3.1.0/tasks/toolchains/gcc.rake#L21
(msvc) https://github.com/mruby/mruby/blob/3.1.0/tasks/toolchains/visualcpp.rake#L18

@lopopolo
Copy link
Contributor Author

I worked around my issues by modifying the source in lieu of using mruby's code generated CXX stubs.

@lopopolo lopopolo closed this as not planned Won't fix, can't repro, duplicate, stale Nov 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants