Nuxi CloudABI for macOS

In addition to the Free and Open Source (FOSS) operating systems, we also provide support for using CloudABI on some commercial operating systems, such as macOS. This article explains both how software for CloudABI can be developed and how the resulting programs can be executed, all using macOS.

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

A complete toolchain for CloudABI based on LLVM, Clang and LLD can be installed using the Homebrew package manager. The following commands can be used to enable access to the CloudABI tap and install its cloudabi-toolchain formula that builds the latest version of LLVM:

$ brew tap nuxinl/cloudabi ==> Tapping nuxinl/cloudabi Cloning into '/usr/local/Library/Taps/nuxinl/homebrew-cloudabi'... ... Tapped 163 formulae (186 files, 218.2K) $ brew install cloudabi-toolchain ==> Installing cloudabi-toolchain from nuxinl/cloudabi ... ==> make ==> make install 🍺 /usr/local/Cellar/cloudabi-toolchain/3.9.0: 1,767 files, 435.9M, built in 23 minutes 19 seconds

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/armv6-unknown-cloudabi-eabihf-c++ /usr/local/bin/armv6-unknown-cloudabi-eabihf-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

Alternatively, a toolchain based on the latest development version of Clang can be installed by running the following command:

$ brew install --HEAD cloudabi-toolchain

2. Accessing the CloudABI Ports Collection

The toolchain that was installed above 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. The packages that are part of this collection are automatically converted to bottles that are synchronized into the same tap, meaning they can easily be installed using brew install.

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:

$ brew install x86_64-unknown-cloudabi-cxx-runtime ==> Installing x86_64-unknown-cloudabi-cxx-runtime from nuxinl/cloudabi ... ==> Pouring x86_64-unknown-cloudabi-cxx-runtime-1.0.el_capitan.bottle.2.tar.gz 🍺 /usr/local/Cellar/x86_64-unknown-cloudabi-cxx-runtime/1.0: 335B

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

$ brew search nuxinl/cloudabi nuxinl/cloudabi/aarch64-unknown-cloudabi-boost nuxinl/cloudabi/aarch64-unknown-cloudabi-bzip2 nuxinl/cloudabi/aarch64-unknown-cloudabi-c-runtime nuxinl/cloudabi/aarch64-unknown-cloudabi-cairo ...

3. Executing CloudABI applications

The tap also contains a formula that installs the cloudabi-run utility. On macOS, this utility can be used to run CloudABI executables using a very lightweight system call emulation layer. Though this emulation layer does not strictly guarantee any of the safety properties normally provided by in-kernel support, it is sufficient for running CloudABI applications on macOS for development and testing purposes. The cloudabi-run utility can be installed by running the following command:

$ brew install cloudabi-utils ==> Installing cloudabi-utils from nuxinl/cloudabi ... ==> make ==> make install 🍺 /usr/local/Cellar/cloudabi-utils/0.9: 10 files, 3.0M, built in 6 seconds

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

$ cat hello.c #include <argdata.h> #include <program.h> #include <stdio.h> #include <stdlib.h> void program_main(const argdata_t *ad) { int fd = -1; argdata_get_fd(ad, &fd); dprintf(fd, "Hello, world\n"); exit(0); } $ x86_64-unknown-cloudabi-cc -o hello hello.c $ cat hello.yaml %TAG !,2015:cloudabi/ --- !fd stdout $ cloudabi-run -e hello < hello.yaml ... Hello, world