Articles

[GUIDE] The Bleeding Edge

A short guide on compiling source code and making it into a module.
By Nadim Issa

Compiling source code is a task that most of us will run into while using a linux based system. This guide is intended to help those who are not too familiar with this. The source code that I will be using here is for a simple text editor called nano. This can be downloaded from http://ftp.gnu.org/gnu/nano/. The version should make no difference.I would venture a guess that to be on the bleeding edge you need to be running the latest version of all software you use. Sometimes the wait for someone else to build the module (or the package you need to install this software), will leave you on the coagulated side of things.

Usually, the first thing to do after downloading your source is to unpack it:

tar -xvvf nano-2.3.0.tar.gz

Don't laugh at my flags. I use them for every decompress I come across-- gz's,bz2,ect..

Some of you might say "What is all this mess I just unpacked on my computer?" It is the combination of documentation and source code. There are two key documents to us here, most applications I have compiled have these two files: INSTALL and README. These two files usually have all the information and prerequisites for compiling. Now the sweet and simple is we just issue the following commands.

cd nano-2.3.0
./configure
make
make install

This will work fine if you want to install it to your system root. But I wanted to share a couple of pointers and we are also going to make this into a module.

On the first try I will use the following code:

cd nano-2.3.0
./configure --prefix=/mnt/sda6/nano-os CFLAGS="-Os -fPIC -pipe -fomit-frame-pointer"
make -j4
make install

That looks like a lot of gibberish. Well don't worry it is pretty easy to understand.

The second line of that code calls a configuration script, and that configuration script creates the makefiles that the next two commands use to build the executable. By passing the --prefix= code we are changing the root of the install. We are doing this so we can isolate, easily, the executable,libs and documentation, of the application we are building.

After that we have the CFLAGS.  These options are used for telling the compiler how we are going to optimize our code, mess with it. Our first option in the CFLAGS is a -Os (that is a minus capital O not the number 0, followed by an s). This is used for identifing the optimization level. There is also Os, O1, O2, and O3. The Os typically opitimizes for code size, so it tries to produce the smallest executable. The O3 is usually used to optimize for speed of execution. O2 is the default that is used if nothing is specified. Another thing to remember is that just because the code is smaller doesn't mean it will execute faster.

The -fPIC is specific to the x86_64 architecture, and enables "Position Independent Code". This is well beyond the scope of this document. If you want more info on that, this document made a lot of sense to me: http://www.technovelty.org/code/c/amd64-pic.html

The -pipe forces inline instructions to do just that.

The -fomit-frame-pointer will make it very difficult to debug with traditional debuggers. This usually results in faster executing code.

The next line is make -j4.  Make starts the compile process and the -j4 tells the compiler to compile 4 threads simultaniously. This results in faster build times. How do you know how many threads to compile simultaniously? The usual formula is (number of cpu cores) X 2 + 1. For programs this small it doesn't make a difference but for larger projects it can usually result in hours of compile time difference. Occasionally you will run into errors while compiling. You can make it through some of the softer errors by issuing a "make -k -j4", the -k forces it through some errors.

Finally, the make install instruction just places all the compiled executables, library files, and documentation in the specified place.

Now I'll compile with a different set of flags, placing the resulting files in a different directory:

cd nano-2.3.0
./configure --prefix=/mnt/sda6/nano-o3 CFLAGS="-O3 -fPIC -pipe -fomit-frame-pointer"
make -j4
make install

Here are the results of those two compiles:

/mnt/sda6/nano-os/bin/nano 222672 bytes
/mnt/sda6/nano-o3/bin/nano 246974 bytes

Here it is clear that the -Os cflag resulted in a smaller executable.

Now all that is left to do is strip the executable to reduce its size. This step is optional. The first time I ever ran into this, I was compiling a kernel for a "Sun Ultra 80" with the Sparc cpu's.  For some reason the kernel had to be less than 4 mb, to load properly. So for some systems this step is essential. The way this reduces the size of the executable by removing unneeded symbols in the code. You can also do this to shared libs. This can lead to debugging issues.

strip --strip-unneeded /mnt/sda6/nano-os/bin/nano
strip --strip-unneeded /mnt/sda6/nano-o3/bin/nano

resulting sizes:

/mnt/sda6/nano-os/bin/nano 192240 bytes
/mnt/sda6/nano-o3/bin/nano 216784 bytes

I like to use the smaller executables. So I will use the nano-os directory for my module creation. I remove extra stuff that I don't feel is needed to include in my module. I remove the man files, info files, and the locales. Remember to keep what is important to you. Also with this particular package it needs to be installed to /usr/local/ so make sure you create these directories and move the appropriate files in place. So now the /mnt/sda6/nano-os/usr/local/ is where the prefix should have been. Now we build our module using the dir2xzm.

cd /mnt/sda6
dir2xzm nano-os nano-2.3.0.xzm


This is our final module size:

/mnt/sda6/nano-2.3.0.xzm 106496 bytes


At this point share with your friends, upload it to internet, do whatever you wish with it. You can also find more info on CFLAGS at http://en.wikipedia.org/wiki/CFLAGS
This will help keep you at the bleeding edge with software, on porteus.



To view the discussion about this article, or to make a suggestion or ask a question about it, visit this thread on our forum.