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:
real 51m6.494s
user 160m47.027s
sys 8m49.429s
Dynamic libraries, ninja, split dwarf, x86 backend only:
real 26m19.360s
user 86m11.477s
sys 3m14.478s
Results: incremental build. touch lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp.
Static libraries, non-ninja, all backends:
real 2m17.709s
user 6m8.648s
sys 0m28.594s
Dynamic libraries, ninja, split dwarf, x86 backend only:
real 0m3.245s
user 0m6.104s
sys 0m0.802s
make install times
make:
real 2m6.353s
user 0m7.827s
sys 0m15.316s
ninja:
real 0m2.138s
user 0m0.420s
sys 0m0.831s
The time for rerunning a sharedlib-config ‘ninja install’ is even faster!
Results: time for gdb, b main, run, quit
Static libraries:
real 0m45.904s
user 0m32.376s
sys 0m1.787s
Dynamic libraries, with split dwarf:
real 0m44.440s
user 0m37.096s
sys 0m1.067s
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:
real 0m10.268s
user 0m3.623s
sys 0m0.429s
A 4x reduction, which is quite nice!
Like this:
Like Loading...