Testing Programs‎ > ‎

Producing LLVM Binaries

There are two ways to produce LLVM bitcode binaries in Cloud9:
  1. Place the code under $CLOUD9_ROOT/src/testing_targets, and integrate it into Cloud9's gyp-based LLVM build system.
  2. Create the binary from an external in situ code base, and use the program's unaltered build system. 
The first method is suitable for relatively small-sized programs, micro benchmarks, test cases, or already gyp-ified projects, while the latter works best for large projects that are hard to convert to gyp.

First Method: Gyp-based LLVM Binaries

Building the LLVM Binaries

All Cloud9 built-in testing targets reside under $CLOUD9_ROOT/src/testing_targets. We will call that $TARGETS_ROOT. The gclient sync command automatically generates Makefiles for them. However, if new targets are added, the build files need to be regenerated:
$ $TARGETS_ROOT/build/gyp_testing_targets

The targets are build all at once by running:
$ $TARGETS_ROOT/build/make_all

NOTE: OpenType Sanitizer, part of the bundled testing targets, requires the libfreetype6-dev package to build properly.

Adding new LLVM Testing Targets

Cloud9's LLVM build system is based on the gyp build files generator system, similar in goals with CMake or SCons. Documenting the gyp syntax is beyond our scope, so please consult the tool's own documentation.

To add your code to the LLVM build system, you need to:
  1. Write a gyp file describing the build operations (see examples here and here).
  2. Add your gyp targets as dependencies to the build/all_llvm.gyp file.
Do not forget to regenerate the project files and rebuild. You should find your LLVM binary in the out/Default directory (relative to the testing_targets directory).

Second Method: In Situ LLVM Binaries

Cloud9 makes it easy to build LLVM binaries for external programs. Assuming that the program is compiled using the standard ./configure && make procedure, one generates LLVM binaries as follows:
  1. In a shell session, prepare the environment for LLVM compilation by executing
    $ source $TARGETS_ROOT/build/prepare_build_env.sh
    NOTE: At this point, this session will generate LLVM bitcode and it is not suitable for standard x86 compilation.
  2. Execute the standard compilation steps for the target program:
    $ ./configure ...
    $ make
For each final executable binary, this procedure generates both a native x86 form program, as well as an LLVM bitcode version program.bc. The .bc file is used by Cloud9 for testing.

Advanced LLVM Building

Cloud9 uses a set of proxy scripts that play the role of the building tools (gcc, g++, ar, ranlib, nm). When run, these scripts invoke in turn the corresponding actual tools, based on a set of rules. By default, the tools invoked are configured to produce LLVM binaries.

In some cases, you may need to change the behavior of the proxy scripts. Cloud9 offers 3 possible configurations, which are set through the LLVM_BUILD_MODE environment variable:
  1. llvm - produce LLVM bitcode using Clang (default)
  2. clang - produce x86 binaries using Clang
  3. gcc - produce x86 binaries using GNU's GCC
For instance, if we need to run the ./configure part of the building process using GCC, so the configuration would detect GCC specific features, we execute:
$ source $TARGETS_ROOT/build/prepare_build_env.sh
$ export LLVM_BUILD_MODE="gcc"
$ ./configure
$ export LLVM_BUILD_MODE="llvm"
$ make

Note that the ./configure script picks up the proxy scripts as the building tools. This means that we don't have to change anything in the generated configuration, since the same tools are used for the building process, except that they would behave differently depending on the value of LLVM_BUILD_MODE.

Compiling C++ Programs

Clang's libcxx is part of the Cloud9 LLVM testing targets, and thus it is build automatically. To build C++ programs, you need to either:
  • List build/libcxx.gyp:libcxx as a dependency in your gyp file, if you use the gyp-based method, or
  • Compile your program with the -nostdinc++ flag, add libcxx/include to the include path, and link out/Default/obj.target/build/libcxx.a in your final executable.