Nuxi CloudABI for openSUSE

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 openSUSE 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. Though the version of Clang shipped with openSUSE 42.1 (3.7.0) is sufficient for compiling code for CloudABI, 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 openSUSE, 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 zypper install -y cmake gcc gcc-c++ ninja subversion $ svn co llvm $ svn co llvm/tools/clang $ svn co 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 RPMs for openSUSE.

The CloudABI Ports Collection can be accessed by adding a signing key and a configuration file for the repository to /etc/yum.repos.d:

$ sudo rpm --import '' $ sudo tee /etc/zypp/repos.d/cloudabi.repo << EOF [cloudabi-ports] name=CloudABI Ports baseurl= EOF $ sudo zypper update

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 zypper install -y x86_64-unknown-cloudabi-cxx-runtime ... (1/7) Installing: x86_64-unknown-cloudabi-cloudabi-0.6-1.noarch ..........[done] (2/7) Installing: x86_64-unknown-cloudabi-compiler-rt-3.8.0-3.noarch .....[done] (3/7) Installing: x86_64-unknown-cloudabi-cloudlibc-0.30-1.noarch ........[done] (4/7) Installing: x86_64-unknown-cloudabi-libcxx-3.8.0-5.noarch ..........[done] (5/7) Installing: x86_64-unknown-cloudabi-libunwind-3.8.0-4.noarch .......[done] (6/7) Installing: x86_64-unknown-cloudabi-libcxxabi-3.8.0-5.noarch .......[done] (7/7) Installing: x86_64-unknown-cloudabi-cxx-runtime-1.0-2.noarch .......[done]

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

$ zypper search -r cloudabi-ports S | Name | ... --+------------------------------------+---- | aarch64-unknown-cloudabi-boost | ... | aarch64-unknown-cloudabi-buddy | ... | aarch64-unknown-cloudabi-bzip2 | ... | aarch64-unknown-cloudabi-c-runtime | ... ...

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, using the standard RPM kernel build target:

$ sudo zypper install -y git rpm-build $ git clone 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 rpm ... Wrote: /home/ed/rpmbuild/RPMS/x86_64/kernel-4.5.0_cloudabi+-3.x86_64.rpm ... $ sudo rpm -i /home/ed/rpmbuild/RPMS/x86_64/kernel-4.5.0_cloudabi+-3.x86_64.rpm $ 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 zypper install -y gcc5 libyaml-devel $ git clone Cloning into 'cloudabi'... $ sudo install -m 444 cloudabi/headers/* /usr/local/include/ $ git clone Cloning into 'cloudabi-utils'... $ cd cloudabi-utils $ CC=gcc-5 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 !,2015:cloudabi/ --- tmpdir: !file path: tmp-unittest logfile: !fd stdout nthreads: !!int 8 EOF