Friday, 9 July 2010

LAP - Toolchain, Part 2 - All about C

The next bit of software to install is GCC. This is the Gnu Compiler Collection. Essentially it is the software that we are going to use to compile all of the rest of the Linux From Scratch software. At the moment we are using the Compiler that came with Ubuntu.

This file is a biggie - perhaps the biggest we are going to compile. It is going to unpack to over 500Mb. Now this works with a 2Gb machine, but you are going to need to keep the linux memory cache in hand. The memory cache is a facility where data that linux thinks you are going to use often is loaded into RAM. This is fine most of the time and it makes your system run nicely. It is not fine when we are trying to install GCC. Irritatingly it will not automatically dump the cached data to make room for the rapidly expanding GCC folder. So, we need to clear it for it, and we do that as follows:
sync && sudo echo 3 | sudo tee /proc/sys/vm/drop_caches
Keep an eye on the system - you may need to run that more than once. In fact it would probably be a good idea to get the system to repeat this command every so often. There does not appear to be a way to get it to do this by itself, so lets make a script.
cat > ~/repeat.sh << "EOF"
#!/bin/sh
# usage: repeat [x] 
while true ; do $2 ; sleep $1 ; done
EOF
chmod +x ~/repeat.sh
Now we should be able to run:
~/repeat.sh 60 "sync && sudo echo 3 | sudo tee /proc/sys/vm/drop_caches"
To get it to clear the cache every minute. But of course we can't do that because the script we just made shits itself when it gets to the && bit and ignores what comes next. Brilliant. So we have to script the clear cache command AS WELL:
cat > ~/clearc.sh << "EOF"
sync && sudo echo 3 | sudo tee /proc/sys/vm/drop_caches
EOF
chmod +x ~/clearc.sh
We can actually now run:
~/repeat.sh 60 ~/clearc.sh
That should give us as much free memory as possible during the compilation. If you are using a 4Gb machine, this should not worry you at all. On my 2Gb machine, I ended up with a little over 700Mb free after the build had compiled. So, the Ramdisk option is not feasible for a 1Gb machine. We unpack it in the same way as before:
tar -jxvf $LFS/sources/gcc-4.4.3.tar.bz2
cd gcc-4.4.3
There are two other bits of software that we need to unpack at the same time. These are GMP and MPFR, both of which relate to some sort of complicated mathematical function. When we are building this stage of the Toolchain, we can just uncompress them into the GCC folder, and then rename them. The compilation of GCC will then pick them up.
tar -jxf $LFS/sources/mpfr-2.4.2.tar.bz2
mv -v mpfr-2.4.2 mpfr
tar -jxf $LFS/sources/gmp-5.0.0.tar.bz2
mv -v gmp-5.0.0 gmp
Again, GCC uses a separate build directory, so we need to create it. Note that as we are currently in the GCC directory, we need to insert a '../' into the command, unlike the same command for binutils.
mkdir -v ../gcc-build
cd ../gcc-build
Now to configure the package:
../gcc-4.4.3/configure --target=$LFS_TGT --prefix=/tools --disable-nls --disable-shared --disable-multilib --disable-decimal-float --disable-threads --disable-libmudflap --disable-libssp --disable-libgomp --enable-languages=c
The first three options we have seen before. The [disable-shared] option is described by the LFS as:
“This switch forces GCC to link its internal libraries statically. We do this to avoid possible issues with the host system.”
I have no idea what that means. The [disable-multilib] command is actually described as harmless. The [--disable-decimal-float --disable-threads --disable-libmudflap --disable-libssp --disable-libgomp] are not necessary at this stage because we are only going to use this version of the GCC program to compile Glibc and then we will make another one. Lastly we only need to compile in the 'C' language now, so the last option chooses that for us. Again, in a staggering turn of events I had no problems running the script.
make $CORES_TO_USE
This will take a while – perhaps four times as long as binutils.
make install
According to the book, because we disabled the shared thingummy, something didn't get made that should have been made. As a result, and to get the Glibc software to work, we need to run this absolute HORROR of a command. I understand it up to the '-'.
ln -vs libgcc.a `$LFS_TGT-gcc -print-libgcc-file-name | sed 's/libgcc/&_eh/'`
The output of the command is:
`/media/lfs/tools/bin/../lib/gcc/i686-lfs-linux-gnu/4.4.3/libgcc_eh.a' -> `libgcc.a'
This seems to suggest that there is a link so that anything looking for the file libgcc.a file gets the libgcc_eh.a file instead. Fair enough, but how the fuck we get here from the command with its 'sed's and '&'s I have no earthly idea. Magic, I suppose. Now we need to delete these directories again:
cd ..
rm -rvf gcc-4.4.3 gcc-build
Now the next bit is a bit tricky. It looks like we are going to install the linux kernel, because we decompress the kernel package. But at the last minute we do something small and basic instead. Which is a puzzle. The puzzle is not solved by the books explanation:
“The Linux kernel needs to expose an Application Programming Interface (API) for the system's C library (Glibc in LFS) to use. This is done by way of sanitizing various C header files that are shipped in the Linux kernel source tarball.”
Holy fuck. I have sanitized my header before, but usually with some sort of medicated shampoo. I have no fucking clue what this is all about. Lets just get this over and done with as quickly as possible.
tar -jxvf $LFS/sources/linux-2.6.32.8.tar.bz2
cd linux-2.6.32.8
make mrproper
'Make Mr Proper do what?', I wonder casually.
make headers_check
This runs some sort of test. When I ran it, it complained about scsi with this error:
userspace cannot call function or variable defined in the kernel
I am not overly concerned about this, because I don't have any scsi disks. The next command installs these headers we have been hearing about to the 'dest' directory.
make INSTALL_HDR_PATH=dest headers_install
From there we copy them to the Toolchain manually. We cannot install them to the Toolchain, because apparently they would wipe it out.
cp -rv dest/include/* /tools/include
We should delete the unpacked files now, because while we will need to use them again to actually build the kernel, a) that won't be for ages, and b) they are fucking huge.
cd ..
rm -rvf linux-2.6.32.8
The next one is a biggie. It is Glibc. This package includes programs and libraries for running 'C' compiled programs. So GCC lets you compile programs in the 'C' language, and Glibc lets you actually run them.
tar -jxvf $LFS/sources/glibc-2.11.1.tar.bz2
mkdir -v glibc-build
cd glibc-build
Now we have a tricky bit here. We need to tell Glibc to compile for our i686 architecture. It is a bit huffy about this apparently, and we need to tell it to compile for i486. We could edit lots of text files to change this setting, but to make it easy on ourselves the following command does it automatically:
case `uname -m` in  i?86) echo "CFLAGS += -march=i486 -mtune=native" > configparms ;;esac
That all makes sense to someone, somewhere, whose day mostly consists of trying to get to the buckles at the back of their nice new jacket.
../glibc-2.11.1/configure --prefix=/tools --host=$LFS_TGT --build=$(../glibc-2.11.1/scripts/config.guess) --disable-profile --enable-add-ons --enable-kernel=2.6.18 --with-headers=/tools/include libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes
Riiiiiiiight. Lets roll up our sleeves shall we. First option, fine. This time we have host and not target = $LFS_TGT. Fair enough. The [--build=] nonsense is apparently to ensure that the software uses the GCC compiler that we just installed in /tools. [disable-profile] disables profiles which we do not need unless, according to the book, we do need, in which case we should not disable it. Brilliant. That's clear then. [enable-add-ons] tells it to use NTPL as its threading library. I am not clear on what NTPL is, or what a threading library is, and I am still a bit confused about the profiles one, so we'll skip over that. [enable-kernel=2.6.18] is more straightforwards. We are using a kernel with a version later than that, and presumably there was a significant kernel change around version 2.6.18 so we are just telling Glibc that we are up to date. [with-headers=/tools/include] refers to the headers that we installed from the kernel package and points in their direction. [libc_cv_forced_unwind=yes] and [libc_cv_c_cleanup=yes] stop it running tests that we know will fail at this stage. Clear? Good.
make $CORES_TO_USE
make install
Lets clean up.
cd ..
rm -rvf glibc-build glibc-2.11.1

We now have the first part of our Toolchain completed – the basic utils, the compiler and the libraries needed to run C programs. Good stuff. What next?

No comments:

Post a Comment