Nuxi CloudABI for FreeBSD, TrueOS and DragonFly BSD

As CloudABI has been inspired by FreeBSD's Capsicum sandboxing framework, it goes without saying that support for CloudABI on FreeBSD has been rock solid from day one. FreeBSD's implementation of CloudABI is treated as a reference platform.

This document explains how to develop software for CloudABI on FreeBSD and how FreeBSD can be used to run this software. These instructions also apply to TrueOS and partially to DragonFly BSD. DragonFly BSD cannot run CloudABI software yet, but can still be used for software development purposes.

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

A complete toolchain for CloudABI based on LLVM, Clang and LLD is already provided by both the FreeBSD and DragonFly BSD Ports Collections. This toolchain can be installed by running the following command:

$ sudo pkg install cloudabi-toolchain New packages to be INSTALLED: cloudabi-toolchain: 1.4 pkgconf: 0.9.12_1 llvm-devel: 3.9.d20160502 ... Proceed with this action? [y/N]: y

This package installs a copy of 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 toolchain provided by the operating system does not ship with any code that has been cross compiled for CloudABI, meaning it cannot be used to build CloudABI applications on its own. Cross compiled libraries and tools are instead provided by the CloudABI Ports Collection. Software that is part of the CloudABI Ports Collection is automatically packaged for a variety of systems, including FreeBSD's pkg.

The CloudABI Ports Collection can be accessed by adding both a repository snippet and a public signing key to pkg's configuration directory. This can be accomplished by running the following commands:

$ sudo pkg install -y ca_root_nss $ sudo mkdir -p /usr/local/etc/pkg/repos $ sudo tee /usr/local/etc/pkg/repos/CloudABI.conf << EOF CloudABI: { url: signature_type: pubkey pubkey: /usr/local/etc/pkg/repos/CloudABI.key } EOF $ sudo tee /usr/local/etc/pkg/repos/CloudABI.key << EOF -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7WeFa5CRgGzaJjsMuc4g sBmBN54eazb7W97TC7jhZUMdtx+MguAomC0ducBPbuZtW1UQkIRY6FaVvMNOV/iE /7k/Nlf8Et/JdHpS6EwFhYL4RB3AH1hM5TASvljZupBJQlVZ0bjsrkLrwTqHvj7X BkqKEiJ5hNp/qOS2waCxuvqN1v4pU2Goyaf0xuRa9kCmJtSviiKXIFb4B8RYtMvd hScf6H2bt0pqXGK0TvLbwESPv0Ez2jc3yqJ4rSx4oq5r/aXEd4lZZKYZkq44hNsa ZdP5tV/tJLnDMof87iduXVme8WqmKgmXrMYwDU1UBriFpEQOVz/59JlyvCmlWZtm 7wIDAQAB -----END PUBLIC KEY----- EOF $ sudo pkg update ... CloudABI repository update completed. 166 packages processed.

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 pkg install x86_64-unknown-cloudabi-cxx-runtime New packages to be INSTALLED: x86_64-unknown-cloudabi-cxx-runtime: 1.0_2 [CloudABI] x86_64-unknown-cloudabi-compiler-rt: 3.8.0_3 [CloudABI] x86_64-unknown-cloudabi-libcxxabi: 3.8.0_5 [CloudABI] x86_64-unknown-cloudabi-libcxx: 3.8.0_5 [CloudABI] x86_64-unknown-cloudabi-cloudabi: 0.6_1 [CloudABI] x86_64-unknown-cloudabi-cloudlibc: 0.30_1 [CloudABI] x86_64-unknown-cloudabi-libunwind: 3.8.0_4 [CloudABI] Proceed with this action? [y/N]: y

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

$ pkg search -r CloudABI '.*' aarch64-unknown-cloudabi-boost-1.60.0_10 aarch64-unknown-cloudabi-buddy-2.4_9 aarch64-unknown-cloudabi-bzip2-1.0.6_9 aarch64-unknown-cloudabi-c-runtime-1.0_2 ...

3. Executing CloudABI applications

Support for running CloudABI executables is provided by the cloudabi, cloudabi32 and cloudabi64 kernel modules. The first kernel module implements all of the CPU architecture independent functionality, whereas the two latter implement system calls for 32-bits and 64-bits CPUs specifically.

These kernel modules have been integrated into the FreeBSD source tree, meaning that FreeBSD 11.0 and TrueOS ship with CloudABI support out of the box. The kernel modules can be loaded at runtime using kldload:

$ cat hello.c #include <stdio.h> int main(void) { dprintf(1, "Hello, world\n"); } $ x86_64-unknown-cloudabi-cc -o hello hello.c $ ./hello ELF binary type "17" not known. $ sudo kldload cloudabi64 $ kldstat Id Refs Address Size Name 1 4 0xffffffff80200000 1e7f940 kernel 2 1 0xffffffff82221000 5a61 cloudabi64.ko 3 1 0xffffffff82227000 b167 cloudabi.ko $ ./hello Hello, world

These modules can also be loaded automatically at system boot time by adding cloudabi32_load="YES" or cloudabi64_load="YES" to /boot/loader.conf.

The FreeBSD Ports Collection also provides 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. 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.

$ sudo pkg install cloudabi-utils New packages to be INSTALLED: cloudabi-utils: 0.11 [FreeBSD] libyaml: 0.1.6_2 [FreeBSD] Proceed with this action? [y/N]: y $ mkdir tmp-unittest $ cloudabi-run /usr/local/x86_64-unknown-cloudabi/bin/cloudlibc-unittests << EOF %TAG !,2015:cloudabi/ --- tmpdir: !file path: tmp-unittest logfile: !fd stdout nthreads: !!int 8 EOF -> mbrtowc::euro -> gmtime_r::future -> complex::presence ... => Successfully executed 855 tests

Note: The unit tests are intended to pass on FreeBSD CURRENT and the stable branches. When using FreeBSD 11.1-RELEASE, a small number of unit tests are expected to fail, due to small new features being added. This is harmless.