Nuxi

Nuxi CloudABI for Debian, Ubuntu and other Debian derivatives

Though CloudABI has initially been developed on FreeBSD, a fairly complete implementation for the Linux kernel has also been developed.

This document explains how to develop software for CloudABI on Debian-based systems and how these systems can be configured to run this software. Right now this still requires you to perform a significant number of manual steps, but work is underway to streamline this process by packaging and upstreaming most of these components.

1. Installing a C and C++ compiler for CloudABI

CloudABI uses a toolchain based on LLVM, Clang and LLD for building C and C++ software. The version of Clang shipped with Debian (3.5.0) is not sufficient for compiling code for CloudABI, and only the upcoming version of LLD (3.9.0) is mature enough to generate executables properly. Until this version has been released and packaged by Debian, we advise that LLVM is built from trunk.

The following commands can be used to build LLVM, Clang and LLD from SVN and install them into /usr/local/llvm-trunk:

$ sudo apt-get install build-essential cmake ninja-build subversion $ svn co https://llvm.org/svn/llvm-project/llvm/trunk llvm $ svn co https://llvm.org/svn/llvm-project/cfe/trunk llvm/tools/clang $ svn co https://llvm.org/svn/llvm-project/lld/trunk llvm/tools/lld $ mkdir build $ cd build $ cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/llvm-trunk ../llvm ... -- Configuring done -- Generating done -- Build files have been written to: /home/ed/llvm/build $ ninja $ sudo ninja install

After installing LLVM, we can create a number of symbolic links in /usr/local/bin that point to the utilities provided by LLVM, having the CloudABI cross compilation target prefixed to their name. LLVM automatically acts like a cross compiler for CloudABI when invoked through these symbolic links.

for target in aarch64-unknown-cloudabi i686-unknown-cloudabi x86_64-unknown-cloudabi; do for tool in ar nm objdump ranlib size; do sudo ln -s ../llvm-trunk/bin/llvm-${tool} /usr/local/bin/${target}-${tool} done sudo ln -s ../llvm-trunk/bin/clang /usr/local/bin/${target}-cc sudo ln -s ../llvm-trunk/bin/clang /usr/local/bin/${target}-c++ sudo ln -s ../llvm-trunk/bin/lld /usr/local/bin/${target}-ld sudo ln -s ../../${target} /usr/local/llvm-trunk/${target} done

The commands above set up the Clang C and C++ compiler for every architecture supported by CloudABI, thus making it very easy to cross compile software for other hardware:

