Compiling LevelDB as LLVM binary on Linux

Some time ago I wrote a guide on how to compile and install LevelDB on Linux.

Recently I’m desperately trying to get into LLVM and a tutorial series on how to use LLVM with C/C++ is coming shortly.

As I’m using LevelDB in many of my projects I’d like a way of generating a LLVM IR (intermediate representation) of the LevelDB C++ source – I could link a LLVM program to the native binary, but in order to profit from LLVMs features I suppose using IRs for as many dependencies as possible is the way to go.

Generally there are two ways to go:

  1. Use the g++ LLVM backend
  2. Use clang++

I usually tend to use clang++ for LLVM tasks because even with colorgcc and some recent improvements in gcc error message generation I prefer the clang++ error messages, even if I have way more experience with gcc error messages. Additionally the g++ with LLVM backend does seem to have some bugs, including interpreting -emit-llvm as -e -m -i …, plus recent distribution versions don’t work too well with the LLVM gold plugin and it has proved difficult to tell GCC reliably that it shall use llvm-ld as linker.

Edit: It seems like llvm-gcc is deprecated since LLVM 3.0

Once you have the g++ commands to create a library or program, it’s pretty easy to convert the Makefile to clang++, if you are satisfied with just listing all clang++/LLVM invocations in the all make target.

Here is the llvm.mk file for LevelDB for Linux with Snappy (compile using  make -f llvm.mk):

all:
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/builder.cc -o db/builder.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/c.cc -o db/c.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/dbformat.cc -o db/dbformat.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/db_impl.cc -o db/db_impl.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/db_iter.cc -o db/db_iter.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/filename.cc -o db/filename.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/log_reader.cc -o db/log_reader.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/log_writer.cc -o db/log_writer.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/memtable.cc -o db/memtable.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/repair.cc -o db/repair.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/table_cache.cc -o db/table_cache.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/version_edit.cc -o db/version_edit.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/version_set.cc -o db/version_set.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c db/write_batch.cc -o db/write_batch.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/block_builder.cc -o table/block_builder.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/block.cc -o table/block.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/filter_block.cc -o table/filter_block.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/format.cc -o table/format.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/iterator.cc -o table/iterator.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/merger.cc -o table/merger.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/table_builder.cc -o table/table_builder.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/table.cc -o table/table.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c table/two_level_iterator.cc -o table/two_level_iterator.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/arena.cc -o util/arena.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/bloom.cc -o util/bloom.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/cache.cc -o util/cache.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/coding.cc -o util/coding.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/comparator.cc -o util/comparator.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/crc32c.cc -o util/crc32c.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/env.cc -o util/env.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/env_posix.cc -o util/env_posix.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/filter_policy.cc -o util/filter_policy.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/hash.cc -o util/hash.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/histogram.cc -o util/histogram.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/logging.cc -o util/logging.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/options.cc -o util/options.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c util/status.cc -o util/status.bc
    clang++ -emit-llvm -I. -I./include -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -DNDEBUG -c port/port_posix.cc -o port/port_posix.bc
    llvm-link -o libleveldb.bc db/builder.bc db/c.bc db/dbformat.bc db/db_impl.bc db/db_iter.bc db/filename.bc db/log_reader.bc db/log_writer.bc db/memtable.bc db/repair.bc db/table_cache.bc db/version_edit.bc db/version_set.bc db/write_batch.bc table/block_builder.bc table/block.bc table/filter_block.bc table/format.bc table/iterator.bc table/merger.bc table/table_builder.bc table/table.bc table/two_level_iterator.bc util/arena.bc util/bloom.bc util/cache.bc util/coding.bc util/comparator.bc util/crc32c.bc util/env.bc util/env_posix.bc util/filter_policy.bc util/hash.bc util/histogram.bc util/logging.bc util/options.bc util/status.bc port/port_posix.bc

Note the invocation of llvm-link in order to merge the IR files (.bc extension). llvm-ld is a linker that links executables with libraries whereas llvm-link merges IR files – they are not the same.

The result is libleveldb.bc, a 576 kiB IR file, compared to the 688 kiB libleveldb.a (git revision 514c943), Feb 6 2013). libleveldb.so.1.9 however is only 392 kiB large.