How do I compile a C++ file to WebAssembly? - c++

Suppose I have a simple, self-contained C++ file (math.cpp) like this:
int add(int x, int y) {
return x + y;
}
How would I compile it to WebAssembly (math.wasm)?
Note: I am using the Clang tool-chain.

I found this gist to be very helpful.
Basically, this are the steps:
(build llvm and clang 5.0.0 or above with -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly)
Compile the .cpp soure to llvm bitcode with clang:
clang -emit-llvm --target=wasm32 -Oz math.cpp -c -o math.bc
Compile the bitcode to s-assembly:
llc -asm-verbose=false -o math.s math.bc
Use binaryen's s2wasm tool to create a .wast file
s2wasm math.s > math.wast
Use WABT's wast2wasm tool to translate the textual .wast file into binary .wasm:
wast2wasm -o math.wasm math.wast
Some of the steps feel redundant but I have not yet found a tool that allows shortcuts. (It would be nice if llc could compile directly to .wasm, or if s2wasm actually created binary .wasm files as the name suggests.) Anyway, once you got the toolchain running it's relatively painless. Note, however, that there are no C or C++ standard libraries for web assembly yet.
Alternatively, if you need the .wasm file just for trying out stuff you can get away without all the toolchain trouble. Browse to https://mbebenita.github.io/WasmExplorer/, paste in your C/C++ code, and download the compiled .wasm file.
Thank you #noontz and #LB-- for pointing out that
Actually as the comments in the gist suggest you can skip binaryen and compile straight to wasm from Clang/LLVM. I'm currently using the following command line for C++ :
clang++ test.cpp -ObjC++ --compile --target=wasm32-unknown-unknown-wasm \
--optimize=3 --output test.wasm

Emscripten comes with everything you will need to compile a C++ file to wasm. Emscripten also has an SDK that makes life easy when it comes to installing all the necessary tools.
By default, however, Emscripten will add some framework code to your wasm file as well as generate some html and javascript.
It is possible to create a minimal wasm file with Emscripten that doesn't include any framework code, javascript, or html. Using options -s SIDE_MODULE=1 -Oz -s ONLY_MY_CODE=1 while compiling with emcc or em++ will give you a minimal wasm file.
The following command would export a minimal wasm file using your examples and Emscripten:
em++ math.cpp -o math.wasm -Oz -s SIDE_MODULE=1 -s WASM=1 -s "EXPORTED_FUNCTIONS=['_add']" -s ONLY_MY_CODE=1

As of 2019, Clang (8) supports webassembly out of the box. Here is a repository that contains everything needed to compile, link and run a simple .wasm file.
https://github.com/PetterS/clang-wasm

Currently the easiest way to compile C and C++ is with emscripten. The components you mention are all components, but emscripten is a full toolchain that supports building end-to-end, and includes all the parts you need including libc/libc++, and a variety of other useful libraries. It supports targeting both asm.js and wasm.

Based on the answers in this thread, I've created a little guide.
For me, the easiest way was to compile emscripten (the website is also a great starting point!) on my machine, compile the code to wasm, generate the appropriate bindings and hide all this in a wrapper on the JS-Side to that I get a nice interface.
Because of the name mangling of c++, I've found getting started with C is easier.

A little late for this answer but there are beautiful tools online for compiling your scripts.
By example, I'm using this one. That one giving you minimim option of compiling (C,C++,std99...) but there are sufficient : https://wasdk.github.io/WasmFiddle/
And depending of how you gonna use it, you can choose between differents languages such as x86, code Buffer. You can also share your code, kind of functions that I find cool when you are working with some other buddy : https://wasdk.github.io/WasmFiddle/?gus9d :)

Related

How can I compile, assemble and link a C++ file using Clang?

