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
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
name: Build Base Image
name: Build Image

on:
push:
branches: [ "main" ]
paths:
- 'Dockerfile.base'
- '.github/workflows/base-image.yml'
- 'Dockerfile'
- '.github/workflows/build-image.yml'
pull_request:
branches: [ "main" ]
paths:
- 'Dockerfile.base'
- '.github/workflows/base-image.yml'
- 'Dockerfile'
- '.github/workflows/build-image.yml'
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}-base
IMAGE_NAME: ${{ github.repository }}

jobs:
build-base-image:
build-image:
strategy:
matrix:
include:
- runner: ubuntu-22.04-arm
arch: arm64
build-args: ECV_AARCH64=1
- runner: ubuntu-22.04
arch: amd64
build-args: ECV_X86=1
runs-on: ${{ matrix.runner }}
permissions:
contents: read
Expand All @@ -43,10 +45,11 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build base image
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.base
file: Dockerfile
build-args: ${{ matrix.build-args }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ matrix.arch }}
77 changes: 60 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,65 @@
# syntax=docker/dockerfile:1

ARG TARGETARCH
ARG LLVM_VERSION=16
ARG BASE_IMAGE=ghcr.io/yomaytk/elfconv-base:${TARGETARCH}
ARG EMCC_VERSION=4.0.9
ARG UBUNTU_VERSION=22.04
ARG DISTRO_NAME=jammy

FROM ${BASE_IMAGE}
ARG LLVM_VERSION=16
# stage 1. System packages and toolchain installation
FROM ubuntu:${UBUNTU_VERSION} AS toolchain
ARG LLVM_VERSION
ARG DISTRO_NAME

