Skip to content
Open
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
1 change: 1 addition & 0 deletions cpp-bye/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/out/
12 changes: 12 additions & 0 deletions cpp-bye/Config.uk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Configure C++ Bye application. Use C++ libraries.

config APPCPPBYE
bool "Configure C++ Bye"
default y

# Select C++ libraries.
select LIBCOMPILER_RT
select LIBCXX
select LIBCXXABI
select LIBUNWIND
select LIBMUSL
14 changes: 14 additions & 0 deletions cpp-bye/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
UK_ROOT ?= $(PWD)/../repos/unikraft
UK_BUILD ?= $(PWD)/out
UK_APP ?= $(PWD)
LIBS_BASE = $(PWD)/../repos/libs
UK_LIBS := $(LIBS_BASE)/libcxxabi:$(LIBS_BASE)/libcxx:$(LIBS_BASE)/libunwind:$(LIBS_BASE)/compiler-rt:$(LIBS_BASE)/musl

.PHONY: all

all:
@$(MAKE) -C $(UK_ROOT) L=$(UK_LIBS) A=$(UK_APP) O=$(UK_BUILD)

$(MAKECMDGOALS):
@$(MAKE) -C $(UK_ROOT) L=$(UK_LIBS) A=$(UK_APP) O=$(UK_BUILD) $(MAKECMDGOALS)

3 changes: 3 additions & 0 deletions cpp-bye/Makefile.uk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$(eval $(call addlib,appbyecpp))

APPBYECPP_SRCS-y += $(APPBYECPP_BASE)/bye.cpp
271 changes: 271 additions & 0 deletions cpp-bye/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
# C++ Hello on Unikraft

