1
votes

I'm trying to write a simple hello world kernel module. I'm working in Ubuntu 18.04.2 LTS on Virtual Box. In the directory /usr/src I created a directory named hello and inside that hello directory I've created hello.c and a makefile. Here is my makefile:

obj-m += hello.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

When I make the command "sudo make" I get this output:

make -C /lib/modules/5.3.0-28-generic/build M= modules
make[1]: Entering directory '/usr/src/linux-headers-5.3.0-28-generic'
make[2]: *** No rule to make target 'arch/x89/tools/relocs_32.c', needed by 'arch/x86/tools/relocs_32.o'. Stop.
arch/x86/Makefile:232: recipe for target 'archscripts' failed
make[1]: *** [archscripts] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.3.0-28-generic'
makefile:4: recipe for target 'all' failed
make: *** [all] Error 2

I've tried a few variations of my makefile including changing "PWD" to "shell pwd". I've installed all the essential tools and libraries as far as I know. What could be the problem here?

2
What does x89 mean in your log?0andriy

2 Answers

2
votes

Variable PWD is set by the shell, so your Makefile relies on make invocation to be performed from the shell, as we normally do when type make in the terminal.

But sudo make executes make from a plain user environment. This environment lacks for PWD variable, so your Makefile behaves incorrectly. This can be found from your output:

make -C /lib/modules/5.3.0-28-generic/build M= modules

Use $(shell pwd) expression instead, it is more reliable:

obj-m += hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

Alternatively, you may call make with root privileges using this way:

sudo /bin/sh -c make

This way make is executed not from the plain root environment, but under an intermediate shell. This shell sets PWD variable.

Update

As noted by @Ian Abbott in the comments, another alternative for $(PWD) is $(CURDIR). Variable CURDIR is set by the make itself (precisely, by GNU Make). See also that question: bash: What is the difference between PWD and CURDIR?.

0
votes

Your Makefile should look like this

obj-m += hello.o

Then your build command will look like

make -C $KDIR M=$PWD

Where $KDIR is the source tree of your kernel build.

is the way. The rest is handled by the kbuild system.

Please refer to refer to the official documentation for building off-tree modules