I found the default static library configuration of clang slow to rebuild, so I started building it with in shared mode. That loaded pretty slow in gdb, so I went looking for how to enable split dwarf, and found a nice little presentation on how to speed up clang builds.
There’s a followup blog post with some speed up conclusions.
A failure of that blog post is actually listing the cmake commands required to build with all these tricks. Using all these tricks listed there, I’m now trying the following:
mkdir -p ~/freeware cd ~/freeware git clone git://sourceware.org/git/binutils-gdb.git cd binutils-gdb ./configure --prefix=$HOME/local/binutils.gold --enable-gold=default make make install cd .. git clone git://github.com/ninja-build/ninja.git cd ninja ./configure.py --bootstrap mkdir -p ~/local/ninja/bin/ cp ninja ~/local/ninja/bin/
With ninja in my PATH, I can now build clang with:
CC=clang CXX=clang++ \ cmake -G Ninja \ ../llvm \ -DLLVM_USE_SPLIT_DWARF=TRUE \ -DLLVM_ENABLE_ASSERTIONS=TRUE \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_INSTALL_PREFIX=$HOME/clang39.be \ -DCMAKE_SHARED_LINKER_FLAGS="-B$HOME/local/binutils.gold/bin -Wl,--gdb-index' \ -DCMAKE_EXE_LINKER_FLAGS="-B$HOME/local/binutils.gold/bin -Wl,--gdb-index' \ -DBUILD_SHARED_LIBS=true \ -DLLVM_TARGETS_TO_BUILD=X86 \ 2>&1 | tee o ninja ninja install
This does build way faster, both for full builds and incremental builds.
Build tree size
Dynamic libraries: 4.4 Gb. Static libraries: 19.8Gb.
Installed size
Dynamic libraries: 0.7 Gb. Static libraries: 14.7Gb.
Results: full build time.
Static libraries, non-ninja, all backends:
Dynamic libraries, ninja, split dwarf, x86 backend only:
Results: incremental build. touch lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp.
Static libraries, non-ninja, all backends:
Dynamic libraries, ninja, split dwarf, x86 backend only:
make install times
make:
ninja:
The time for rerunning a sharedlib-config ‘ninja install’ is even faster!
Results: time for gdb, b main, run, quit
Static libraries:
Dynamic libraries, with split dwarf:
This one isn’t what I would have expected. The initial gdb load time for the split-dwarf exe is almost instantaneous, however it still takes a long time to break in main and continue to that point. I guess that we are taking the hit for a lot of symbol lookup at that point, so it comes out as a wash.
Thinking about this, I noticed that the clang make system doesn’t seem to add ‘-Wl,-gdb-index’ to the link step along with the addition of -gsplit-dwarf to the compilation command line. I thought that was required to get all the deferred symbol table lookup?
Attempting to do so, I found that the insertion of an alternate linker in my PATH wasn’t enough to get clang to use it. Adding –Wl,–gdb-index into the link flags caused complaints from /usr/bin/ld! The cmake magic required was:
-DCMAKE_SHARED_LINKER_FLAGS="-B$HOME/local/binutils.gold/bin -Wl,--gdb-index' \ -DCMAKE_EXE_LINKER_FLAGS="-B$HOME/local/binutils.gold/bin -Wl,--gdb-index' \
This is in the first cmake invocation flags above, but wasn’t used for my initial 45s gdb+clang time measurements. With –gdb-index, the time for the gdb b-main, run, quit sequence is now reduced to:
A 4x reduction, which is quite nice!