# Web MLX42 supports compilation towards [WASM](https://webassembly.org/). What this means is you can run any application written in C directly in the browser! This overcomes a lot of issues with for instance showing projects towards others or have an environment where building natively just won't work. In this README you will learn how to compile your project towards Webassembly and later deploy it on github! ## Pre-requisites - [Emscripten](https://emscripten.org/), you can install this via brew or read the instructions they provide for [Windows or Linux](https://emscripten.org/docs/getting_started/downloads.html) ## Building Once you made sure you have emscripten installed (check if `emcc` and `emcmake` work). Run: ```bash emcmake cmake -B build && cmake --build build --parallel ``` ## Modifications You're only required to do a few modifications to your `main.c`. For this we will use the demo main provided in the root [readme](../README.md). Add the following headers at the top: ```c #include #include ``` Modify your main: ```c // Invoked instead of mlx_loop directly. void emscripten_main_loop() { mlx_loop(mlx); } int32_t main(int argc, char **argv) { // Gotta error check this stuff if (!(mlx = mlx_init(WIDTH, HEIGHT, "MLX42", true))) { puts(mlx_strerror(mlx_errno)); return(EXIT_FAILURE); } if (!(image = mlx_new_image(mlx, 128, 128))) { mlx_close_window(mlx); puts(mlx_strerror(mlx_errno)); return(EXIT_FAILURE); } if (mlx_image_to_window(mlx, image, 0, 0) == -1) { mlx_close_window(mlx); puts(mlx_strerror(mlx_errno)); return(EXIT_FAILURE); } mlx_loop_hook(mlx, ft_randomize, mlx); mlx_loop_hook(mlx, ft_hook, mlx); // This function will set up the main loop emscripten_set_main_loop(emscripten_main_loop, 0, true); mlx_terminate(mlx); return (EXIT_SUCCESS); } ``` Thats actually it! It may or may not be necessary to modify your own source code depending on what you do but that's most often not the case. It is that easy to just re-deploy your own app into webassembly. ## Building ```bash # Compile C into JS/WASM emcc -O3 -I include -I mlx -pthread main.c \ -o ./web/demo.js \ ./build/libmlx42.a \ -s USE_GLFW=3 -s USE_WEBGL2=1 -s FULL_ES3=1 -s WASM=1 \ -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' \ -s ALLOW_MEMORY_GROWTH # Navigate into the web folder (if you're running this directly from this repo) cd web # Launch local webserver, this is required to make the service worker function. python3 -m http.server 8000 ``` Once the server is up and running all you need to do now is go to [localhost](http://localhost:8000/index.html). There you can locally develop your application without having to do any git commits or actions shenanigans. # Deploying to Github Pages For a free, quick and easy hosting solution you can realistically deploy this anywhere. However for now we will only focus on putting this up via github pages. What you need in your repository is a `.github/workflows/static.yml` file. It can be named anything `static`, `ci`, whatever. Later on if you learn more about CI Pipelines you can use this to do a lot of useful things. ## Enabling github pages Follow this step: https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow Once selected, you need to commit an actions file. For now you can copy paste MLX42's `wasm.yml` file which functionally does the exact same. ```yml # Simple workflow for deploying static content to GitHub Pages name: Deploy static content to Pages on: push: branches: ["master"] # Change to main or whatever fancy name workflow_dispatch: permissions: contents: read pages: write id-token: write # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: "pages" cancel-in-progress: false # Single deploy job since we're just deploying jobs: deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest #TODO: add a build step to get the wasm file instead of commiting it. #Doesn't really matter atm since the git history is polluted anyway steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: './web' # <= Set this variable to the directory relative to the root of the repo. - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ``` Once you commit this file github will do it's magic and create a deployment. You should then get a link to where you can access you program. Now you can access your app anywhere!