$ ls /usr/local/bin/*-unknown-cloudabi-{cc,c++} /usr/local/bin/aarch64-unknown-cloudabi-c++ /usr/local/bin/aarch64-unknown-cloudabi-cc /usr/local/bin/i686-unknown-cloudabi-c++ /usr/local/bin/i686-unknown-cloudabi-cc /usr/local/bin/x86_64-unknown-cloudabi-c++ /usr/local/bin/x86_64-unknown-cloudabi-cc

2. Accessing the CloudABI Ports Collection

The CloudABI Ports Collection provides copies of precompiled libraries that you can use to build complex CloudABI applications. Software that is part of the CloudABI Ports Collection is automatically packaged for a variety of systems, including Debian's apt-get.

The CloudABI Ports Collection can be accessed by adding both a repository to sources.list and a public signing key to apt-get's keyring:

$ sudo apt-get install apt-transport-https $ echo deb https://nuxi.nl/distfiles/cloudabi-ports/debian/ cloudabi cloudabi | sudo tee /etc/apt/sources.list.d/cloudabi.list deb https://nuxi.nl/distfiles/cloudabi-ports/debian/ cloudabi cloudabi $ wget -qO - 'https://pgp.mit.edu/pks/lookup?op=get&search=0x0DA51B8531344B15' | sudo apt-key add - OK $ sudo apt-get update Hit https://nuxi.nl cloudabi InRelease Hit https://nuxi.nl cloudabi/cloudabi amd64 Packages ...

It typically makes sense to at least install the standard C++ runtime environment package, so that it is possible to compile C and C++ applications that depend on just core C, C++ and POSIX interfaces:

$ sudo apt-get install x86-64-unknown-cloudabi-cxx-runtime The following NEW packages will be installed: x86-64-unknown-cloudabi-cloudlibc x86-64-unknown-cloudabi-compiler-rt x86-64-unknown-cloudabi-cxx-runtime x86-64-unknown-cloudabi-libcxx x86-64-unknown-cloudabi-libcxxabi x86-64-unknown-cloudabi-libunwind Do you want to continue? [Y/n] y

A full list of packages provided by the CloudABI Ports Collection can be obtained by running the following command:

$ grep -h ^Package: /var/lib/apt/lists/nuxi.nl* | sort -u Package: aarch64-unknown-cloudabi-boost Package: aarch64-unknown-cloudabi-bzip2 Package: aarch64-unknown-cloudabi-c-runtime Package: aarch64-unknown-cloudabi-cairo ...

3. Executing CloudABI applications

Our eventual goal is to provide support for CloudABI in the form of a kernel module that can be used in combination with a stock Linux kernel. Unfortunately we still depend on a fair number of local changes to the kernel that need to be upstreamed first, meaning that support for CloudABI is currently only available in the form of a modified Linux kernel with integrated CloudABI support.

The following instructions show how this kernel can be checked out, built, packaged and installed, all using the standard Debian kernel build scripts:

$ sudo apt-get install fakeroot git kernel-package $ git clone https://github.com/NuxiNL/linux.git Cloning into 'linux'... $ cd linux $ git branch -l * cloudabi $ cp /boot/config-$(uname -r) .config $ make oldconfig ... Enable clone4() system call (CLONE4) [Y/n/?] (NEW) y Enable CLONE_FD flag for clone4() (CLONEFD) [Y/n/?] (NEW) y ... Kernel support for CloudABI ELF binaries (BINFMT_ELF_CLOUDABI) [N/y/?] (NEW) y ... Capsicum capabilities (SECURITY_CAPSICUM) [Y/n/?] (NEW) y ... # configuration written to .config $ make-kpkg clean $ fakeroot make-kpkg -j4 --initrd --revision=1.0.cloudabi kernel_image ... dpkg-deb: building package 'linux-image-4.5.0-rc1-capsicum+' in '../linux-image-4.5.0-rc1-capsicum+_1.0.cloudabi_amd64.deb'. $ sudo dpkg -i ../linux-image-4.5.0-rc1-capsicum+_1.0.cloudabi_amd64.deb Selecting previously unselected package linux-image-4.5.0-rc1-capsicum+. Preparing to unpack linux-image-4.5.0-rc1-capsicum+_1.0.cloudabi_amd64.deb ... ... done $ sudo reboot

After rebooting, CloudABI executables can be executed directly:

$ cat hello.c #include <stdio.h> int main(void) { dprintf(1, "Hello, world\n"); } $ x86_64-unknown-cloudabi-cc -o hello hello.c $ ./hello Hello, world

It also makes sense to install the cloudabi-utils package that contains the cloudabi-run utility. This tool can be used to spawn CloudABI applications safely, ensuring that no resources are accidentally leaked into the process. It can be installed as follows:

$ sudo apt-get install libyaml-dev pkg-config $ git clone https://github.com/NuxiNL/cloudabi.git Cloning into 'cloudabi'... $ sudo install -m 444 cloudabi/headers/* /usr/local/include/ $ git clone https://github.com/NuxiNL/cloudabi-utils.git Cloning into 'cloudabi-utils'... $ cd cloudabi-utils $ CC=/usr/local/llvm-trunk/bin/clang cmake . $ make ... Linking C executable cloudabi-run [100%] Built target cloudabi-run $ sudo make install ... -- Installing: /usr/local/bin/cloudabi-run $ sudo ldconfig

The shell commands below show how cloudabi-run can be used to execute the CloudABI test suite. Please refer to cloudabi-run's manual page for more examples.

$ mkdir tmp-unittest $ cloudabi-run /usr/x86_64-unknown-cloudabi/bin/cloudlibc-unittests << EOF %TAG ! tag:nuxi.nl,2015:cloudabi/ --- tmpdir: !file path: tmp-unittest logfile: !fd stdout nthreads: !!int 8 EOF