I have been coding for over 5 years and would now like to take a step away from IDE's and try a project without one. I have the things I need to get started (I think), a HelloWorld.cpp file, the Windows Command Prompt open and Clang installed.
Now that I have these things my question is this - What do I need to type into the Command Prompt to make Clang take my C++ code in the HelloWorld.cpp file and compile it into a separate file containing the assembly code, and then make Clang take my assembly code and assemble it into a separate file containing the object code, and then finally make Clang take my object code and link it into a separate file containing the machine code?
Ultimately meaning at the end I will have 4 files, one with C++ code, one with assembly code, one with object code and finally one with machine code. The point of all of this being the ability to read and understand each stage of the process before running the file containing the machine code.
Being someone who has left the world of IDE's for the first time, I find the official Clang documentation very confusing and cannot find a straight answer to my question.
Same as with GCC, and I'll do you one better by first preprocessing the source file. In principle Clang also can emit LLVM bitcode or LLVM IR as two extra intermediate stages.
clang++ source.cpp -E
clang++ source.ii -S
clang++ source.s -c
clang++ source.o
This last one gives a.out as an executable file. You can define the output file for each command by appending
-o output.file
The extensions may not be 100% correct. Just check what comes out.

How to compile a cpp file directly from vim editor in Windows?

I've recently installed a vim editor in my Windows operating system.
I only know the conventional procedure i.e, creating the source file in the editor and running it from the command line. But,
I don't quite understand how to compile a CPP program directly from the vim editor.
when I run the command
:!g++ hello.cpp -o hello
from the vim command line, I get the following message
C:\WINDOWS\system32\cmd.exe /c (g++ hello.cpp -o hello)
Hit any key to close this window...
I assume your version of Vim is windows version and not cygwin version.
First you need to install a compiler, and make sure it's in your PATH.
Also, read the documentation about quickfix window as this is the integrated vim way of compiling. :!make or :!g++ ... are not the way to go.
MSVC
I don't suppose this is the compiler you have as I expect you'd have used Visual Studio in that case. Anyway, IIRC, there is a msdev compiler plugin you could load with :compiler msdev, then you should able to run :make.
Don't hesitate to complete my answer if you see errors.
g++ through cygwin
There is a big advantage: gnumake is properly configured: in the console you could run make foo, and if you have foo.cpp or foo.c and no Makefile in the current directory, this would compile the monofile project. In all cases, a Makefile is fine; and it's required with multiple source files.
The big problem: pathnames are not expressed in the same way. They need to be translated. I provide a way to do that in my Build-Tools-Wrapper plugin. Just execute :BTW add cygwin.
Then from vim, again type :make %<. That will translate into :make foo (assuming you're editing foo.cpp), which translates into make fooshell wise, which translates into $CXX $CPPFLAGS $CXXFLAGS $LDFLAGS foo.cpp -o foo $LDLIBS (or something like that).
Note: this means the options can be tweaked with: :let $CXXFLAGS = '-std=c++17 -Wall -Wextra'
BTW, if you have my build-tools-wrapper plugin, you can execute directly :Make instead of :make %<, or just <F5>directly, IIRC.
g++ through mingw
The good news: no need to translate pathnames
The bad news, gnumake isn't correctly configured. This means that in the console make foo won't work. And consequently, this won't work from Vim.
This time, you'll either need a Makefile, or you'll need to tweak 'makeprg' setting. Like for instance :let &makeprg = 'g++ -Wall -Wextra -std=c++17 -o %< %' and then type simply :make.

How to generate bitcode (.bc file) using emscripten with a cmake project?

I have a c++ project that I built with cmake. It compiles and links fine. The goal is to use Emscripten to generate code from it that will run in the browser.
From the docs on the Emscripten site here one finds:
After running the first two commands (emconfigure and emmake), seemingly successfully, I do not have any .bc file anywhere, although it actually does produce a .js and .wasm file. The docs imply there that the .js file would only result from executing the third command ./emcc.
A little further down on the same docs page you find:
Make generates linked LLVM bitcode. It does not automatically generate
JavaScript during linking because all the files must be compiled using
the same optimizations and compiler options — and it makes sense to do
this in the final conversion from bitcode to JavaScript.
so it seems it should produce some bitcode. How to do this?
(I did use the VERBOSE command as those docs suggest and although I do not see emcc being used instead of the native compiler, em++ is being used, which seems to mostly the same as emcc.)
When the Emscripten build system is used to build a project, it will always generate a bitcode file. This is regardless of the file extension of the default output file. It can't generate a different file, since that would confuse Make, with the file not being created that it was told would be. At the Emscripten website there is a note a short way down the page that says:
The file output from make might have a different suffix: .a for a static library archive, .so for a shared library, .o or .bc for object files (these file extensions are the same as gcc would use for the different types). Irrespective of the file extension, these files contain linked LLVM bitcode that emcc can compile into JavaScript in the final step. If the suffix is something else - like no suffix at all, or something like .so.1 - then you may need to rename the file before sending it to emcc.
Whatever files the build is supposed to create, even ones that are usually shared libraries, will always contain the bitcode, and can be linked directly with the rest of your project.
Edit:
I can only assume that the reason for the .js output file is because the CMake project is set up to produce an executable. It is possible that Emscripten is smart enough to create .js in that case, but I don't know for sure.
From the manpage of emscripten:
The target file, if specified (-o <target>), defines what will be generated:
<name>.js
JavaScript
<name>.html
HTML with embedded JavaScript
<name>.bc
LLVM bitcode (default)
<name>.o
LLVM bitcode (same as .bc)
I assume you can just then create a custom command where the output file has the extension .bc to produce bitcode. Seems like you could just skip the hassle potentially by going straight to producing .js from .c(pp).
Edit:
Alternatively, if you just want it as a side-effect and not the actual product:
--save-bc PATH
When compiling to JavaScript or HTML, this option will save a copy of the bitcode to the specified
path. The bitcode will include all files being linked, including standard libraries, and after any
link-time optimizations (if any).
Depending on the project, you may be able to skip configure entirely. In the past, i've specified C functions to export that my Wasm implementation would then use to quickly build from. Some C libraries require autogen to be run at a minimum, but I have bypassed configure for multi-dependency C projects.
# create bitcode library for WebAssembly module
$ emcc \
-o wasmlib.bc \
-s EXPORTED_FUNCTIONS="[ \
'_needed_c_function1' \
'_needed_c_function2', \
]" \
-I "c_lib_src/include" \
c_lib_src/*.c
# Quickly build using the bitcode we just created
$ emcc \
-o my_wasm_module.js \
-I "c_lib_src/include" \
wasmlib.bc \
my_wasm_impl.c
Up until Emscripten 1.38.x fastcomp you could use the CMake option EMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES set to ON and static libraries would end up being .bc files:
cmake -Bbuild -DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=ON
To check, inspected in a hex-editor those .bc files start with BC.
The option was removed (and throws an error) in recent upstream Emscripten versions (like 2.0.x). I still have to figure out, how it's done there.

How to execute yosys passes from an LLVM pass?

I have been working with two programs llvm's opt and clifford wolf's yosys both have similar interfaces for passes.(they use shared libraries as optimization passes)
I want to use certain data structures and functions from yosys.h to build a design module(which is then written in verilog to file) based on the data generated by my llvm opt pass.
PROBLEM:
I want to make use of functions,data from yosys.h in the pass for llvm-opt.
How do i compile(EDIT: and also execute either on llvm-opt or on yosys or a seperate binary executable) such code?
individually they can be compiled and executed as seperate passes.
COMPILE YOSYS PASS
gcc `yosys-config --cxxflags --ldlibs --ldflags` --shared yosyspass.cpp -o yosyspass.so
and execute it with
yosys -m yosyspass.so verilogfile.v
COMPILE LLVM PASS
gcc `llvm-config --cxxflags --ldlibs` --shared llvmpass.ccp -o llvmpass.so
and execute it with
opt -load ./llvmpass.so -llvmpass Somefile.bc
but how to build code which has both components from llvm , yosys?
and how to execute it?
How can i make this happen without changing source code of yosys too much?
All of this is to avoid writing a verilog generation backend for my llvm-opt pass.
ONE OF MY SOLUTIONS:
Metaprogramming: i.e., generate the code which when compiled and run as a yosys pass gives me the result.(verilog design file based on llvm opt input)
Maybe i'm missing something fundamental in build shared libraries? I'm new to this sort of thing. any input is welcome.
This project(though unrelated) may be similar to Rotems C-to-Verilog and univ of toronto's legup HLS tool.
As Krzysztof Kosiński pointed out, until now the Yosys core functionality was not available as library. However, this was on the todo list for a long time and I have now added this functionality to Yosys git head.
Here is a usage example:
// example.cc
#include <kernel/yosys.h>
int main()
{
Yosys::log_streams.push_back(&std::cout);
Yosys::log_error_stderr = true;
Yosys::yosys_setup();
Yosys::yosys_banner();
Yosys::run_pass("read_verilog example.v");
Yosys::run_pass("synth -noabc");
Yosys::run_pass("clean -purge");
Yosys::run_pass("write_blif example.blif");
Yosys::yosys_shutdown();
return 0;
}
Building a binary:
yosys-config --exec --cxx -o example --cxxflags --ldflags example.cc -lyosys -lstdc++
Now you can run ./example to convert example.v into example.blif.
(As this is a brand new feature, the details of how to build programs or other libraries using libyosys are likely to change in the future.)
Edit: In current git head the Makefile option ENABLE_LIBYOSYS must be set to 1 to enable building of libyosys.so.
Additional feedback: You might want to consider to write a Yosys plugin instead that implements a Yosys front-end that uses LLVM libraries to load a .bc file. If you are not planning to go back and forth between LLVM and Yosys, but only want execute a sequence of LLVM passes followed by a sequence of Yosys passes, then this solution might provide a more natural and easier to debug interface between LLVM and Yosys.

Can GCC compile and run a source code without generating object or executable files?

Can GCC compile and run a source code without generating any output file (neither object nor executable), in a manner that is supported cross-platform? Especially, a solution supported by GCC directly.
I want to avoid generation of any trace file since that is a minor code in a big project. It just messes up the bin directory.
An existing question, here, provides a solution for compiling source code without generating any output file, such as:
gcc somefile.c -o /dev/null
However, this only compiles, and doesn't run.
Another similar question here provides a solution that is specific to Windows OS, not cross-platform.
A simple bash script might help:
#!/bin/bash
echo 'compile... ' $1
gcc $1 && ./a.out && rm a.out
supposed it's named once, then you can do
$ sh once any.c
to compile any.c and just run it once.
You can also make once executable with chmod +x once so you can just type
$ once any.c
Hope it helps ;)
In order to compile and run the C / C++ program and then remove the compiled file, you should add a function to delete the program after it is executed.
Here is a link to an example of a program that deletes itself.
Click Here
In your case (you want to avoid cluttering the build tree), a practically useful solution might be to have some convention about temporary executables.
For example, you could decide that every intermediate executable or file is named *.tmp or _* or *.tmpbin (for temporary binaries) and have some Makefile rules which removes them. Or you could use mktemp(1) in your Makefile to get a temporary file name. Don't forget to remove it later.
Also, most big projects have a compilation step and an installing step (often make install); and if you don't have that you probably should. You want your installing step to avoid installing the temporary binaries or files; with some naming convention this is quite simple: the first command for install phony target in your Makefile would remove these temporary binaries or files.
Also, you generally build in a file tree different of the final bin/ directory, so you could leave the temporary executables in the build tree.
As several people noticed, removing its own executable is easy on Linux (do a readlink(2) on "/proc/self/exe" (see proc(5) for details) then unlink(2) the result of readlink....) but difficult on Windows.
So practically your question is not a very important issue.... (if you use suitable build conventions). And GCC work on files (because it will run ld internally to build that executable file); however GCCJIT is hiding them. AFAIK, you won't even be able to use /dev/stdout as the executable output of gcc (but you can run gcc -x c /dev/stdin to compile C code from stdin). So GCC cannot avoid making an executable file (but you could have it temporary, or in a tmpfs file system or a FUSE one). So you need something external to your gcc command (perhaps simple an rm in some following line of your Makefile) to remove the produced executable.
You could also decide to have (dynamically loaded) plugins (e.g. use dlopen(3) on Linux). Your main program could load a plugin (with  dlopen on Linux) - perhaps even after having generated dynamically its C++ code and having compiled that generated code into e.g. some shared object .so on Linux (or some DLL on Windows), as I do in MELT -, run functions in it obtained with dlsym, and unload the plugin (with dlclose on Linux) and finally remove it. You might use cross-platform frameworks like Qt or POCO to avoid dealing with OS specific plugin code.
For c gcc/g++ filname.c && ./a.out && rm a.out
For c++ g++ filename.cpp && ./a.out && rm a.out