Showing posts with label GCC. Show all posts
Showing posts with label GCC. Show all posts

Kernel compile notes

NOTE: The upstream (git) kernel *sometimes* does not compile with gcc-4.x. Install gcc-3.4 and change /usr/bin/gcc (which links to gcc-4.x) to point to gcc-3.4 instead.

Compile using make-kpkg on Debian. Kernel compiles as a .deb (initrd image + modules) and can be directly installed using dpkg -i. (Steps, UbuntuWiki). The problem with make-kpkg is that every time you make a change to the kernel code it recompiles everything from scratch, which is a pain in the neck! To avoid that, it is better to compile the kernel from scratch and not use jazzy distro scripts


The old fashioned way

1. Go to the kernel directory (say, kernel_dir) and edit the Makefile to specify the EXTRAVERSION. (This is what --append-to-version does in make-kpkg). It is good to do this as it helps to identify your kernel from the rest.

2. Configure the kernel
make menuconfig

If you do not know where to start for, use
make defconfig

This creates a default configuration for i386. You can then confirm the configuration with
make menuconfig

[OLD]It might be useful to run (not required)
make oldconfig

3. Compile the kernel and modules
make bzImage
make modules


In the 2.6+ kernel, you can just do the following instead

make -j N, where N is the number of parallel compilation tasks you want to kick in for a faster compile. (N = 2,4,...)

TIP: If you have already compiled and installed the kernel once and later made changes ONLY to the kernel, doing a make would build the modules too. To avoid that do

make bzImage

TIP: To reduce the compilation noise you can forward the output of make to /dev/null.

4. Install the modules in /lib/modules

sudo make modules_install

Confirm that /lib/modules/ has the modules corresponding to your kernel version.

5. Copy the kernel image binaries to /boot

Lets say that the kernel version (along with the EXTRAVERSION) is 2.6.24-custom.010209

cd kernel_dir
sudo mv arch/i386/boot/bzImage /boot/vmlinuz-2.6.24-custom.010209
sudo mv .config /boot/config-2.6.24-custom.010209
sudo mv System.map /boot/System.map-2.6.24-custom.010209


6. Create the RAM Disk image (initrd).

In Ubuntu the mkinitrd is no longer supported. Instead mkinitramfs is used.

update-initramfs -c -k 2.6.24-custom.010209 # your kernel version

Note that update-initramfs looks at /lib/module for the kernel version. Make sure that you have installed the modules in step 4.

The initrd file initrd-2.6.24-custom.010209 would be created in /boot

NOTE: Usually the following are selected by default at the time of kernel configuration. If these are not set, you might get a kernel panic while booting.
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CRAMFS=y


7. Last step is to update grub

sudo update-grub

Check in /boot/grub/menu.lst and confirm.

8. Reboot, and select your kernel

Packing structures \ enums

There are various ways in which this can be done.

1. using #pragma pack()
#pragma pack(2)
typedef struct
{
char c;
int i;
} DataType;
#pragma pack()

This would pack the structure on a 2 byte boundary. If a tight packing is required use #pragma pack(1) instead. Compile it normally using gcc.

2. Using -fpack-struct
Instead of using the #pragma, we can directly use the compiler flags instead.
$gcc -Wall -fpack-struct -fshort-enums test.c -o test
This would pack all the structs to the 1 byte boundary and consider shorts for enums instead of integers

2. Using __attribute__ ((__packed__))

typedef struct
{
char c;
int i;
} __attribute__ ((__packed__))DataType;
.
Compile the code normally.

We can also do it this way

typedef struct
{
char c __attribute__ ((__packed__));
int i1 __attribute__ ((__packed__));
int i2;
} DataType;