How to Compile Linux Kernel with Something Other Than Gcc

compiling linux kernel with non-gcc

There is ongoing process of committing LLVMLinux patches into vanilla kernel (2013-2014).

The LLVMLinux is project by The Linux Foundation: http://llvm.linuxfoundation.org/ to enable vanilla kernel to be built with LLVM. Lot of patches are prepared by Behan Webster, who is LLVMLinux project lead.

There is LWN article about the project from May 2013
https://lwn.net/Articles/549203/ "LFCS: The LLVMLinux project"

Current status of LLVMLinux project is tracked at page http://llvm.linuxfoundation.org/index.php/Bugs#Linux_Kernel_Issues

Things (basically gcc-isms) already eliminated from kernel:
* Expicit Registers Variables (non-C99)
* VLAIS (non C99-compliant undocumented GCC feature "Variable length arrays in structs") like struct S { int array[N];} or even struct S { int array[N]; int array_usb_gadget[M]; } where N and M are non-constant function argument
* Nested Functions (Ada feature ported into C by GCC/Gnat developers; not allowed in C99)
* Some gcc/gas magic like special segments, or macro

Things to be done:
* Usage of __builtin_constant_p builtin to implement scary magic like BUILD_BUG_ON(!__builtin_constant_p(offset));

The good news about LLVMLinux are that after its patches kernel not only becomes buildable with LLVM+clang, but also easier to build by other non-GCC compilers, because the project kills much not C99 code like VLAIS, created by usb gadget author, by netfilter hackers, and by crypto subsystem hackers; also nested functions are killed.

How to pass compiler options during Linux kernel compilation?

From Linux kernel's makefile:

# Add any arch overrides and user supplied CPPFLAGS, AFLAGS and CFLAGS as the
# last assignments
KBUILD_CPPFLAGS += $(ARCH_CPPFLAGS) $(KCPPFLAGS)
KBUILD_AFLAGS += $(ARCH_AFLAGS) $(KAFLAGS)
KBUILD_CFLAGS += $(ARCH_CFLAGS) $(KCFLAGS)

So, passing additional options for Kbuild uses usual environment/makefile variables but with K prefix:

make "KCFLAGS=-pipe -Wsomething"

Rebuild linux kernel module for another architecture

You could try:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- M=path/to/the/module/

Also read:

Cross compiling a kernel module

gcc-arm-linux-gnueabi command not found

warnings while trying to compile old linux kernel with gcc 12.1.0

To compile older version of kernel I needed older compiler ("Linux kernel sources are in general not forward-compatible with new compilers"). In my case the kernel version was 5.16.0 and I could compile it with gcc 11. If you have gcc 11 specific warnings then try gcc 10 and so on.

Except CC flags, I also needed set to HOSTCC flags to use gcc-11 compiler:

make HOSTCC=gcc-11 CC=gcc-11

How do we compile kernel code in C?


I am trying to compile it this way
gcc -c -O2 -W -Wall -isystem /lib/modules/'uname -r'/build/include -D_KERNEL_ -DMODULE measurecpu.c

Usually the way to compile a kernel module is to use the kernel build system - ie you use make instead of gcc directly. You need to create a Makefile and specify the object, which is the line obj-m := measurecpu.o in your case. After that in the same directory, issue the make command, which will yield the kernel object file measurecpu.ko

# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := measurecpu.o

# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean

endif

Note that kernel module is not user space program, so you cannot just run it. You will need to tell the kernel about that kernel module via insmod, and check the results via dmesg.

Compile a linux 2.6 kernel module with newer compiler

Your kernel version is too old and it is missing linux/compiler-gcc5.h.

The header is included from linux/compiler-gcc.h and its name is generated by preprocessor macro based on current compiler version:

#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)

This header was introduced around version 3.18.

You might try to get this file from a newer kernel source and put in into include/linux.



Related Topics



Leave a reply



Submit