Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions Dockerfile.x86_64
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# using ubuntu 20 docker image
FROM ubuntu:focal
# using ubuntu 24.04 (noble) docker image
FROM ubuntu:noble

ENV LLVM_VERSION=13
ENV WASI_SDK_VERSION=12

ARG DEBIAN_FRONTEND=noninteractive
ARG HEY_URL=https://hey-release.s3.us-east-2.amazonaws.com/hey_linux_amd64
ARG WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
ARG SHFMT_URL=https://github.com/mvdan/sh/releases/download/v3.2.4/shfmt_v3.2.4_linux_amd64
ARG SHELLCHECK_URL=https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz
Expand All @@ -28,10 +27,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
binutils-dev \
cmake \
git \
libtinfo5 \
libtool \
pkg-config

# The repo is bind-mounted from the host, so its files are owned by the host user
# while the build runs as root (docker exec -u 0). Modern git rejects this as
# "dubious ownership", so whitelist any directory for all users in the image.
RUN git config --system --add safe.directory '*'

# Needed to install from http endpoints via curl or wget
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
Expand All @@ -43,12 +46,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
wget

# Test Script Stuff
# hey is a load generator used by the test workloads (noble ships it in universe;
# the previously-used hey-release S3/GCS binaries now return 403)
RUN apt-get update && apt-get install -y --no-install-recommends \
bc \
fonts-dejavu \
fonts-cascadia-code \
fonts-roboto \
gnuplot \
hey \
httpie \
imagemagick \
jq \
Expand All @@ -57,11 +63,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
pango1.0-tools \
wamerican

# Hey is a load generator we have to recklessly download from the 'net, as it is only published to brew
# Binaries are only provided for AMD64 though, so ARM will have to build from source
# See https://github.com/rakyll/hey
RUN wget $HEY_URL -O hey && chmod +x hey && mv hey /usr/bin/hey

# shfmt is a formatter for shell scripts
RUN wget $SHFMT_URL -O shfmt && chmod +x shfmt && mv shfmt /usr/local/bin/shfmt
RUN wget $SHELLCHECK_URL -O shellcheck && chmod +x shellcheck && mv shellcheck /usr/local/bin/shellcheck
Expand All @@ -84,12 +85,14 @@ RUN ./sledge/install_llvm.sh $LLVM_VERSION
RUN curl -sS -L -O $WASI_SDK_URL && dpkg -i wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb && rm -f wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
ENV WASI_SDK_PATH=/opt/wasi-sdk

# Create non-root user and add to sudoers
ARG USERNAME=dev
# Non-root user and sudoers.
# Ubuntu noble (24.04) already ships a default non-root login user "ubuntu" at
# UID/GID 1000 (real shell + /home/ubuntu, in the sudo group) intended to be the
# account you work as, so reuse it rather than creating a second user at 1000
# (which would collide on UID 1000 and fail).
ARG USERNAME=ubuntu
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN groupadd --gid $USER_GID $USERNAME
RUN useradd --uid $USER_UID --gid $USER_GID -m $USERNAME
RUN apt-get update && apt-get install -y sudo
RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
RUN chmod 0440 /etc/sudoers.d/$USERNAME
Expand All @@ -109,7 +112,12 @@ RUN cd sledge && ./fix_root.sh
# Rust
# Rustup does not cleanly support system installs, so install as non-root user
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain stable --component rustfmt --target wasm32-wasi -y
ENV PATH=/home/dev/.cargo/bin:$PATH
ENV PATH=/home/ubuntu/.cargo/bin:$PATH
# `make install` runs as root (docker exec -u 0), but Rust is installed for the
# ubuntu user. Point rustup/cargo at ubuntu's install so root resolves the default
# toolchain instead of failing with "no default is configured".
ENV RUSTUP_HOME=/home/ubuntu/.rustup
ENV CARGO_HOME=/home/ubuntu/.cargo
RUN cargo install --debug cargo-audit cargo-watch rsign2

# We need to set the locale for pango-view
Expand Down
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,12 @@ applications:
applications.clean:
make -C applications clean

# Instead of having two copies of wasm_apps, just link to the awsm repo's copy
# Instead of having two copies of wasm_apps, just link to the awsm repo's copy.
# -f -n make this idempotent: the symlink is committed to the repo, so it already
# exists on a fresh clone and on rebuilds; without these flags ln fails with
# "File exists" and breaks `make install`.
wasm_apps:
ln -sr awsm/applications/wasm_apps/ applications/
ln -srfn awsm/applications/wasm_apps/ applications/wasm_apps

