3

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.

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

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.

halfer
20.2k20 gold badges110 silver badges207 bronze badges
asked Jun 20 at 15:13
8
  • 1
    This question is similar to: Building a kernel module from several source files which one of them has the same name as the module. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Jun 20 at 16:31
  • When using multiple .c files, the name of the module must be different from any .c basename. Commented Jun 20 at 18:44
  • stackoverflow community had gone into some territory. I just can not name it properly. Imagine, I read pages of question text to find out that a root cause was a typo. The question upvoted BTW. Commented Jun 20 at 22:25
  • And the answerer who did the job of finding a typo, who had a burden of looking through pages of a text written by complete stranger, the answerer is downvoted. Commented Jun 20 at 22:28
  • the situation I see not the first time, here on SO. People efforts priced like junk. Tell me, SO community, why it is more and more situations like this? Why should I spend an hour, where the poster will spend a minutes of copy paste from AI and drop this junk to the question? The OP will drop upvote(at maximum). Is it really thinked of as a motivation? Commented Jun 20 at 22:36

2 Answers 2

1

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,

  • You can build libraries, but this is not ordinarily part of building modules from multiple sources, and it rarely makes sense for externally-built modules.

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
answered Jun 22 at 1:50
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I am reading the doc around it this time +1 - I wanted to add a reply after I will have read more about it and not only the part about the modules but it seems that you were way more quicker. The module was compiled now. It is still not working because I am getting following error: insmod: ERROR: could not insert module ./module.ko: Invalid parameters, but the error which I was getting was finally solved and now I have even the link to the doc (which I would maybe find sooner in case I would more read and less ask). So in general the solution helps and solves the issue which I had.
The error which I was experiencing - that means: insmod: ERROR: could not insert module module.ko: Invalid parameters disappeared after the module renaming with the specific name and with the name addition as a prefix as is according to the following documentation: docs.kernel.org/kbuild/modules.html#shared-makefile There is also a bunch of other interesting docs in the location but this seems me as the most important now.
1

I've created kernel modules in the past that used multiple .o files. But, it's been a number of years ;-) I dug deep into an archive and found an old makefile.

It is similar your Makefile3 version. But, you didn't show the error output for that version.

But, you have a "double .o" in your makefile. Here is a corrected version. I've desk checked it but didn't test it:

KDIR := /lib/modules/$(shell uname -r)/build
# NOTE/BUG:
###MODULE_NAME := module_initialization.o
# NOTE/FIX:
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
answered Jun 20 at 15:49

6 Comments

Thanks for the explanation, the error is a typo caused by me writing the example and as I was using an example file names I wrote the typo. The actual Makefile including the file names from the disk 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:
Ah, I am sorry, it seems that the comment won't let me discuss with too long text, so the error: 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'
$(MODULE_NAME)-objs := library_header.o - This creates a kernel module from the single source file, library_header.c. The other source file, module_initialization.o, is not compiled, because it is not specified in the Makefile.
Thanks everyone for the responses, can I also ask if you are familiar regarding some documentation about the Makefile usage?
Generic Makefile documentation is widely available (e.g. info make). As to the kernel, maybe the best way is to find an existing Makefile that already does multiple .o files and learn/copy from that (that's what a lot of kernel developers would do). AFAICT, for your latest error, the symbol MemoryReaderSettingsInit is undefined. So, what .c file do you define it in? The corresponding .o has to be listed in either obj-m or modname-objs Use nm on the .o files to check. BTW, you should put error text in a code block in your question vs using >, etc.
Thanks for the response, MemoryReaderSettingsInitMemoryReaderSettingsInit was implemented in the related library. The issue was solved in the comment above.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.