Compiling a kernel driver that has multiple source files

By | March 27, 2008

All the drivers that I had dealt with until today where written in just one source file. But today I had several problems trying to compile a driver for a 2.6 kernel that had several source files. Most of the info I found like in the LKMPG and in LDD3, did not work for me. The problem was with my Makefile that I was writing in this way (the tabs after the all and clean targets were removed due to formatting issues):

PWD = $(shell pwd)
obj-m += modmain.o
modmain-objs += file1.o
all:
make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) clean

The files in my dir were:

$ ls
file1.c  file1.h  Makefile  modmain.c

If you follow the LKMPG or other sources you see that this seems correct: I wanted to compile a couple of files, modmain.c that contains the module init/exit funcs, and file.c that contains funcs used in modmain.c, and generate a driver module modmain.ko..
After compiling and linking without problems, I insmod the module but I didn’t see any of the printk() I wrote, in fact, the driver can be inserted and removed, but it does nothing.
After a while, I use nm to check which symbols were inside the driver and to my surprise the only symbols inside the .ko were

00000000 r __func__.1640
00000020 r __mod_vermagic5
00000000 r __module_depends
00000000 D __this_module
00000000 T init_stuff
U printk

No signs of init_module and friends. At this point I realized that the file modmain.c was not being compiled. In fact, my output from the Makefile was the following:

$ make
make -C /lib/modules/2.6.23.1-42.fc8/build SUBDIRS=/home/piter/code/c modules
make[1]: Entering directory '/usr/src/kernels/2.6.23.1-42.fc8-i686'
CC [M]  /home/piter/code/c/file1.o
LD [M]  /home/piter/code/c/modmain.o
Building modules, stage 2.
MODPOST 1 modules
CC      /home/piter/code/c/modmain.mod.o
LD [M]  /home/piter/code/c/modmain.ko
make[1]: Leaving directory '/usr/src/kernels/2.6.23.1-42.fc8-i686'

modmain.c was not being compiled!

After playing around with the Makefile I got the right file (again, the tabs after the all and clean targets were removed due to formatting issues):

PWD = $(shell pwd)
obj-m += mymod.o
mymod-objs += file1.o modmain.o
all:
make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) clean

Now, the output when compiling and linking is the following:

$ make
make -C /lib/modules/2.6.23.1-42.fc8/build SUBDIRS=/home/piter/code/c modules
make[1]: Entering directory '/usr/src/kernels/2.6.23.1-42.fc8-i686'
CC [M]  /home/piter/code/c/file1.o
CC [M]  /home/piter/code/c/modmain.o
LD [M]  /home/piter/code/c/mymod.o
Building modules, stage 2.
MODPOST 1 modules
CC      /home/piter/code/c/mymod.mod.o
LD [M]  /home/piter/code/c/mymod.ko
make[1]: Leaving directory '/usr/src/kernels/2.6.23.1-42.fc8-i686'

modmain.c is being compiled this time!
And nm says the following:

00000000 r __func__.1640
00000017 r __func__.8988
0000000b r __func__.8993
00000024 r __mod_author6
0000000c r __mod_description7
00000000 r __mod_license8
00000080 r __mod_vermagic5
00000060 r __module_depends
00000000 D __this_module
00000000 T cleanup_module
00000000 T init_module
00000000 T init_stuff
00000000 t my_mod_exit
00000000 t my_mod_init
U printk

The symbols used in modmain.c appear normally.

Conclusion
I changed the final driver name to mymod.ko and the file modmain.c is now part of the mymod-objs variable, in this way I’m sure that it’s compiled. Notice that the final driver name is different from any of the source files, including the file that contains the module_init/exit funcs.

Notice
Since I had the above mentioned issues for compiling a driver that has multiple source files following commonly linux kernel drivers docs and I have seen other people in the same situation, I decided to share the procedure that worked for me, but this does not mean in any way that the references I used were mistaken, most probably I missed something.

6 thoughts on “Compiling a kernel driver that has multiple source files

  1. Nick Formaber

    Thank you very much for this post! It solved the same issue I had!

    Was searching for more than 2 hours (in stackoverflow, etc.) before finding your post 🙂

    Reply
  2. Irfan Ullah

    I am facing the same problem. I have tested the solution but it does not work for me. I am using kernel version 5.2, and GNU make version 4.1?
    Thanks

    Reply
    1. paguilar Post author

      I haven’t tried with the 5.x kernels, but this procedure should work since it’s standard since the 2.6.x versions.
      Have you checked that the file names are right? The .ko file should have a different name than the source files.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *