03 Sep 2015, 11:26

Using PGP on DragonFly

Pretty Good Privacy (PGP) is used to sign or verify files or emails. For DragonFly there exist three different ports that implement PGP functionality:

  • security/pgp
  • security/netpgp
  • security/gnupg

Only the latter really worked for me. For instance, my public key created with pgp could not be imported on another system, which I assume was using GnuPGP. So I stick with security/gnupg and describe below how to use it to create a key and how to sign and verify binary data.

Creating a key

gpg --gen-key

Then follow the instructions. To show the fingerprint of your key, use:

gpg --fingerprint youremailaddress

Exporting your public

gpg --export --armor youremailaddress > mykey.asc

You can then send mykey.asc to someone or put it on your homepage for others to download.

Signing a binary file

To generate a detached signature for snapshot.tar.gz:

gpg --armor --detach-sign snapshot.tar.gz

This will create snapshot.tar.gz.asc.

Verify a signed file

To verify the signature from the last step use:

gpg --verify snapshot.tar.gz.asc snapshot.tar.gz

If successful, this should show something similar to:

gpg: Good signature from "Michael ...."

15 Jun 2015, 21:40

Testing ports with poudriere

To build or test ports on DragonFly or FreeBSD, a fantastic tool named poudriere exists. It provides a clean environment for reproducibly building packages.

Installation is as easy as pkg ins poudriere. Then edit /usr/local/etc/poudriere.conf. In my case I only had to change the DPORTS_URL setting to a local git repository for the ports tree (for example point it to /git/DPorts.git). This is because I want to add or test new ports. If you only want to build existing ports, point it towards a mirror of our ports tree.

Next, we check out the ports. This is done via

# poudriere ports -c

Then, we build a jail named myjail with a specified DragonFly version. I will use the master branch. Inside this jail we will later on build the ports.

# poudriere jail -c -j myjail -v master

This takes a while as it has to do a full buildworld. Now we can start to build a port. Let’s say we want to test the lang/ruby22 port:

# poudriere testport -j myjail -o lang/ruby22

That’s all. For more complex tasks, please consult it’s man page poudriere(8).

29 Jul 2014, 11:27

Rust ported to DragonFly BSD

During the last week I spent numerous hours on porting my favorite programming language Rust to operate on my favorite operating system DragonFly. While my first attempt months earlier failed, this time I was successful! In the following article I go through all the problems I had to deal with and how you can build Rust for DragonFly yourself. This might also be of interest to people who want to port Rust to further platforms like NetBSD or OpenBSD.

You find the scripts needed to compile Rust on DragonFly here and my DragonFly branch of Rust here (hopefully to be merged soon).

You can download the binary distribution of the Rust compiler including the Cargo package manager here (size: 93 MB, checksum). The script to bootstrap Cargo can be found here.

Quick overview

In short what needs to be done to port Rust to a new platform is the following:

  1. Extend the rustc compiler to generate code for the platform you are porting to.

  2. As rustc depends on LLVM this might require some patching here too, to be able to generate code for the target operating system (in my case segmented stacks were unsupported for DragonFly).

  3. As Rust (still) requires segmented stacks there needs to be support for it in some way in the operating system. All Rust and LLVM need is a thread local field where they can store the size of the stack.

  4. The Rust libraries (e.g. liballoc, liblibc, libstd, libnative) need to be ported. This basically involves adding some #[cfg(target_os = "dragonfly")] somewhere, but also some system structures need to be adapted.

Once this is done we are ready to cross-compile Rust to DragonFly.

Cross compiling

After trying to cross-compile Rust by specifying --target x86_64-pc-dragonfly-elf to Rust’s own configure script and spending numerous hours just to note that the build fails, I gave up on this idea. Instead I took a different approach as shown below. Note that this all requires my dragonfly branch of rust. All stages depend sequentially on another. Below we are using the scripts from my rust-cross-dragonfly project.

Stage1 (Linux, DragonFly)

  • On Linux: Compile a modified rustc on Linux that supports DragonFly as target (rustc natively is able to generate code for different targets!).

  • On DragonFly: At the same time we can build the C libraries Rust depends on.

Use scripts stage1-linux.sh and stage1-dragonfly.sh respectively.

Actually I tried to cross-compile everything on Linux, but I failed for LLVM. So I decided to build everything that involved compiling C or C++ on the target (DragonFly) itself.

Stage2 (Linux)

