I am writing to you because I am having an issue with my module compilation written in C for Kernel and I even can't find documentation which would be helpful for me.
My issue looks like following:
There are several files written in C like this: configuration_header.h
#ifndef CONFIGURATION_HEADER_H
#define CONFIGURATION_HEADER_H
// Some code here
#endif
library_header.h
#ifndef LIBRARY_HEADER_H
#define LIBRARY_HEADER_H
#include "configuration_header.h"
// Some code here
#endif
library_header.c
#ifndef LIBRARY_HEADER_C
#define LIBRARY_HEADER_C
#include "library_header.h"
#include <linux/string.h>
// Some code here
#endif
module_initialization.h
#ifndef MODULE_INITIALIZATION_H
#define MODULE_INITIALIZATION_H
// Some code here
#endif
module_initialization.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
#include "library_header.h"
#include "module_initialization.h"
// module_init, module_exit functions and the related stuff.
#endif
And here I am trying to make this using following Makefiles:
Makefile1:
KDIR := /lib/modules/$(shell uname -r)/build
obj-m += module_initialization.o
lib-m += library_header.o
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm *.o
make -C $(KDIR) M=$(PWD) clean
.PHONY: all clean
Makefile2:
KDIR := /lib/modules/$(shell uname -r)/build
obj-m += module_initialization.o library_header.o
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm *.o
make -C $(KDIR) M=$(PWD) clean
.PHONY: all clean
Makefile3:
KDIR := /lib/modules/$(shell uname -r)/build
#MODULE_NAME := module_initialization.o <-- Typo in the initial question, I am sorry for that.
MODULE_NAME := module_initialization
obj-m += $(MODULE_NAME).o
$(MODULE_NAME)-objs := library_header.o
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
.PHONY: all clean
None of above worked. After compilation according the first version I am getting following error:
ERROR: modpost: "library_header_initialization" [/home/user/Code/C/MemoryReader-v1.a/configuration_test.ko] undefined!
make[3]: *** [scripts/Makefile.modpost:145: /home/user/Code/C/MemoryReader-v1.a/Module.symvers] Error 1
make[2]: *** [/usr/src/linux-headers-6.11.0-26-generic/Makefile:1879: modpost] Error 2
make[1]: *** [Makefile:224: __sub-make] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-6.11.0-26-generic'
make: *** [Makefile:14: all] Error 2
I in the first moment thought that there is somewhere an error in the program but I have noticed that there is library_header.o file never created so it seemed to me like the code was never compiled properly.
According to the second version of the Makefile the code is compiled if I will modify it somehow, but it will create two .ko modules and this is something what I don't want to do.
How can I write proper Makefile for the code above to get the module successfully compiled? Is there any documentation which would document well Makefiles used for Linux Kernel compilation? I know it should be possible because I saw another code far more complex than mine which seems like it work this way but I didn't find out how the Makefiles of such code works. Btw. I also tried a few advises from AI but the code from it is the third version and it doesn't work either because of the printk functions - resp. their equivalents doesn't write an output to the log (the last version of Makefile is from AI).
I have tried to write various Makefile versions and none worked. Also I have tried to find a documentation but with no success.
For Craig Estey:
Craig, thank you for your quick reply! The error is a typo done by myself because I was writing the names which are more suitable for the problem understanding. The actual Makefile which was created without the filenames modification looks like following:
# Specify the kernel build directory
KDIR := /lib/modules/$(shell uname -r)/build
# Specify the module name
MODULE_NAME := configuration_test
# List all object files needed for the module
obj-m += $(MODULE_NAME).o
# Specify the source files for the module
$(MODULE_NAME)-objs := configuration.o # Add other object files as needed
# The default target
all:
make -C $(KDIR) M=$(PWD) modules
# Clean target
clean:
make -C $(KDIR) M=$(PWD) clean
.PHONY: all clean
After using it I am getting following errors:
make -C /lib/modules/6.11.0-26-generic/build M=/home/user/Code/C/MemoryReader-v1.a modules
make[1]: Entering directory '/usr/src/linux-headers-6.11.0-26-generic'
warning: the compiler differs from the one used to build the kernel
The kernel was built by:
x86_64-linux-gnu-gcc-13 (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
You are using:
gcc-13 (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
MODPOST /home/user/Code/C/MemoryReader-v1.a/Module.symvers ERROR:
modpost: "MemoryReaderSettingsInit" [/home/user/Code/C/MemoryReader-v1.a/configuration_test.ko] undefined!
make[3]: *** [scripts/Makefile.modpost:145:
/home/user/Code/C/MemoryReader-v1.a/Module.symvers] Error 1
make[2]: *** [/usr/src/linux-headers-6.11.0-26-generic/Makefile:1879: modpost] Error 2
make[1]: *** [Makefile:224: __sub-make] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-6.11.0-26-generic'
make: *** [Makefile-ai:15: all] Error 2
The file configuration.o (or library_header.o) according to the initial example is not present so it looks like it isn't compiled to me for a reason. I am getting no error during compilation, but only warnings.
I even can't find documentation which would be helpful for me.
The documentation for the kernel build system is here: https://docs.kernel.org/kbuild/makefiles.html. It goes into considerable detail, with examples, including of a case analogous to yours. It's probably worth reading in whole, but the part most relevant to this question is https://docs.kernel.org/kbuild/makefiles.html#loadable-module-goals-obj-m.
Here are some key points about the kbuild framework, as conveyed by that documentation:
The obj-m
variable lists objects that are to be built as kernel modules. In the usual case where your makefile covers just one module, it will add only one object to this variable, no matter how many source files are involved in building it. The name(s) listed here is the module name as far as the kernel is concerned.
A <module>-y
variable (if present) lists the object files contributing to module <module>. These will be built as ordinary object files, to subsequently be linked together to form the module object. It follows, among other things, that the module object must not be in this list (it is built from these, not one of them), but there must be an object listed for each contributing source file. Additionally, that implies that when this facility is used, none of your source file names should exactly match the module name, contrary to the single-source case.
Since the question shows an attempt involving building a library,
Here's how a kbuild file for your example might look:
KDIR := /lib/modules/$(shell uname -r)/build
# The name of this module is "module"
obj-m += module.o
module-y := module_initialization.o library_header.o
# Convenience targets for an external module:
all:
make -C $(KDIR) M=$$(pwd) modules
install:
make -C $(KDIR) M=$$(pwd) modules_install
clean:
make -C $(KDIR) M=$$(pwd) clean
.PHONY: all clean install
=====================================================================
Edit from yrvsvd [modified]:
Module names apparently have some naming conventions which need to be followed. Here is a variation on the above that worked for me, based on this section of the doc: https://docs.kernel.org/kbuild/modules.html#shared-makefile:
KDIR := /lib/modules/$(shell uname -r)/build
obj-m += m1515.o
m1515-y := m1515-configuration.o m1515-initialization.o
all:
make -C $(KDIR) M=$$(pwd) modules
clean:
make -C $(KDIR) M=$$(pwd) clean
.PHONY: all clean