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

Compile mruby with emscripten (or: how to include compiler in cross build) #5453

Closed
sasq64 opened this issue May 19, 2021 · 12 comments
Closed

Comments

@sasq64
Copy link
Contributor

sasq64 commented May 19, 2021

I am trying to build mruby for the web using emscripten, but I get two undefined symbols;

wasm-ld: error: CMakeFiles/toy.html.dir/src/toy.cpp.o: undefined symbol: mrb_load_string
wasm-ld: error: CMakeFiles/toy.html.dir/src/toy.cpp.o: undefined symbol: mrb_load_file

Emscripten works differently than normal c-compilers so errors like this are not too uncommon, but I just wonder;

Is there anything special about those two functions compared to other mrb-functions, since those are the only ones giving me trouble ?

@sasq64
Copy link
Contributor Author

sasq64 commented May 19, 2021

Examining the contents og librmuby.a and libmruby_core.a I see that they contain the same files, whereas in the PC build libmruby.a contains a lot more files, including y.tab.o.

And checking the build output, it seems y.tab.c is still compiled using normal gcc, even though I specified

MRuby::Toolchain.new('emscripten') do |conf|

  toolchain :clang
  
  conf.cc.command = 'emcc'
  conf.cxx.command = 'em++'
  conf.linker.command = 'em++'
  conf.archiver.command = 'emar'

end

... so I guess I have missed something in the config ?

@sasq64
Copy link
Contributor Author

sasq64 commented May 19, 2021

Ok so it seems this use case is no really supported ? A cross build does not include the compiler and can not load code dynamically ?
I think I solved it by building a non-cross build and copying over the bin tools from my non emscripten build.

What would be involved with supporting a cross build that included the compiler ?

@sasq64 sasq64 changed the title Compile mruby with emscripten (wasm) Compile mruby with emscripten (or: how to include compiler in cross build) May 19, 2021
@dearblue
Copy link
Contributor

@sasq64
Copy link
Contributor Author

sasq64 commented May 19, 2021

No, that PR does not include the compiler, like I noticed.

By the way, I am now running successfully running an mruby REPL in the browser, so the compiler in included, but I have to do the manual step mentioned above.

@zzak
Copy link
Contributor

zzak commented May 19, 2021

I think compiler has to be built using host environment, but it should be possible to build only the compiler as a separate build target and copy them like you suggested.

@sasq64
Copy link
Contributor Author

sasq64 commented May 20, 2021

Yes, and I wonder what needs to change in the build environment to allow this behavior.

@YunzheZJU
Copy link

Hi, Have you solved your problem?

Several months ago I successfully compiled the mruby compiler into WASM. It can execute ruby scripts which are dynamically inputted by the user (like p 'Hello world' which eventually log a string in the console) in the browser env.

Basically it first

  • cross-builds mruby library targeting WebAssembly(which outputs lib/libmruby.a),
  • then compiles mruby library (included with my own c source files) to wasm(which outputs mruby.mjs and mruby.wasm)
  • and finally bundles mruby wasm and Javascript sources files of my own.

I don't quite understand the meaning of your include the compiler but if you are going to achieve a similar target as mine, I'd like to share more details about my build config.

@sasq64
Copy link
Contributor Author

sasq64 commented Jun 10, 2021

Right now I my mruby.cfg contains both a Build and a CrossBuild, and will fail when it tries to run the binaries in the host/bin dir (like mrbc) because it was built for emscripten. So then I just copy over the binaries from the PC build and build again, and I get a complete emscripten build.

If you have a config that allows me to skip this hack that wold be great.

But it's working, you can test it at http://apone.org/toy/

(It even supports blocking IO, like
name = gets() ; puts "hello #{name}"
... can you guess how that works ? :)

@matz
Copy link
Member

matz commented Jun 11, 2021

Sorry for being late to reply.

mrb_load_string and mrb_load_file are functions provided by mruby-compiler gem. So you have to specify the gem for the target side as well. So your config file should be like:

MRuby::Toolchain.new('emscripten') do |conf|

  toolchain :clang
  
  conf.cc.command = 'emcc'
  conf.cxx.command = 'em++'
  conf.linker.command = 'em++'
  conf.archiver.command = 'emar'

  conf.gem :core => 'mruby-compiler'   ## << add this line
end

@sasq64
Copy link
Contributor Author

sasq64 commented Jun 11, 2021

Thank you, now it builds.
But I am missing some other core things. Like 'p()' so I guess there are some other gems I should add also ?

@sasq64
Copy link
Contributor Author

sasq64 commented Jun 11, 2021

I just replaced the gem line with
conf.gembox 'default'
which game me a full build

@matz
Copy link
Member

matz commented Jun 11, 2021

FYI, 'p' is in the mruby-print gem.

@matz matz closed this as completed Jun 11, 2021
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

5 participants