Skip to content

uvapl/terra

Repository files navigation

Terra IDE

A preliminary logo for the Terra IDE

Exam website that ships with an editor and a terminal that can run C or Python code completely offline using WebAssembly.

Table of Contents

Getting Started

Simply clone the project:

git clone https://github.com/uvapl/terra && cd terra

You need some kind of tool that serves static files in order for everything to work, as it can't be run in file:///path/to/index.html.

One example is to use Python's http module: python3 -m http.server, then open localhost:8000 in your browser and enjoy.

Structure

.
├── index.html
└── static/
    ├── css/
    │   ├── include/                # Custom app CSS
    │   ├── main.embed.css          # Main css file when the embed is loaded
    │   ├── main.exam.css           # Main css file when the exam app is loaded
    │   ├── main.ide.css            # Main css file when the IDE is loaded
    │   └── vendor/                 # Third-party CSS
    ├── img/                        # App images, such as icons
    ├── js/
    │   ├── constants.js            # Global app constants
    │   ├── gitfs.js                # Bridge between app and Git worker
    │   ├── helpers/                # Global app helper functions
    │   ├── ide/                    # Additional IDE JS files
    │   ├── layout/                 # Main layout and component classes
    │   ├── lfs.js                  # Local filesystem main class
    │   ├── main.embed.js           # Bootstraps the embed app.
    │   ├── main.exam.js            # Bootstraps the exam app.
    │   ├── main.ide.js             # Bootstraps the IDE app.
    │   ├── main.shared.js          # Shared function among main.*.js files
    │   ├── vendor/                 # Third-party javascript files
    │   ├── vfs.js                  # Virtual Filesystem that emits to other filesystems (Git, LFS)
    │   ├── lang-worker-api.js      # Bridge between app and language other workers
    │   └── workers/                # Language specific workers that compiles and runs the code
    └── wasm                        # WASM files grouped per lang, loaded by corresponding worker

Adding custom header files to C

The static/wasm/sysroot.tar contains C++ standard headers and libraries.

Inspecting which header files are included can be done through

tar -tf static/wasm/sysroot.tar

Including another header .h file can be done by extracting the tar, adding the header and making a new tar. For example:

  • cd ./static/wasm/c_cpp/ make sure you're in this folder
  • tar -xvf sysroot.tar extract tar
  • cp my-header-file.h ./include/ add custom my-header-file.h to the include/ folder
  • tar --format ustar -cvf sysroot.tar include lib share make a new tar
  • rm -rf include lib share remove previously extracted folders

Create custom wasm32-wasi library

This project contains a custom wasm32-wasi cs50 build. This project currently uses wasi-sdk-5, which provides all the necessary functionality, despite being quite an outdated version.

To create a custom library archive .a file yourself, download the corresponding wasi-sdk-5.0-<PLATFORM>.tar.gz from here for your own platform. Then, extract this, for example, in your ~/Downloads folder.

In order to compile to wasm32-wasi, we need to use ~/Downloads/wasi-sdk-5.0/opt/wasi-sdk/bin/clang. Consecutively we need to use ~/Downloads/wasi-sdk-5.0/opt/wasi-sdk/bin/llvm-ar to create the archive .a file.

Start off with cd ./static/wasm/c_cpp/ and extract the sysroot.tar through tar -xvf sysroot.tar. This will extract 3 folder, namely include, lib and share.

Inside ./static/wasm/c_cpp/, create a temporary folder for your library. For the sake of this example, we'll call our library libfoo which we can later link through -lfoo. We'll create it through: mkdir libfoo.

Next, inside our libfoo/ folder we have 3 files: foo.c, foo.h and Makefile, with the following contents:

foo.c
#include <stdio.h>
#include "foo.h"

void say_hello() {
    printf("Hello from foo!\n");
}
foo.h
#ifndef FOO_H
#define FOO_H

void say_hello();

#endif /* FOO_H */
Makefile
CC = /Users/<USER>/Downloads/wasi-sdk-5.0/opt/wasi-sdk/bin/clang --sysroot=/Users/<USER>/Downloads/wasi-sdk-5.0/opt/wasi-sdk/share/sysroot
AR = /Users/<USER>/Downloads/wasi-sdk-5.0/opt/wasi-sdk/bin/llvm-ar
CFLAGS = -Wall -Wextra -I/Users/<USER>/Downloads/wasi-sdk-5.0/opt/wasi-sdk/share/sysroot/include

all: libfoo.a

libfoo.a: foo.o
	$(AR) rcs $@ $^

foo.o: foo.c foo.h
	$(CC) $(CFLAGS) -c -o $@ $<

clean:
	rm -f libfoo.a foo.o

The CFLAGS contains -I/Users/<USER>/Downloads/wasi-sdk-5.0/opt/wasi-sdk/share/sysroot/include which is needed because foo.c includes <stdio.h>. Since we compile to wasm32-wasi, we need to include the wasm32-wasi header files from the wasi-sdk.

When running make, you should have the libfoo.a.

Next, we go one folder up through cd .. and then copy the libfoo.a and foo.h to the corresponding folder of the sysroot.tar we extracted earlier:

$ cp ./libfoo/foo.h ./include
$ cp ./libfoo/libfoo.a ./lib/wasm32-wasi/

Next, we create a new tar:

rm sysroot.tar && tar -cvf sysroot.tar include lib share

Go into your browser settings, clear the cached web content and then finally you can go into the ./static/js/workers/clang.worker.js and add -lfoo to the this.ldflags inside the constructor:

class API extends BaseAPI {
  constructor(options) {

    // ...

    this.ldflags = ['-lc', '-lcs50', '-lfoo'];
  }
}

Packaging Python files in stdlib

See INSTALL_PY_PKG.md on how to add a python package to the pyodide environment.

Enable stdin

In order to enable stdin, the index.html (or any HTML-file that works with input) requires the following headers to be sent with every request:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

The above allows the usage of WebAssembly.Memory, which is needed to make shared memory work in order to make input work properly between the main thread and worker instances.

Acknowledgements

Thanks to wasm-clang for the amazing C/C++ in WASM implementation.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published