Debugging symbols and compiler optimizations

Most programs and libraries by default are compiled with debugging symbols and optimizing level 2 (gcc options -g and -O2) and are compiled for a specific CPU. On Intel platforms software is compiled for i386 processors by default. If you don't wish to run software on other machines other than your own, you might want to change the default compiler options so that they will be compiled with a higher optimization level, no debugging symbols and generate code for your specific architecture. Let me first explain what debugging symbols are.

A program compiled with debugging symbols means you can run a program or library through a debugger and the debugger's output will be user friendlier. These debugging symbols also enlarge the program or library significantly.

To remove debugging symbols from a binary (must be an a.out or ELF binary) run strip --strip-debug filename You can use wild cards if you need to strip debugging symbols from multiple files (use something like strip --strip-debug $LFS/usr/bin/*). Another, easier, options is just not to compile programs with debugging symbols. Most people will probably never use a debugger on software, so by leaving those symbols out you can save a lot of diskspace.

Before you wonder if these debugging symbols would make a big difference, here are some statistics:

Sizes may vary depending on which compiler was used and which C library version was used to link dynamic programs against, but your results will be similar if you compare programs with and without debugging symbols. After I was done with this chapter and stripped all debugging symbols from all LFS binaries and libraries I regained a little over 102 MB of disk space. Quite the difference.

There are a few ways to change the default compiler options. One way is to edit every Makefile file you can find in a package, look for the CFLAGS and CXXFLAGS variables (a well designed package uses the CFLAGS variable to define gcc compiler options and CXXFLAGS to define g++ compiler options) and change their values. Packages like binutils, gcc, glibc and others have a lot of Makefile files in a lot of subdirectories so this would take a lot of time to do. Instead there's an easier way to do things: create the CFLAGS and CXXFLAGS environment variables. Most configure scripts read the CFLAGS and CXXFLAGS variables and use them in the Makefile files. A few packages don't follow this convention and those package require manual editing.

In the next section we'll create the $LFS/root/.bash_profile that will contain the following optimization:

CFLAGS="-O3 -mcpu=xxx -march=xxx"

This is a minimal set of optimizations that ensures it works on almost all platforms. These two options (mcpu and march) will compile the binaries with specific instructions for that CPU you have specified. This means you can't copy this binary to a lower class CPU and execute it. It will either work very unreliable or not at all (it will give errors like Illegal Instruction, core dumped). You'll have to read the GCC Info page to find more possible optimization flags. In the above environment variable you have to replace xxx and yyy with the appropriate CPU identifiers such as i586, i686, powerpc and others.

Please keep in mind that if you find that a package doesn't compile and gives errors like "segmentation fault, core dumped" it's most likely got to do with these compiler optimizations. Try lowering the optimizing level by changing -O3 to -O2. If that doesn't work try -O or leave it out all together. Also try changing the -mcpu and -march variables. Compilers are very sensitive to certain hardware too. Bad memory can cause compilation problems when a high level of optimization is used, like the -O3 setting. The fact that I don't have any problems compiling everything with -O3 doesn't mean you won't have any problems either. Another problem can be the Binutils version that's installed on your system which often causes compilation problems in Glibc (most noticable in RedHat because RedHat often uses beta software which aren't always very stable. "RedHat likes living on the bleeding edge, but leaves the bleeding up to you" (quoted from somebody on the lfs-discuss mailinglist).