Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eudyptula Challenge and kernel path

I have decided to take the Eudyptula Challenge. After I submitted the first task which is to build a simple "Hello World!" module, I received the following answer.

Please read the requirements for the Makefile and allow the module to be built against any kernel source tree on the filesystem, not just those kernels that happened to be installed in /lib/ at some point in time.

The requirements are:

The Makefile should be able to build the kernel module against the source of the currently-running kernel as well as being able to accept an arbitrary kernel sources directory from an environment variable.

What I am doing is checking whether the environment variable KERNELRELEASE is set. If it is I build the module against

$(KERNELRELEASE)/build  

and if it isn't against

/lib/modules/$(shell uname -r)/build

I can't understand why this does not satisfy the requirements of this task.

like image 559
user2424276 Avatar asked May 04 '15 13:05

user2424276


1 Answers

As per Eudyptula challenge rules, it is prohibited to give you direct solution, so I will try to describe elements of answer, so you can come up with solution by yourself. Basically, everything I've written below is described pretty much in Documentation/kbuild/modules.txt file (especially in section 3.1 - Shared Makefile ), so I don't think it would be some sort of rules violation. So below is just explanation for what is described in mentioned documentation.

KERNELRELEASE variable

What you are wrong about is thinking that $(KERNELRELEASE) is intended for keeping the path to the kernel. What $(KERNELRELEASE) variable actually means -- you can find it in Documentation/kbuild/makefiles.txt:

KERNELRELEASE

$(KERNELRELEASE) is a single string such as "2.4.0-pre4", suitable for constructing installation directory names or showing in version strings. Some arch Makefiles use it for this purpose.

The thing is, your Makefile is going to be executed 2 times: from your make command and from kernel Makefile. And $(KERNELRELEASE) can be helpful to figure it out:

  1. If this variable is not defined, your Makefile is running from your make command; at this step you are going to execute kernel's Makefile (providing kernel directory using -C param). Once you have run make for kernel's Makefile (from inside of your Makefile), your Makefile is going to be executed second time (see next item).
  2. If this variable is defined, your Makefile is executing from kernel's Makefile (which defined this variable and called your Makefile back). At this step you can use kernel build system features, like obj-m.

-C param

What you really need to do is define some custom variable in your Makefile which will hold kernel directory path. You can call it KDIR for example. As you know, your kernel sources are located at this path: /lib/modules/$(shell uname -r)/build. Next you can provide this variable to -C param (see man 1 make) when executing kernel's Makefile.

Next you have to make it possible to pass this variable from outside of your Makefile. To do so, one can use conditional variable assignment operator:

KDIR ?= /lib/modules/$(shell uname -r)/build

This way if you pass KDIR variable to your Makefile, like this:

$ make KDIR=bla-bla-bla

the KDIR variable will have the value you passed. Otherwise it will contain default value, which is /lib/modules/$(shell uname -r)/build.

like image 181
Sam Protsenko Avatar answered Oct 05 '22 18:10

Sam Protsenko