Build and run a C++ Hello program on Unikraft.
Follow the instructions below to set up, configure, build and run C++ Hello.
Make sure you installed the [requirements](../README.md#requirements).

## Quick Setup (aka TLDR)

For a quick setup, run the commands below.
Note that you still need to install the [requirements](../README.md#requirements).

To build and run the application for `x86_64`, use the commands below:

```console
test -d ../repos/unikraft || git clone https://github.com/unikraft/unikraft ../repos/unikraft
test -d ../repos/libs/libcxxabi || git clone https://github.com/unikraft/lib-libcxxabi ../repos/libs/libcxxabi
test -d ../repos/libs/libcxx || git clone https://github.com/unikraft/lib-libcxx ../repos/libs/libcxx
test -d ../repos/libs/libunwind || git clone https://github.com/unikraft/lib-libunwind ../repos/libs/libunwind
test -d ../repos/libs/compiler-rt || git clone https://github.com/unikraft/lib-compiler-rt ../repos/libs/compiler-rt
test -d ../repos/libs/musl || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl
make distclean
echo -e 'CONFIG_PLAT_KVM=y\nCONFIG_PLAT_KVM_VMM_QEMU=y\nCONFIG_ARCH_X86_64=y\nCONFIG_LIBCOMPILER_RT=y\nCONFIG_LIBCXX=y\nCONFIG_LIBCXXABI=y\nCONFIG_LIBUNWIND=y\nCONFIG_LIBMUSL=y' > /tmp/defconfig
UK_DEFCONFIG=/tmp/defconfig make defconfig
make -j $(nproc)
qemu-system-x86_64 -nographic -m 8 -cpu max -kernel out/cpp-bye_qemu-x86_64
```

This will configure, build and run the application, resulting in a `Hello from Unikraft!` message being printed.

To do the same for `AArch64`, run the commands below:

```console
test -d ../repos/unikraft || git clone https://github.com/unikraft/unikraft ../repos/unikraft
test -d ../repos/libs/libcxxabi || git clone https://github.com/unikraft/lib-libcxxabi ../repos/libs/libcxxa>
test -d ../repos/libs/libcxx || git clone https://github.com/unikraft/lib-libcxx ../repos/libs/libcxx
test -d ../repos/libs/libunwind || git clone https://github.com/unikraft/lib-libunwind ../repos/libs/libunwi>
test -d ../repos/libs/compiler-rt || git clone https://github.com/unikraft/lib-compiler-rt ../repos/libs/com>
test -d ../repos/libs/musl || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl
make distclean
echo -e 'CONFIG_PLAT_KVM=y\nCONFIG_PLAT_KVM_VMM_QEMU=y\nCONFIG_ARCH_ARM_64=y\nCONFIG_LIBCOMPILER_RT=y\nCONFIG_LIBCXX=y\nCONFIG_LIBCXXABI=y\nCONFIG_LIBUNWIND=y\nCONFIG_LIBMUSL=y' > /tmp/defconfig
UK_DEFCONFIG=/tmp/defconfig make defconfig
make -j $(nproc)
qemu-system-aarch64 -nographic -machine virt -m 8 -cpu max -kernel out/cpp-bye_qemu-arm64
```

Similar to the `x86_64` build, this will result in a `Hello from Unikraft!` message being printed.

Information about every step and about other types of builds is detailed below.

## Set Up

Set up the [`unikraft` repository](https://github.com/unikraft/unikraft).
Clone it in `../repos/unikraft/` if not already cloned:

```console
test -d ../repos/unikraft || git clone https://github.com/unikraft/unikraft ../repos/unikraft
test -d ../repos/libs/libcxxabi || git clone https://github.com/unikraft/lib-libcxxabi ../repos/libs/libcxxabi
test -d ../repos/libs/libcxx || git clone https://github.com/unikraft/lib-libcxx ../repos/libs/libcxx
test -d ../repos/libs/libunwind || git clone https://github.com/unikraft/lib-libunwind ../repos/libs/libunwind
test -d ../repos/libs/compiler-rt || git clone https://github.com/unikraft/lib-compiler-rt ../repos/libs/compiler-rt
test -d ../repos/libs/musl || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl
```

If you want use a custom variant of the repository (e.g. apply your own patch, make modifications), update it accordingly in the `../repos/` directory.

## Clean

While not strictly required, it is safest to clean the previous build artifacts:

```console
make distclean
```

## Configure

To configure the kernel, use:

```console
make menuconfig
```

In the console menu interface, choose the target architecture (x86_64 or ARMv8 or ARMv7) and platform (Xen or KVM/QEMU or KVM/Firecracker).

The end result will be the creation of the `.config` configuration file.

## Build

Build the application for the current configuration:

```console
make -j $(nproc)
```

This results in the creation of the `out/` directory storing the build artifacts.
The unikernel application image file is `out/cpp-bye_<plat>-<arch>`, where `<plat>` is the platform name (`qemu`, `fc`, `xen`), and `<arch>` is the architecture (`x86_64` or `arm64`).

### Use a Different Compiler

If you want to use a different compiler, such as a Clang or a different GCC version, pass the `CC` variable to `make`.

To build with Clang, use the commands below:

```console
make properclean
make CC=clang -j $(nproc)
```

Note that Clang >= 14 is required to build Unikraft.

To build with another GCC version, use the commands below:

```console
make properclean
make CC=gcc-<version> -j $(nproc)
```

where `<version>` is the GCC version, such as `11`, `12`.

Note that GCC >= 8 is required to build Unikraft.

## Clean Up

Doing a new configuration, or a new build may require cleaning up the configuration and build artifacts.

In order to remove the build artifacts, use:

```console
make clean
```

In order to remove fetched files also, that is the removal of the `out/` directory, use:

```console
make properclean
```

In order to remove the generated `.config` file as well, use:

```console
make distclean
```

## Run

Run the resulting image using the corresponding platform tool.
Firecracker requires KVM support.
Xen requires a system with Xen installed.

A successful run will show a message such as the one below:

```text
Booting from ROM..Powered by
o. .o _ _ __ _
Oo Oo ___ (_) | __ __ __ _ ' _) :_
oO oO ' _ `| | |/ / _)' _` | |_| _)
oOo oOO| | | | | (| | | (_) | _) :_
OoOoO ._, ._:_:_,\_._, .__,_:_, \___)
Calypso 0.17.0~5d38d108
Hello from Unikraft!
```

### Run on QEMU/x86_64

```console
qemu-system-x86_64 -nographic -m 8 -cpu max -kernel out/cpp-bye_qemu-x86_64
```

### Run on QEMU/ARM64

```console
qemu-system-aarch64 -nographic -machine virt -m 8 -cpu max -kernel out/cpp-bye_qemu-arm64
```

### Run on Firecracker/x86_64

```console
rm -f firecracker.socket
firecracker-x86_64 --config-file fc.x86_64.json --api-sock firecracker.socket
```

The user running the above command must be able to use KVM.
Typically this means being part of the `kvm` group.
Otherwise, run the command above as root or prefixed by `sudo`.

### Run on Firecracker/ARM64

```console
rm -f firecracker.socket
firecracker-aarch64 --config-file fc.arm64.json --api-sock firecracker.socket
```

The user running the above command must be able to use KVM.
Typically this means being part of the `kvm` group.
Otherwise, run the command above as the `root` account or prefixed by `sudo`.

### Run on Xen/x86_64

```console
sudo xl create -c xen.x86_64.cfg
```

You need use `sudo` or the `root` account to run Xen.

### Run on Xen/ARM64

```console
sudo xl create -c xen.arm64.cfg
```

You need use `sudo` or the `root` account to run Xen.

## Customize
### Update the Unikraft Core Code

If updating the Unikraft core code in the `../repos/unikraft/` directory, you then go through the [configure](#configure), [build](#build) and [run](#run) steps.

### Add Other Source Code Files

The current configuration use a single source file: `bye.cpp`.
If looking to add another file to the build, update the [`Makefile.uk`](Makefile.uk) file.

For example, to add a new file `support.cpp` to the build, update the [`Makefile.uk`](Makefile.uk) file to:

```make
$(eval $(call addlib,appbyeworldcpp))

APPHELLOWORLDCPP_SRCS-y += $(APPHELLOWORLDCPP_BASE)/bye.cpp
APPHELLOWORLDCPP_SRCS-y += $(APPHELLOWORLDCPP_BASE)/support.cpp
```

To add a new include directory, such as a local `include/` directory, update the [`Makefile.uk`](Makefile.uk) file to:

```make
$(eval $(call addlib,appbyeworldcpp))

APPHELLOWORLDCPP_SRCS-y += $(APPHELLOWORLDCPP_BASE)/bye.cpp
CINLUDES-y += -I$(APPHELLOWORLDCPP_BASE)/include
```

Then go through the [configure](#configure), [build](#build) and [run](#run) steps.

### Add Other Libraries

It may be the case that you want to add a library to the build, in order to test the library or a certain feature.
If that is the case, update the `UK_LIBS` variable in the [`Makefile`](Makefile).

For example, to add the Musl library to the build, clone the [`lib-musl` library repository](https://github.com/unikraft/lib-musl):

```console
test -d ../repos/libs/musl || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl
```

and update the `UK_LIBS` line the [`Makefile`](Makefile) to:

```make
UK_LIBS ?= $(LIBS_BASE)/musl
```

To add another library, such as LWIP, clone the [corresponding `lib-lwip` repository](https://github.com/unikraft/lib-musl):

```console
test -d ../repos/libs/lwip || git clone https://github.com/unikraft/lib-lwip ../repos/libs/lwip
```

and update the `UK_LIBS` line the [`Makefile`](Makefile) to:

```make
UK_LIBS ?= $(LIBS_BASE)/musl:$(LIBS_BASE)/lwip
```

Then go through the [configure](#configure), [build](#build) and [run](#run) steps.
54 changes: 54 additions & 0 deletions cpp-bye/README.scripts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Scripts for C++ Bye on Unikraft

These are companions instruction to the main instructions in the [`README`](README.md).

Use scripts as quick actions for building and running C++ Bye on Unikraft.

## Build for <plat> / <arch>:

```console
./build.<plat>.<arch>
```

e.g.:

```console
./build.qemu.x86_64
./build.qemu.arm64
./build.fc.x86_64
./build.xen.arm64
```

## Build for <plat> / <arch> using a different compiler

```console
CC=/path/to/compiler ./build.<plat>.<arch>
```

e.g.

```console
CC=/usr/bin/gcc-12 ./build.qemu.x86_64
CC=/usr/bin/aarch64-linux-gnu-gcc-12 ./build.qemu.arm64
CC=/usr/bin/clang ./build.qemu.x86_64
CC=/usr/bin/clang ./build.qemu.arm64
CC=/usr/bin/gcc-12 ./build.fc.x86_64
CC=/usr/bin/aarch64-linux-gnu-gcc-12 ./build.fc.arm64
CC=/usr/bin/clang ./build.fc.x86_64
CC=/usr/bin/clang ./build.fc.arm64
```

## Run on <plat> / <arch>

```console
./run.<plat>.<arch>
```

e.g.

```console
./run.qemu.x86_64
./run.qemu.arm64
./run.fc.x86_64
./run.xen.arm64
```
18 changes: 18 additions & 0 deletions cpp-bye/build.fc.arm64
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

test -d "../repos/unikraft" || git clone https://github.com/unikraft/unikraft ../repos/unikraft
test -d "../repos/libs/libcxxabi" || git clone https://github.com/unikraft/lib-libcxxabi ../repos/libs/libcxxabi
test -d "../repos/libs/libcxx" || git clone https://github.com/unikraft/lib-libcxx ../repos/libs/libcxx
test -d "../repos/libs/libunwind" || git clone https://github.com/unikraft/lib-libunwind ../repos/libs/libunwind
test -d "../repos/libs/compiler-rt" || git clone https://github.com/unikraft/lib-compiler-rt ../repos/libs/compiler-rt
test -d "../repos/libs/musl" || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl

make distclean
UK_DEFCONFIG=$(pwd)/defconfig.fc.arm64 make defconfig
touch Makefile.uk
make prepare
if test -z "$CC"; then
make -j $(nproc)
else
make CC="$CC" -j $(nproc)
fi
18 changes: 18 additions & 0 deletions cpp-bye/build.fc.x86_64
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

test -d "../repos/unikraft" || git clone https://github.com/unikraft/unikraft ../repos/unikraft
test -d "../repos/libs/libcxxabi" || git clone https://github.com/unikraft/lib-libcxxabi ../repos/libs/libcxxabi
test -d "../repos/libs/libcxx" || git clone https://github.com/unikraft/lib-libcxx ../repos/libs/libcxx
test -d "../repos/libs/libunwind" || git clone https://github.com/unikraft/lib-libunwind ../repos/libs/libunwind
test -d "../repos/libs/compiler-rt" || git clone https://github.com/unikraft/lib-compiler-rt ../repos/libs/compiler-rt
test -d "../repos/libs/musl" || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl

make distclean
UK_DEFCONFIG=$(pwd)/defconfig.fc.x86_64 make defconfig
touch Makefile.uk
make prepare
if test -z "$CC"; then
make -j $(nproc)
else
make CC="$CC" -j $(nproc)
fi
Loading