# Tests
.PHONY: test
Expand Down
36 changes: 26 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,11 @@

## Setting up a development environment

### Native on Debian Host
SLEdge's `aWsm` compiler is built against a **specific LLVM version (LLVM 13)** via the `llvm-alt` Rust bindings. Those bindings use LLVM C-API functions (e.g. `LLVMBuildCall`, `LLVMBuildLoad`) that were **removed in LLVM 15+**, so the build will fail to link against newer LLVM toolchains.

```sh
git clone https://github.com/gwsystems/sledge-serverless-framework.git
cd sledge-serverless-framework
./install_deb.sh
source ~/.bashrc
make install
make test
```
**For this reason, the Docker environment below is the recommended way to build SLEdge.** It pins the exact Ubuntu + LLVM 13 + WASI SDK toolchain that the compiler needs, and works on any host with Docker (macOS, Windows/WSL2, or any Linux distribution). To build directly on a Debian or Ubuntu host instead — including Ubuntu 24.04 (noble) — see [Native build](#native-build-linux-debian-or-ubuntu-including-2404-noble) below.

### Docker
### Docker (recommended)

**Note: These steps require Docker. Make sure you've got it installed!**

Expand Down Expand Up @@ -75,6 +68,29 @@ If you are finished working with the SLEdge runtime and wish to remove it, run t

And then simply delete this repository.

### Native build (Linux: Debian or Ubuntu, including 24.04 noble)

`install_deb.sh` installs the full toolchain directly on the host — the apt dependencies, **LLVM 13**, the WASI SDK, and a Rust toolchain — after which `make install` builds the runtime and the sample functions.

On **Ubuntu 24.04 (noble)** neither the distro nor `apt.llvm.org/noble` provides LLVM 13, so `install_llvm.sh` automatically pins the **focal** `apt.llvm.org` repository for LLVM 13 and installs the two focal-era runtime libraries that noble dropped (`libtinfo5`, `libffi7`). This path is validated on Ubuntu 24.04.4 (noble), x86_64: `aWsm`, `libsledge`, the runtime, and all nine sample `*.wasm.so` modules compile, and the resulting `sledgert` binary runs.

```sh
git clone https://github.com/gwsystems/sledge-serverless-framework.git
cd sledge-serverless-framework
./install_deb.sh
source ~/.bashrc
make install
make test
```

**Caveats:**

- `install_deb.sh` requires `sudo` and uses `update-alternatives` to point the default `clang`, `wasm-ld`, and `llvm-config` at version 13. On a host that already runs a newer LLVM as its default (e.g. noble's system clang), this changes that default system-wide.
- On noble the toolchain is pinned to focal-era LLVM 13 packages, which are on an older support track; the `apt.llvm.org/focal` and `archive.ubuntu.com` `.deb` URLs it relies on may eventually move or disappear.
- The sample functions are C, compiled with the WASI SDK's clang, so a Rust `wasm32-wasi`/`wasm32-wasip1` target is not required to build them.

On a distribution where neither the native repositories nor the focal fallback provide LLVM 13, use the Docker route above instead.

## Running your first serverless function

An SLEdge serverless function consists of a shared library (\*.so) and a JSON configuration file that determines how the runtime should execute the serverless function. As an example, here is the configuration file for our sample fibonacci function:
Expand Down
4 changes: 3 additions & 1 deletion install_deb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ sudo apt-get update && sudo apt-get install -y --no-install-recommends \
jq \
less \
libssl-dev \
libtinfo5 \
libtool \
libz3-4 \
lsb-release \
Expand All @@ -64,6 +63,9 @@ sudo apt-get update && sudo apt-get install -y --no-install-recommends \

wget $SHFMT_URL -O shfmt && chmod +x shfmt && sudo mv shfmt /usr/local/bin/shfmt

# Installs LLVM $LLVM_VERSION. On Ubuntu noble this pins the focal apt.llvm.org
# repo and pulls the focal-era libtinfo5/libffi7 the LLVM 13 packages need (noble
# dropped libtinfo5, which is why it is no longer in the apt list above).
sudo ./install_llvm.sh $LLVM_VERSION

curl -sS -L -O $WASI_SDK_URL && sudo dpkg -i wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb && rm -f wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
Expand Down
60 changes: 49 additions & 11 deletions install_llvm.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,48 @@
#!/bin/bash
# Installs LLVM tooling, delegating the to the LLVM script as much as possible
# Installs LLVM tooling for the SLEdge x86_64 dev image.
#
# On most releases this just delegates to the upstream apt.llvm.org installer.
# On Ubuntu noble (24.04) that doesn't work: apt.llvm.org never published an
# llvm-toolchain-noble-13 repo (only 18/19+), and SLEdge is pinned to LLVM 13
# (awsm builds against an LLVM-13 binding fork). So on noble we pin the *focal*
# apt.llvm.org repo instead, plus the two focal-era runtime libs noble dropped
# (libtinfo5, libffi7) that the focal LLVM packages depend on.
set -e

LLVM_VERSION=$1

echo "Installing LLVM $LLVM_VERSION"

# Script Installs clang, lldb, lld, and clangd
curl --proto '=https' --tlsv1.2 -sSf https://apt.llvm.org/llvm.sh | bash -s -- "$LLVM_VERSION"
CODENAME="$(. /etc/os-release && echo "$VERSION_CODENAME")"

if [ "$CODENAME" = "noble" ]; then
echo "Detected Ubuntu noble: pinning the focal apt.llvm.org repo for LLVM $LLVM_VERSION"

# focal-era runtime libs no longer shipped by noble, required by focal LLVM debs
cd /tmp
curl -fsSL -o libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.2-0ubuntu2.1_amd64.deb
curl -fsSL -o libffi7.deb http://archive.ubuntu.com/ubuntu/pool/main/libf/libffi/libffi7_3.3-4_amd64.deb
dpkg -i libtinfo5.deb libffi7.deb
rm -f libtinfo5.deb libffi7.deb

wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor -o /usr/share/keyrings/llvm.gpg
echo "deb [signed-by=/usr/share/keyrings/llvm.gpg] http://apt.llvm.org/focal/ llvm-toolchain-focal-$LLVM_VERSION main" \
> /etc/apt/sources.list.d/llvm.list
apt-get update

# Note: lldb-$LLVM_VERSION is intentionally omitted. The focal lldb package
# depends on libpython3.8, which noble no longer provides, and the debugger is
# not needed to build SLEdge.
apt-get install -y --no-install-recommends \
"clang-$LLVM_VERSION" \
"lld-$LLVM_VERSION" \
"clangd-$LLVM_VERSION" \
"llvm-$LLVM_VERSION" \
"llvm-$LLVM_VERSION-dev"
else
# Upstream installer: installs clang, lldb, lld, and clangd
curl --proto '=https' --tlsv1.2 -sSf https://apt.llvm.org/llvm.sh | bash -s -- "$LLVM_VERSION"
fi

# Installing "libc++-xx-dev" automagically installs "libc++1-xx", "libunwind-xx" and "libunwind-xx-dev"
apt-get install -y --no-install-recommends \
Expand All @@ -16,14 +52,16 @@ apt-get install -y --no-install-recommends \
"clang-tidy-$LLVM_VERSION" \
"clang-format-$LLVM_VERSION"

update-alternatives --remove-all wasm-ld
update-alternatives --remove-all llvm-config
update-alternatives --remove-all llvm-objdump
update-alternatives --remove-all llvm-dis
update-alternatives --remove-all clang-format
update-alternatives --remove-all clang
update-alternatives --remove-all clang++
update-alternatives --remove-all clang-tidy
# --remove-all clears any prior registration; harmless if none exists (so do not
# let "no alternatives" abort the script under set -e).
update-alternatives --remove-all wasm-ld 2> /dev/null || true
update-alternatives --remove-all llvm-config 2> /dev/null || true
update-alternatives --remove-all llvm-objdump 2> /dev/null || true
update-alternatives --remove-all llvm-dis 2> /dev/null || true
update-alternatives --remove-all clang-format 2> /dev/null || true
update-alternatives --remove-all clang 2> /dev/null || true
update-alternatives --remove-all clang++ 2> /dev/null || true
update-alternatives --remove-all clang-tidy 2> /dev/null || true

update-alternatives --install /usr/bin/wasm-ld wasm-ld "/usr/bin/wasm-ld-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-config llvm-config "/usr/bin/llvm-config-$LLVM_VERSION" 100
Expand Down
Loading