We have to copy the outcome of stage1-dragonfly (which is stage1-dragonfly.tgz) to the Linux box and extract it to create stage1-dragonfly/. This includes the C libraries required for Rust as well as some system libraries.

Stage2 (sh stage2-linux.sh) cross-compiles all of Rust’s libraries (e.g. libstd, libsyntax, librustc) and generates the object file for the rustc binary (driver.o). I don’t generate the executable here itself, which I could, but when I did, static initializations were omitted and the generated rustc was unable to find statically registered command line options of LLVM. I spent hours to figure this out. The solution was to just generate the object file for rustc and together with the Rust libraries pass it on to Stage3, which links the rustc binary on DragonFly.

Copy the outcome of Stage2 (stage2-linux.tgz) back to the DragonFly system.

Stage3 (DragonFly)

Finally back again on DragonFly. Extract stage2-linux.tgz to become stage2-linux. In this stage we will construct a working rustc binary (the Rust compiler) and test to compile a simple Hello World application hw.rs natively on DragonFly.

All you have to do is to execute sh stage3-dragonfly.sh.

Stage4 (DragonFly)

Stage4 is the last stage and it builds my dragonfly branch with the compiler from Stage3. It uses Rust’s own build infrastructure to do so and not my “hacked” build infrastructure.

All you have to do is to execute sh stage4-dragonfly.sh and wait. It does not automatically install Rust for you, so you have to gmake install inside directory stage4-dragonfly/rust yourself (needing admin privileges).

Problems faced

  • LLVM does not support segmented stacks on DragonFly. So I had to patch LLVM and will submit the patch upstream soon.

  • The LLVM patch implies having a special field in the thread control block to record the stack size. Thanks to Matthew Dillon I was “allowed” to use a yet unused field for it and the patch got accepted.

  • Rust fails with a memory corruption when jemalloc is not used, see my bug report #16071. I noticed that earlier on Linux but ignored it. Later when I had a rustc compiler working on DragonFly I got hit by this again as I built it without jemalloc. It cost me a whole night ktracing it and several reboots. The solution was to compile with jemalloc.

  • Intially the port of libstd and liblibc were basically copies of the related FreeBSD code. Several times I got hit by differences in system structures and return codes. The right solution would be to generate code like this in an automated fashion.

  • Cross-linking, that is linking an executable targeted for DragonFly on Linux, has some limitations, or more probable is that I did something wrong. Static initializations are handled incorrectly (they are not executed). It took me a while to figure this out after searching through the LLVM code.

  • Last but not least, compiling Rust takes an enormous amount of time. That is, the turn-around times are quite high. Compiling, fixing an error, compiling again. And so on and on.


Rust works on DragonFly, yippey! I work on uploading a snapshot and maybe setting up a regular build and add it to dports. Hopefully this document also helps others in porting Rust to further platforms, mainly OpenBSD and NetBSD.

23 Feb 2014, 19:03

Cross-compiling for DragonFly BSD

In this short article I want to show the basics of how to generate an executable for the DragonFly BSD operating system from a Linux system. This process is called cross compiling. The reason why I investigated into this topic was that I wanted to cross-compile the Rust compiler.

All you need is clang installed and a DragonFly BSD installer ISO image which you can obtain from it’s homepage. The application we want to cross-compile is the one listed below:

#include <stdio.h>

int main(int argc, char **argv) {
  printf("Hello World\n");
  return 0;

The first step is to mount the ISO image into the local directory ./iso because we need the header files for compilation as well as the files crt{1,i,begin}.o and libgcc.a for linking.

mkdir iso
sudo mount -o loop,ro DragonFly-x86_64-LATEST-ISO.iso ./iso

After that, we are ready to compile our simple Hello World example application. To compile we need to specify the corresponding include and link paths and tell the compiler the target we want to create code for, in our case this is x86_64-pc-dragonfly-elf.

clang -I./iso/usr/include \
      -L./iso/usr/lib -L./iso/usr/lib/gcc47 \
      -B./iso/usr/lib -B./iso/usr/lib/gcc47 \
      -target x86_64-pc-dragonfly-elf \
      -o hw hw.c 

Running file hw should now display something like this:

hw: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked
    (uses shared libs), for DragonFly 3.0.702, not stripped

VoilĂ , there it is, our binary for DragonFly BSD.

14 Jan 2010, 00:00

HAMMER File System

This is a presentation I gave in January 2010 at the Audimax lecture hall of KIT in Karlsruhe. I talked about the HAMMER filesystem of DragonFlyBSD.