Reputation: 143
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?
Upvotes: 1
Views: 6462
Reputation: 66298
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?.
Upvotes: 3
Reputation: 1329
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
Upvotes: 0