Building FreeBSD with clang/llvm
FreeBSD world and kernel can be built with clang/llvm. Clang is a compiler built on the Low Level Virtual Machine compiler infrastructure. Both clang and llvm are released under a BSD like license.
Contents
Status
Clang has been imported into head and stable/9, and is built by default, so there is no need to install the port anymore, unless you want to play with the other tools that llvm provides. An unmodified FreeBSD head and stable/9 can completely be built by clang! (Note that you still need to setup /etc/make.conf properly, see below for the details.)
Newer snapshots of clang/llvm are imported regularly into head, and will be merged to stable branches, as appropriate. FreeBSD 9.0 is the first release to contain clang by default.
All of userland (plus clang/llvm itself) and the kernel compiles and runs ok. The amd64, i386 and arm kernels boot multiuser. Arm world needs newer ABI (AAPCS, we currently use ATPCS). PowerPC32 needs patched llvm (not saving FP registers on call func). PowerPC64 has crashing aicasm and the resulting kernel (without ahc that uses aicasm) does not link (relocation truncated to fit: R_PPC64_TOC16_DS against `.toc').
A buildbot that runs on-commit builds and boot tests can be found here.
Build status |
amd64 |
i386 |
arm |
powerpc |
powerpc64 |
mips |
mips64 | |
Hello world |
OK |
OK |
needs newer ABI |
OK |
OK with binutils >= 2.17 |
unknown |
OK |
FreeBSD World |
OK |
OK |
needs newer ABI |
OK, PIC missing |
ls and sh reported to work |
unknown |
unknown |
GENERIC kernel |
OK |
OK |
OK |
OK (with patches) |
unknown |
missing -mno-abicalls |
unknown |
LINT kernel |
OK |
OK |
OK |
unknown |
unknown |
missing -mno-abicalls |
unknown |
Please note that cross compiling is not yet supported by clang.
Quickstart
Checkout head (make sure this is r212979 or later):
# svn co http://svn.freebsd.org/base/head src
Add the following lines to /etc/make.conf:
.if !defined(CC) || ${CC} == "cc"
CC=clang
.endif
.if !defined(CXX) || ${CXX} == "c++"
CXX=clang++
.endif
.if !defined(CPP) || ${CPP} == "cpp"
CPP=clang-cpp
.endif
# Don't die on warnings
NO_WERROR=
WERROR=
# Don't forget this when using Jails!
NO_FSCHG=Verify that "/usr/bin/clang -v" works:
FreeBSD clang version 3.0 (branches/release_30 142614) 20111021 Target: x86_64-unknown-freebsd10.0 Thread model: posix
and produces output similar to the above.
Building/installing world (into a chroot).
# make buildworld # make installworld DESTDIR=/usr/obj/clang # chroot /usr/obj/clang /bin/echo Hello clang world! Hello clang world! # chroot /usr/obj/clang /bin/tcsh
Building/installing kernel.
# make kernel KERNCONF=GENERIC INSTKERNNAME=clang
Boot it.
OK set module_path=/boot/clang OK boot clang
To update the source tree perform the following steps.
# cd src/ # svn up
Using the static analyzer
On the kernel (This requires lots of space in the output directory, 406M when using "scan-build make MODULES_OVERRIDE=").
# cd /sys/{amd64,i386}/conf/
# config GENERIC
# cd ../compile/GENERIC/
# make depend
# scan-build make MODULES_OVERRIDE=
# {firefox,epiphany,konqueror,lynx,less} /tmp/scan-build-YYYY-MM-DD-N/index.htmlOn a userland program.
# cd /usr/src/usr.bin/make/
# make cleandir && make obj && make depend
# scan-build make
# {firefox,epiphany,konqueror,lynx,less} /tmp/scan-build-YYYY-MM-DD-N/index.html
Using the analyzer on vanilla sources
Scanning the FreeBSD sources using the static analyzer requires you to:
# svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
# cd llvm/tools && svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
# cd .. && ./configure --enable-optimized && gmake
# cp -p tools/clang/tools/scan-build/{ccc-analyzer,scan-build,scanview.css,sorttable.js} Release+Asserts/bin
# ln -sf ccc-analyzer Release+Asserts/bin/c++-analyzerNow you have all the necessary tools in llvm/Release+Asserts/bin. They need to be next to each other, as we will be using the full-path to scan-build later and it must find clang-cc, which it searches in it's own directory and $PATH. As $PATH will be cleansed during buildworld, only the first option remains.
Running the analyzer is now as easy as
# cd /usr/src && /path/to/llvm/Release+Asserts/bin/scan-build -k make buildworld
Weekly scans of buildworld and buildkernel can be studied at http://scan.freebsd.your.org/freebsd-head. The high amount of false positives due to missing intra-procedural analysis (IPA) in ccc-analyzer makes them not very useful though. One run usually produces almost 6 GB of HTML output.
Link Time Optimizations
LLVM supports LTO. It can be used for kernel build by these pseudo steps:
0) build gold and libLLVMgold.so (see http://llvm.org/docs/LinkTimeOptimization.html) 1) CFLAGS+=-emit-llvm 2) setenv LD "/tmp/ld-new --plugin /tmp/libLLVMgold.so" 3) setenv CC clang 4) build the kernel
This was tested on i386. The resulting kernel does boot.
Automatic test generation with KLEE
KLEE is a symbolic virtual machine built on top of the LLVM compiler infrastructure. More about KLEE here and paper here.
Building KLEE
# svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm # svn co http://llvm.org/svn/llvm-project/cfe/trunk llvm/tools/clang # svn co http://llvm.org/svn/llvm-project/klee/trunk klee # cd llvm/ # ./configure --prefix=/usr/local --enable-optimized --enable-targets=host-only --enable-bindings=none # gmake # gmake install # cd ../klee/ # ./configure --with-llvm=$PWD/../llvm # gmake LLVMGCC=/usr/local/bin/clang # cp Release+Asserts/bin/* /usr/local/bin/ # cp Release+Asserts/lib/* /usr/local/lib/
Using KLEE
# cd /usr/src/usr.bin/touch/ # clang -c -g -emit-llvm -o touch.bc touch.c # klee touch.bc KLEE: output directory = "klee-out-0" ...
More to come later...
Known issues
- none
Contacts
Resources
For more details on compiling the ports with clang/llvm see: PortsAndClang