RUN apt-get update && \
apt-get install -qqy --no-install-recommends \
apt-transport-https software-properties-common gnupg ca-certificates wget && \
apt-add-repository ppa:git-core/ppa --yes && \
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
echo "deb http://apt.llvm.org/${DISTRO_NAME}/ llvm-toolchain-${DISTRO_NAME}-${LLVM_VERSION} main" >> /etc/apt/sources.list && \
echo "deb-src http://apt.llvm.org/${DISTRO_NAME}/ llvm-toolchain-${DISTRO_NAME}-${LLVM_VERSION} main" >> /etc/apt/sources.list && \
apt-get update && \
apt-get install -qqy --no-install-recommends \
build-essential python3 pkg-config \
clang-${LLVM_VERSION} lld-${LLVM_VERSION} llvm-${LLVM_VERSION} llvm-${LLVM_VERSION}-dev libclang-${LLVM_VERSION}-dev \
ninja-build \
curl unzip tar git \
libc6-dev liblzma-dev zlib1g-dev \
binutils-dev libelf-dev libiberty-dev libdwarf-dev && \
apt-get upgrade --yes && apt-get clean --yes && \
rm -rf /var/lib/apt/lists/*

# cmake install
RUN wget "https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1-linux-$(uname -m).sh" && \
/bin/bash cmake-*.sh --skip-license --prefix=/usr/local && rm cmake-*.sh

# stage 2. SDK and WASI runtime installation
FROM toolchain AS sdks
ARG EMCC_VERSION

# emscripten install
RUN cd /root && git clone https://github.com/emscripten-core/emsdk.git && cd emsdk && \
./emsdk install ${EMCC_VERSION} && ./emsdk activate ${EMCC_VERSION} && \
. ./emsdk_env.sh && echo 'source "/root/emsdk/emsdk_env.sh"' >> /root/.bash_profile

# wasi-sdk install
RUN cd /root && \
export WASI_VERSION=24 && \
export WASI_VERSION_FULL=${WASI_VERSION}.0 && \
if [ "$(uname -m)" = "x86_64" ]; then \
export WASI_OS=linux WASI_ARCH=x86_64; \
elif [ "$(uname -m)" = "aarch64" ]; then \
export WASI_OS=linux WASI_ARCH=arm64; \
fi && \
printf 'export WASI_OS=%s\nexport WASI_ARCH=%s\nexport WASI_VERSION=%s\nexport WASI_VERSION_FULL=%s\nexport WASI_SDK_PATH=/root/wasi-sdk-%s-%s-%s\n' "${WASI_OS}" "${WASI_ARCH}" "${WASI_VERSION}" "${WASI_VERSION_FULL}" "${WASI_VERSION_FULL}" "${WASI_ARCH}" "${WASI_OS}" >> /root/.bash_profile && \
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-${WASI_ARCH}-${WASI_OS}.tar.gz && \
tar xvf wasi-sdk-${WASI_VERSION_FULL}-${WASI_ARCH}-${WASI_OS}.tar.gz && \
rm -f wasi-sdk-*.tar.gz

# WASI Runtimes install
RUN curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash
RUN curl https://wasmtime.dev/install.sh -sSf | bash && echo 'export PATH=$PATH:/root/.wasmtime/bin' >> /root/.bash_profile

# stage 3. build elfconv
FROM sdks AS resimg
ARG ROOT_DIR=/root/elfconv
ARG ECV_AARCH64
ARG ECV_X86
Expand All @@ -18,21 +72,10 @@ RUN if [ $(( ${ELFCONV_AARCH64:-0} ^ ${ELFCONV_X86:-0} )) -eq 0 ]; then \
exit 1; \
fi

# git settings
RUN git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" && git config --global user.name "github-actions[bot]"

WORKDIR ${ROOT_DIR}
COPY ./ ./

RUN apt-get update && apt-get install -qqy --no-install-recommends \
llvm-${LLVM_VERSION}-dev libclang-${LLVM_VERSION}-dev libcurl4-openssl-dev && \
rm -rf /var/lib/apt/lists/*

RUN ./scripts/build.sh
RUN if [ "${ELFCONV_AARCH64:-0}" = "1" ]; then \
make -C ~/elfconv/examples/hello/c hello_aarch64; \
elif [ "${ELFCONV_X86:-0}" = "1" ]; then \
make -C ~/elfconv/examples/hello/c hello_amd64; \
fi
RUN make -C /root/elfconv/examples/hello/c hello
ENTRYPOINT ["/bin/bash", "--login", "-c"]
CMD ["/bin/bash"]
59 changes: 0 additions & 59 deletions Dockerfile.base

This file was deleted.

43 changes: 28 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,39 +68,52 @@ We measured the performance of Wasm generated by elfconv against Wasm compiled d
## Quick Start
The easiest way to try elfconv is using Linux container, which supports both x86-64 and ARM64 hosts.

### Getting the Container
You can either pull a pre-built image from ghcr.io or build from source using the Dockerfile.

**Pull pre-built image (recommended):**
```bash
# For ARM64 hosts
$ docker pull ghcr.io/yomaytk/elfconv:arm64
# For x86-64 hosts
$ docker pull ghcr.io/yomaytk/elfconv:amd64
```

**Build from Dockerfile:**
```bash
$ git clone --recursive https://github.com/yomaytk/elfconv
$ cd elfconv
# For AArch64 ELF target
$ docker build . --build-arg ECV_AARCH64=1
# For x86-64 ELF target
$ docker build . --build-arg ECV_X86=1
```

### Usage
Choose your execution environment:
- **Option 1 - Browser**: Run Wasm in a web browser with terminal emulation
- **Option 2 - WASI Runtime**: Run Wasm on the host using WasmEdge or other WASI-compatible runtimes

### Option 1: Browser Execution
```bash
# 1. Build container
$ git clone --recursive https://github.com/yomaytk/elfconv
$ cd elfconv
$ docker build . --build-arg ECV_AARCH64=1 -t elfconv-image
# Note: ECV_AARCH64=1 for AArch64 ELF, ECV_X86=1 for x86-64 ELF

# 2. Run container with port forwarding
$ docker run -it --rm -p 8080:8080 --name elfconv-container elfconv-image
# 1. Run container with port forwarding
$ docker run -it -p 8080:8080 <image-name>

# 3. Convert ELF to Wasm
# 2. Convert ELF to Wasm
~/elfconv# cd bin
~/elfconv/bin# TARGET=aarch64-wasm INITWASM=1 ./exe.sh /path/to/ELF
# Example: TARGET=aarch64-wasm INITWASM=1 ./exe.sh ../examples/hello/c/a.aarch64

# 4. Start web server
# 3. Start web server
~/elfconv/bin# emrun --no_browser --port 8080 <ELFNAME>.html
```

Access the Wasm application from your browser at `http://localhost:8080/<ELFNAME>.html`

### Option 2: WASI Runtime Execution
```bash
# 1. Build and run container
$ git clone --recursive https://github.com/yomaytk/elfconv
$ cd elfconv
$ docker build . --build-arg ECV_AARCH64=1 -t elfconv-image
$ docker run -it --name elfconv-container elfconv-image
# 1. Run container
$ docker run -it <image-name>

# 2. Convert ELF to Wasm
~/elfconv# cd bin
Expand Down
28 changes: 4 additions & 24 deletions examples/hello/c/Makefile
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@
CC=clang-16

hello_aarch64: hello.c
@ARCH=$$( uname -m ); \
if [ "$$ARCH" = "x86_64" ]; then \
$(CC) -static -o a.aarch64 --target=aarch64-linux-gnu --gcc-toolchain=/usr --sysroot=/usr/aarch64-linux-gnu hello.c; \
aarch64-linux-gnu-strip a.aarch64 -o a_stripped.aarch64; \
elif [ "$$ARCH" = "aarch64" ]; then \
$(CC) -static -o a.aarch64 hello.c; \
strip a.aarch64 -o a_stripped.aarch64; \
else \
echo "Unknown architecture"; exit 1; \
fi

hello_amd64: hello.c
@ARCH=$$( uname -m ); \
if [ "$$ARCH" = "x86_64" ]; then \
$(CC) -static -o a.amd64 hello.c; \
strip a.amd64 -o a_stripped.amd64; \
elif [ "$$ARCH" = "aarch64" ]; then \
$(CC) -static -o a.amd64 --target=x86_64-linux-gnu --gcc-toolchain=/usr --sysroot=/usr/x86_64-linux-gnu hello.c; \
x86_64-linux-gnu-strip a.amd64 -o a_stripped.amd64; \
else \
echo "Unknown architecture"; exit 1; \
fi
hello: hello.c
$(CC) -static -o hello hello.c; \
strip hello -o hello_stripped; \

clean:
rm a.out
rm hello hello_stripped
2 changes: 1 addition & 1 deletion tests/elfconv/Run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ std::string exec_wasm(WASI_RUNTIME wasi_runtime) {

void unit_test_wasi_runtime(const char *program, const char *expected, WASI_RUNTIME wasi_runtime) {
// binary lifting
binary_lifting(("../../../examples/" + std::string(program) + "/a_stripped.aarch64").c_str());
binary_lifting(("../../../examples/" + std::string(program) + "/hello_stripped").c_str());
// generate wasm
gen_wasm_for_wasi_runtimes();
// execute wasm
Expand Down