| Building older versions of GCC compatible with Linux Kernel 2.4 |
| =============================================================== |
| |
| |
| This document explains how to build an older supported version of the GCC |
| compiler from a distribution which only offers incompatible recent versions. |
| |
| |
| Context |
| ======= |
| |
| When Linux 2.4.0 was released in early 2001, GCC 2.95.2 was mainstream and |
| GCC 2.91.66 was still widely used. The GCC development model was evolving |
| and still confused. Since then, GCC has evolved a lot and stabilized. New |
| versions are regularly released, and some old features from the early code |
| get deprecated then removed. |
| |
| The kernel heavily relies on GCC's capabilities and behaviour. Some of the |
| code in Linux looks strange but is in fact intended to workaround early GCC |
| bugs. For these reasons, almost every new major GCC release breaks the kernel |
| build process. GCC 3.4 was a real pain to introduce as it required a lot of |
| rewriting in sensible areas, and GCC 4 required a lot of work, though this |
| work was less complicated thanks to the cleanup efforts invested in GCC 3.4. |
| |
| Starting with GCC 4.2, the output code randomly fails depending on section |
| ordering, which itself depends on the declaration order of functions, module |
| parameters and many other things. The nasty part is that the code builds but |
| randomly fails at runtime, so it is almost impossible to fix it and ensure |
| that everything works, especially in the drivers area where most of the |
| problems lie. |
| |
| As of 2008, GCC 4.3.2 is advertised as the current release and 4.2 the previous |
| release. Most distributions have been shipping with 4.2 and 4.3 for some time, |
| so building Linux 2.4 on a recent distribution has become a real problem for |
| users who still have to support kernel 2.4 on servers, firewalls or any other |
| system. |
| |
| |
| Solution : the two-minutes process |
| ================================== |
| |
| If it is not possible to adapt the kernel to GCC, let's adapt GCC to the |
| kernel. We're lucky, building GCC to build just a kernel is not hard and |
| is rather fast. I call that a two-minutes process because building an |
| older GCC takes about 1 minute, and the kernel with that GCC also takes |
| one minute. |
| |
| First, you have to select which version of GCC you want to build your kernel |
| with. Here are some comments on possible versions : |
| |
| - 2.95.3 : very well tested for the kernel, builds kernels very fast, |
| requires a lot of patches and is rather hard to build.. |
| |
| - 3.0 : very buggy, avoid it. |
| |
| - 3.1 & 3.2 : apparently less buggy but rarely used so bugs might have |
| remained unnoticed. |
| |
| - 3.3 : used and tested for a long time. A bit slow but easy to build. |
| |
| - 3.4 : was recently introduced, received less testing, though seems |
| OK. Builds kernels faster than 3.3, and is easy to build too. |
| |
| - 4.0 & 4.1 : received little testing, particularly slow but may produce |
| smaller kernels when compiled with -Os. |
| |
| Always take the last maintenance version of a compiler (eg: 3.4.6 for 3.4). |
| |
| For best reliability and less hassle, I tend to recommend GCC 3.3.6. For |
| improved build times (about 30% lower) and improved kernel performance, I'd |
| recommend 3.4.6. It tends to produce more efficient code on i386, but has |
| had a long history of causing annoyances with inline declarations. It seems |
| OK though, and I build all my kernels with it. We'll assume 3.4 is used for |
| the rest of this document, though what is described will work with 3.3 to |
| 4.1 unless stated otherwise. |
| |
| |
| Instructions |
| ============ |
| |
| 1) Download gcc sources from the nearest mirror |
| ----------------------------------------------- |
| |
| Find a mirror address here : [ http://gcc.gnu.org/mirrors.html ] or download |
| from this directory : |
| |
| ftp://ftp.gnu.org/pub/gnu/gcc/gcc-3.4.6/ |
| |
| Get gcc-core-3.4.6.tar.bz2. It only contains the C compiler, which is what you |
| want. |
| |
| 2) Prepare your build environment |
| --------------------------------- |
| |
| Create a temporary directory where you'll extract the sources. Don't build on |
| NFS, it may be slow. Use /tmp if you want. You'll need about 150 MB of free |
| space. You'll have to extract the sources in that new directory, and create a |
| temporary build directory aside it : |
| |
| $ mkdir /tmp/gcc-build |
| $ cd /tmp/gcc-build |
| $ tar jxf /tmp/gcc-core-3.4.6.tar.bz2 |
| $ mkdir build |
| |
| 3) Configure gcc |
| ---------------- |
| |
| You don't want your new gcc to conflict with the one already in place. I |
| recommend simply prefixing it with "kernel-", and not installing it in |
| /usr/bin, but rather /opt/kgcc/bin or anywhere else (/usr/local/bin will be |
| used by default). I recommend choosing a place you already have in your PATH |
| (such as the default /usr/local/bin), so that you don't have to pass the full |
| path to the binary when building. |
| |
| $ cd /tmp/gcc-build/build |
| $ ../gcc-3.4.6/configure --disable-locale --disable-shared --disable-nls \ |
| --enable-languages=c \ |
| --prefix=/opt/kgcc --program-prefix=kernel- |
| |
| If you're using GCC 3.3, you may see strange messages indicating that some |
| programs were not found (eg: kernel-objdump). Simply ignore them. |
| |
| Note that you can set a lot of options, even use it as a cross-compiler. While |
| very frequent, such a build will not be covered by this document. |
| |
| 4) Build GCC |
| ------------ |
| |
| Both GCC 3.3 and 3.4 support parallel building, which reduces build time on SMP |
| systems : |
| |
| $ make -j 4 |
| |
| If the build fails here because of some options you added above, you'll have to |
| remove the build dir and recreate it. |
| |
| 5) Install your new GCC |
| ----------------------- |
| |
| The binaries may be a bit big, but you can strip them. Both GCC 3.3 and 3.4 |
| support a trick on the command line during the installation process, which |
| consists in passing the "-s" flag to "install" : |
| |
| $ sudo make install INSTALL_PROGRAM='${INSTALL} -s' |
| |
| It will be installed under the directory referred to by the "prefix" option |
| above, or /usr/local/bin if none was specified : |
| |
| $ ls -l /opt/kgcc/bin/kernel-gcc |
| -rwxr-xr-x 3 root root 73124 Sep 6 22:45 /opt/kgcc/bin/kernel-gcc |
| |
| $ /opt/kgcc/bin/kernel-gcc -v |
| Reading specs from /tmp/gcc-3.4.6-build/tmp-inst/opt/kgcc/bin/... |
| Configured with: ../gcc-3.4.6/configure --disable-shared --disable-... |
| Thread model: posix |
| gcc version 3.4.6 |
| |
| 6) Using your new compiler |
| -------------------------- |
| |
| The compiler just has to be passed to "make" via the "CC" variable for all |
| commands : |
| |
| $ make CC=/opt/kgcc/bin/kernel-gcc -j 4 dep bzImage modules |
| $ sudo make CC=/opt/kgcc/bin/kernel-gcc modules_install install |
| |
| or more simply, when you have it in your path : |
| |
| $ make CC=kernel-gcc -j 4 dep bzImage modules |
| $ sudo make CC=kernel-gcc -j 4 modules_install install |
| |
| Note: make modules_install needs a 2.4-compatible depmod. If your distro is |
| 2.6-based and says it does not find depmod or depmod.old, it means that |
| either modutils or module-init-tools have not been correctly installed. |
| You can still force the path to depmod by passing it in the DEPMOD |
| variable during make modules_install if you know where to find a good |
| one. |
| |
| |
| 7) I want to use a really old compiler, but compiling it breaks! |
| ----------------------------------------------------------------- |
| |
| Tackle the problem in stages. Compile 3.x.y as above. Then use that to |
| compile 2.95.x (CC=/opt/kgcc/bin/kernel-gcc ./configure ...), install, |
| use 2.95.x to compile the next compiler in the chain, continue as |
| far as you'd like. |
| |
| Conclusion |
| ========== |
| |
| Building an older GCC on to build an older kernel on a newer machine is not |
| really hard. It becomes harder when you have to cross-build (eg: you're |
| building on a 64-bit machine for a 32-bit one). But for this, I would recommend |
| that you check the excellent "crosstool" utility from Dan Kegel. It supports a |
| wide variety of compilers, contains a lot of fixes and will do all the hard |
| patching and configuration work for any combination you want or need. |
| |
| |
| Suggestions and comments |
| ======================== |
| |
| If you find mistakes or want to send comments about this document, please mail |
| me at <w@1wt.eu>. |
| |