7 ms·
Show HN: How to compile C/C++ for WASM, pure Clang, no libs, no framework
A little help for programmers, who wants to run C/C++ code in the browser.
(This is my second attempt to show it, first time I got banned bcoz of my personal page domain, I don't really understand it why is is suspicious.)
- syrusakbary 4y agoThis is really awesome, good work! We did a similar thing running Clang on the browser, which is now uploaded to WAPM: https://wapm.io/syrusakbary/clang https://wapm.io/syrusakbary/clang
- hobo_mark 4y agoExcellent, I wonder if using a two year old LLVM fork is still required, wasm support should be in trunk by now.
- syrusakbary 4y agoRunning Clang with WASI requires compiling LLVM to WASI first, which unfortunately currently requires a fork (because of the "hackyness" of it, as some syscalls are mocked or certain code is just skipped). This talk from Ben Smith goes into a bit more depth on what was required to change on LLVM to compile to WASI: https://www.youtube.com/watch?v=5N4b-rU-OAA https://www.youtube.com/watch?v=5N4b-rU-OAA
- eatonphil 4y agoMeta comment: your committer email is not in sync with your profile so the Github UI shows the commits attached to a blank user. If you want these two in sync you can either add your committing email to your Github account or you can modify your git config to use your Github email as your commit email. Or you can just leave it as is too. :)
- ern0 4y agothx, fixed (hopefully)
- hobo_mark 4y agoThat is half of what I would need for a project, the other half being Clang itself running in the browser (to use for teaching). In theory there is [1] since many years, but in practice it never worked for me (even now I get "Runtime error: memory access out of bounds"). [1] https://tbfleming.github.io/cib/ https://tbfleming.github.io/cib/
- mbrock 4y agoIt’s not ready just yet but if you’re curious about Zig they’re going to have a nice self-hosted WebAssembly toolchain soon, with no LLVM dependency. I’m really looking forward to it and I’m happy to see the Zig compiler work making lots of progress these days. I hope I’ll be able to start playing with this in a couple of weeks or so.
- hobo_mark 4y agoI was quite excited about `zig cc (although I understand why they would want to throw LLVM away), but despite what the crab people shout all day I still need C++.
- randomsilence 4y agoDo you know https://webassembly-studio.kamenokosoft.com/ https://webassembly-studio.kamenokosoft.com/ ? I don't know if it compiles in the browser or on a server.
- hobo_mark 4y agoThat's fast! But it looks like it still needs a server, and I'd rather avoid giving the internet arbitrary code execution rights to some server I pay for and risk having my bill explode or my account terminated for abuse.
- randomsilence 4y agoChoose a supplier with a 100Mbit limit and unlimited bandwidth.
- david2ndaccount 4y agoI do a similar thing for my side project. Note that the clang that comes with Xcode (Apple clang) doesn’t have wasm support.
- ern0 4y agoThanks for warning! Anyway, I just got a new Mac, but I started with installing brew and then install CLANG comes with brew. I have had more headache with my not-too-but-old-enough Linux systems, 2 of 2 failed: one got stuck when linking (yes, the linker hangs!), another one produced perfect size .wasm output, with... wait for it... full of zero bytes. Full story here: https://stackoverflow.com/questions/71573019/cant-compile-to-wasm-on-linux https://stackoverflow.com/questions/71573019/cant-compile-to...
- gspr 4y agoVery cool! I've been desperately looking for something similar for Rust. I'm too old for all these magic frameworks and "deployers" :-) I have some Rust code, possibly linking in some objects compiled from C. How do I compile to wasm and deploy without magic? Any pointers?
- aquova 4y agoI made some emulators in Rust as a learning project during the start of the pandemic, and ran into the exact same issue when I wanted to make a wasm version to run in a browser. Eventually, I was able to figure out how to do it, although I do use the 'wasm-pack' Cargo package to assist with it (I think you can get away without it if you're really motivated, you just need to set up the targets and other elements yourself). Basically you define some Rust API to expose whatever you need from your project, then that and the project get compiled into one .wasm binary and some (surprisingly readable) JavaScript "glue" gets generated which allows for easy inclusion into a web page. It works well for code in the std, but I've had issues with 3rd party packages. It's focused on emulation development, but I wrote a document that describes the process I followed: https://github.com/aquova/chip8-book/blob/master/src/wasm.md https://github.com/aquova/chip8-book/blob/master/src/wasm.md
- melony 4y agoThis looks good! In my experience the hardest part for compiling WebAssembly is third party dependencies. Getting arbitrary libraries to build can be rather challenging.
- eeegnu 4y agoIt seems your first attempt to post this was flagged because the domain name sounds like it'll act like a redirect, and the page itself only had an image with no elaboration and just the link to github.
- jhgb 4y agoThis is exactly what I needed. Thanks!
- dosshell 4y agodirectly when reading this code I cannot help myself but to get into review-mode. It is an awesome example, which i will probably use myself one day. However... inc.cpp:27 Gray is not the average of RGB, it is usally approximated with `Y = 0.299 R + 0.587 G + 0.114 B`.
- Datagenerator 4y agoMarvelous example of the bikeshed effect
- jhgb 4y agoThat doesn't seem applicable unless there are bigger problems to solve that are being ignored.
- syrusakbary 4y agoFor future readers, this is the code that is being referred: https://github.com/ern0/howto-wasm-minimal/blob/master/inc.cpp#L31-L35 https://github.com/ern0/howto-wasm-minimal/blob/master/inc.c... It should be: uint32_t gray = 0.299 * ptr[i] + 0.587 * ptr[i+1] + 0.114 * ptr[i+2]; ptr[i] = gray; ptr[i+1] = gray; ptr[i+2] = gray;
- ern0 4y agoI know it (see: https://github.com/ern0/kolorwheel.js https://github.com/ern0/kolorwheel.js ), but I did not wanted use floats.
- Asooka 4y agoAlso, you must work in linear colour space. In OP's case you would have to apply the inverse sRGB transform, do the calculation, then apply the forward sRGB transform. Best if you just work with linear colour end to end, if you have the memory to spare.
- astrange 4y ago
- 0x20cowboy 4y agoNot trying to steal your thunder, but here is another nostdlib clang -> wasm example with malloc, a few math functions, rand, and writing to a canvas doing animation. => https://github.com/robrohan/wefx https://github.com/robrohan/wefx
- moefh 4y agoThis is really cool! I never looked into WASM before, I'm really happy to see it's not that difficult to build a simple example like this. One thing that's bothering me about that code is the declaration of `memory` as an uint8_t when it's clearly being used for its address: extern uint8_t memory; And then in a lot of places: uint8_t* ptr = &memory; ptr[FOO] = BAR; Declaring `memory` as an array is much more idiomatic C, and generates the exact same assembly: extern uint8_t memory[]; And then memory[FOO] = BAR; I just tested it, and it seems to work exactly as one would expect from a plain C linker (so there's no WASM magic I can see). Am I missing something?
- jstimpfle 4y agoPedantically, it might even be undefined behaviour (not sure, maybe a point of contention, similar to container_of macro). It's unlikely to cause problems, but the way you suggested is better (and can even be accompanied by a length field). Thank you to the author though! It is a nice little example.
- deleted 4y ago[deleted]
- bla3 4y agoThese are also good resources on using wasm without dependencies: https://depth-first.com/articles/2019/10/16/compiling-c-to-webassembly-and-running-it-without-emscripten/ https://depth-first.com/articles/2019/10/16/compiling-c-to-w... https://github.com/diekmann/wasm-fizzbuzz https://github.com/diekmann/wasm-fizzbuzz
- petters 4y agoSee also my example I put together some time ago: https://github.com/PetterS/clang-wasm https://github.com/PetterS/clang-wasm At the time, I could not find something like this online. It's fun to write your own malloc! :-)
- drfuchs 4y ago(Obligatory:) Neat! Still, a lot of copying bits around, and more JS than one might hope for. Could you send a pointer to canvas into the C code and operate on it in a direct, zero-copy way there?
- brrrrrm 4y agoUnfortunately, you cannot. https://stackoverflow.com/questions/42806037/modify-canvas-from-wasm https://stackoverflow.com/questions/42806037/modify-canvas-f...
- pulse7 4y agoIs there a similar example for C?
- nhatcher 4y agoShameless plug: https://github.com/nhatcher/matrix-algebra https://github.com/nhatcher/matrix-algebra
- ern0 4y agoJust rename the file and remove extern "C" stuff :). It started as C, but then I switched to CPP, to see, can I export simple symbol names, not mangled ones C++ produces. Anyway, you can use C++ as C, using just as many C++ features as you need. (Insert "throwing the guy out of window" meme picture here.)
- aquova 4y agoIf anyone is curious, I wrote a guide on Chip-8 emulation in Rust, and the final step was building the emulator to work in a browser via WASM. I do use a Cargo package to assist with targets and compilation, but other than that it allows you to build and load a wasm module into any old website. https://github.com/aquova/chip8-book/blob/master/src/wasm.md https://github.com/aquova/chip8-book/blob/master/src/wasm.md
- flohofwoe 4y agoSince I haven't seen it mentioned in the comments yet, here's another interesting project in the general area of "WASM without Emscripten": https://github.com/schellingb/wajic https://github.com/schellingb/wajic This provides an alternative implementation of Emscripten's EM_JS() magic (embed Javascript snippets right in the C/C++ source code), but without requiring a full Emscripten SDK installation. It still needs some additional tools next to Clang though, so it sits somewhere between "pure Clang" and "full Emscripten SDK".