Linux Kernel generate compile-commands.json for module - c

The problem: Most of macro definition and even header files are not looked up by an IDE because include path is not specified in the IDE configuration. It inhibits autocompletion and navigation.
Here is my Makefile:
#-Wno-declaration-after-statement
ccflags-y := -std=gnu11 -Wno-declaration-after-statement -Werror
obj-m += pfsw.o
pfsw-objs := src/init.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
I ran make V=1 and noticed that the compile command along with include path is actually pretty cumbersome (counting Linux Specific -include for parameters):
gcc -Wp,-MD,/home/memyself/lkm/procfs_write/src/.init.o.d -nostdinc
-isystem /usr/lib/gcc/x86_64-linux-gnu/7/include
-I./arch/x86/include -I./arch/x86/include/generated -I./include -I./arch/x86/include/uapi
-I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi
-include ./include/linux/kconfig.h -Iubuntu/include -include ./include/linux/compiler_types.h
-D__KERNEL__
//tons of options ommitted...
-c -o /home/memyself/lkm/procfs_write/src/init.o
/home/memyself/lkm/procfs_write/src/init.c
Question: Is there a way to generate compile-command.json to inform IDE about include paths? Or the only solution is to manually pass the include path to the IDE one by one?

Due to CLang has a lot of different tools, including some to analyze the code, the compile-command.json is required. That's why Tom Roeder from Google provided a
scripts/clang-tools/gen_compile_commands.py in the commit b30204640192 ("scripts: add a tool to produce a compile_commands.json file") for this.
Note, kernel must be compiled at list once to make this script work.
P.S. I suppose you are trying MS Visual Studio Code?
Kudos to colleague of mine, Alex, who is user of it and told me about existence of such script.

Related

kernel module doesn't search for include library when -I is used

I want to build a basic main.c, that is actually a kernel module written in C. I have include header files that are in include/. I want to use GCC -I to make GCC search for the include headers in -Iinclude. However, GCC doesn't seem to understand that, and I have no clue how to debug it.
Tree:
main.c
include
file.h
main.c
#include "file.h"
...
Makefile:
EXTRA_CFLAGS += -Iinclude -Werror -Wall \
-Wno-missing-braces -Wno-error=unused-function
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
The error:
main.c: fatal error: file.h: No such file or directory
That's because make is not actually running in your directory, when it compiles things.
The -C option in this command:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
tells make to change it's current working directory to that path. Thus, include is no longer the include directory in your current directory.
You should write it like this:
EXTRA_CFLAGS += -I'$M/include' -Werror -Wall \
-Wno-missing-braces -Wno-error=unused-function
all:
$(MAKE) -C "/lib/modules/$$(uname -r)/build" M='$(CURDIR)' modules
clean:
$(MAKE) -C "/lib/modules/$$(uname -r)/build" M='$(CURDIR)' clean
You should always use $(MAKE), and never make, when running a sub-make. And using make's shell function is not really needed since a recipe is already running in a shell. And, PWD is just inherited from the calling shell and might be inaccurate.

How specify optimization level of compilation for kernel module [duplicate]

Eg: a common device module's Makefile
obj-m:=jc.o
default:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules clean
I consider if I can set CFLAGS to the file. When I change default section to
$(MAKE) -O2 -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
But it didn't work.
Any help? Thanks a lot.
-O2 would be an option to make (or $(MAKE), as you're using it) in what you tried. Obviously, the compiler (probably gcc) needs this flag, not make.
Kbuild understands a make variable named CFLAGS_modulename.o to add specific C flags when compiling this unit. In your case, your module object will be jc.o, so you can specify:
CFLAGS_jc.o := -O2
and it should work. Add V=1 to your $(MAKE) lines to get a verbose output and you should see -O2 when jc.c is being compiled.
You can find more about compiling modules in the official documentation.
You can also use
ccflags-y := -O2
This will be applied to all of the source files compiled for your module with the Makefile. This is indirectly documented in the link provided by eepp in Section 4.2

GCC Kernel Module Compilation Errors

I'm working on a netfilter and compiling it on a virtual machine.
matt#ubuntu:~$ make
gcc -c -O2 -W -isystem /lib/modules/4.4.0-87-generic/build/include -D__KERNEL__ -DMODULE test10.c -I.
In file included from /usr/src/linux-headers-4.4.0-87/include/linux/kernel.h:6:0,
from structs1.h:2,
from test10.c:1:
/usr/src/linux-headers-4.4.0-87/include/linux/linkage.h:7:25: fatal error: asm/linkage.h: No such file or directory
compilation terminated.
makefile:2: recipe for target 'test' failed
make: *** [test] Error 1
Above is my GCC command used to attempt to build my kernel module and the subsequent error that it throws.
In researching this, I have found one possible solution that involves specifiying the kernel version as such:
KERNEL_VER=/usr/src/linux-headers-4.4.0-87/arch/x86/
But two problems:
I'm not sure how to actually use this in my make file which can be seen below, outside of just making a symbolic link, and
I looked in this folder (/usr/src/linux-headers-4.4.0-87/arch/x86/) and sub folders and it doesn't have any of the same kernel.h files -- which is what I need.
Makefile:
test:
gcc -c -O2 -W -isystem /lib/modules/4.4.0-87-generic/build/include -D__KERNEL__ -DMODULE test10.c -I.
Any help on this would be greatly appreciated.
The standard Makefile used to build a loadable kernel module is as follows.
obj-m += test10.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Refer Compiling a loadable kernel module this for more information.

Error compiling kernel module with two source files

I am trying to compile a kernel module that has two .c files. My Makefile is the following
module-y: dummy.o library.o
obj-m += module.o
default:
make -C /lib/modules/`uname -r`/build M=$(PWD) modules
When I run this I get
cc -c -o dummy.o dummy.c
dummy.c:3:24: fatal error: linux/init.h: No such file or directory
It seems the Makefile doesn't know where to find the headers now.
I have tried using CFLAGS to add include directories, but there are so many of them that it becomes tedious and hard to do (haven't managed to make it work).
I would like to generate these two .o files using the include directories that are (magically) used when using a single .c file. Everything works fine in that case.
How to fix the include directories when using two source files?
I wrote the Makefile like the following, and it worked:
ifneq ($(KERNELRELEASE),)
# kbuild part of makefile
obj-m := module.o
module-y := library.o dummy.o
else
# normal makefile
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD modules
endif

Propagate V=s Flage to all sub makefiles

When ever I build kernel modules using make, I get this kind of logs
CC[M] module1
CC[M] module2
CC[M] module3
CC[M] module4
i.e just compilation or linking info about any module currently being processed.
I need to know complete information that which commands actually compiles the modules source code, what are the flags used in those command etc. e.g
gcc -Wall abcd.c
I even checked it by setting V=s , V=1, -n and -d but couldn't get what I want.
Kindly tell me how to make V=s propagate through each and every subsequent makefiles. It could be done by exporting, by how?
Thanks
There are two kinds of methods:
You can build modules with "make V=1" to print verbose messages.
You can also do this by putting "export KBUILD_VERBOSE=1" line into your Makefile.
Here is an example of makefile:
TARGET :=sysfs-sample
export KBUILD_VERBOSE=1
obj-m += $(TARGET).o
$(TARGET)-objs := main.o
MODULE_DIR := "$(PWD)"
all:
CROSS_COMPILE= ARCH=x86 make -C /lib/modules/$(shell uname -r)/build M=$(MODULE_DIR) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(MODULE_DIR) clean

Resources