obj-m variable in a kernel module - linux

In the kernel module makefile obj-m variable exists. Consider the following:
CUR = $(shell uname -r)
DIR = /lib/modules/$(CUR)/build
PWD = $(shell pwd)
obj-m := m1.o m2.o
default:
$(MAKE) -C $(DIR) SUBDIRS=$(PWD) modules
In this Makefile, the default target contains a recipe which invokes kernel sub-make. The obj-m variable doesn't get exported to environment thus sub-make cannot use it. But if we delete the obj-m variable initialization, then this make doesn't compile m1 and m2 kernel modules. So, question is:
Why kernel sub-make depends on the non-exported obj-m variable in this case?

None of the make variables are exported to the environment.
SUBDIRS gets defined as a make variable.
The kernel makefile looks for the Makefile in SUBDIRS, reads it, and uses any obj-* defined therein.
(According to the documentation, you should use M instead of SUBDIRS.)

Related

Makefile for a kernel module to keep all .o .ko .order .mod files in build/ directory [duplicate]

I'm confronting the Linux kernel build system (Kbuild, kernel ≥2.6.28) with the directory structure and build system for a larger project. Our project contains an out-of-tree Linux kernel module, and our directory structure looks like this (simplified, obviously):
checkout/src/common/*.c source files (common to Linux and other platforms)
checkout/src/linux-driver/*.c source files (for the Linux kernel driver)
checkout/build/linux/Kbuild Kbuild
tmp/linux-2.6.xx/ where the Linux kernel is unpacked and configured
output/linux-arm-debug/ where object files must end up
The build process must not modify anything under checkout, and building the module must not modify anything under tmp/linux-2.6.xx. All output files must end up under output/linux-arm-debug (or whatever architecture and debug variant was selected at build time).
I've read kbuild/modules.txt, and started to write my Kbuild file:
MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG)
obj-m += $(MOD_OUTPUT_DIR)/foo_mod.o
$(MOD_OUTPUT_DIR)/our_module-objs := $(MOD_OUTPUT_DIR)/foo_common.o $(MOD_OUTPUT_DIR)/foo_linux.o
This handles storing the object files in a different directory from where Kbuild lives. Now how can I specify that foo_common.o needs to be compiled from …/checkout/src/common/foo_common.c and foo_linux.o from …/checkout/src/linux-driver/foo_linux.c?
Here is a Makefile which does out of source-tree builds for out of kernel-tree modules (adapted from #Mark's comment)...
KDIR ?= /lib/modules/$(shell uname -r)/build
BUILD_DIR ?= $(PWD)/build
BUILD_DIR_MAKEFILE ?= $(PWD)/build/Makefile
default: $(BUILD_DIR_MAKEFILE)
make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) modules
$(BUILD_DIR):
mkdir -p "$#"
$(BUILD_DIR_MAKEFILE): $(BUILD_DIR)
touch "$#"
clean:
make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) clean
Note: You still need a Kbuild file...
obj-m += my_driver.o
I had a similar problem. I modified linux_2_6_34/scripts/Makefile.build as follows.
ifdef SRCDIR
src := $(SRCDIR)
else
src := $(obj)
endif
SRCDIR is the directory source.
To compile the module, run
make -c $(KDIR) M=$(Your_output_dir) SRCDIR=$(your source directory)`
My inelegant but effective solution is to copy the source files into the output tree.
FOO_SOURCES_DIR = $(src)/../../../checkout/src
FOO_MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG)
# Specify the object files
obj-m += $(FOO_MOD_OUTPUT_DIR)/foo_mod.o
FOO_MODULE_OBJS := $(FOO_MOD_OUTPUT_DIR)/foo_common.o $(FOO_MOD_OUTPUT_DIR)/foo_linux.o
$(FOO_MOD_OUTPUT_DIR)/foo_mod-objs := $(FOO_MODULE_OBJS)
# Where to find the sources
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_common.c: $(FOO_SOURCES_DIR)/common/foo_common.c
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_linux.c: $(FOO_SOURCES_DIR)/linux-driver/foo_linux.c
# Rules to copy the sources
FOO_COPIED_SOURCES = $(patsubst %.o,$(src)/%.c,$(FOO_MODULE_OBJS))
$(FOO_COPIED_SOURCES):
$(Q)mkdir -p $(#D)
cp -f $< $#
clean-files += $(FOO_COPIED_SOURCES)
clean-dirs += $(FOO_MOD_OUTPUT_DIR)
While you haven't mentioned what you've tried so far (or whether you found a solution already), it looks like you just need to continue further down the modules.txt file a bit -- to Section 4.3:
--- 4.3 Several Subdirectories
kbuild can handle files that are spread over several directories.
Consider the following example:
.
|__ src
| |__ complex_main.c
| |__ hal
| |__ hardwareif.c
| |__ include
| |__ hardwareif.h
|__ include
|__ complex.h
To build the module complex.ko, we then need the following
kbuild file:
--> filename: Kbuild
obj-m := complex.o
complex-y := src/complex_main.o
complex-y += src/hal/hardwareif.o
ccflags-y := -I$(src)/include
ccflags-y += -I$(src)/src/hal/include
As you can see, kbuild knows how to handle object files located
in other directories. The trick is to specify the directory
relative to the kbuild file's location. That being said, this
is NOT recommended practice.
For the header files, kbuild must be explicitly told where to
look. When kbuild executes, the current directory is always the
root of the kernel tree (the argument to "-C") and therefore an
absolute path is needed. $(src) provides the absolute path by
pointing to the directory where the currently executing kbuild
file is located.
A bit late, but it looks like O= flag is what you need.
You can set the environment variable KBUILD_OUTPUT. This functions similar to the O= option; however, since it's an environment variable, it can span multiple makefiles where O= can't be passed or an out-of-directory module needs to be built. I was having this same issue with trying to build a set of compat-wireless modules and I needed to use O= for the actual kernel image build.

How to rename a kernel module name without renaming the .ko passed to insmod?

I need to rename a kernel module (the name that get displayed with lsmod) of an already existing driver without changing the name of the source file.
e.g.
# insmod xxx.ko
<<module loads successfully>>
# lsmod
Module Size Used by Tainted: P
xxx 191527 0
#
I want to rename xxx to yyy.
Now I know that changing the name of the driver source file (when it involves a single file) changes the name of the module.
But I don't want to change the name of a source file.
Rename your obj-m in Makefile and set dependency of obj-m to original module.
For example, I have file hello.c that contain all of my source code. But I want module to be mynewname.
Here is whole Makefile that does this:
obj-m := mynewname.o
mynewname-objs := hello.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
I set obj-m to mynewname.o and make mynewname.o dependant on hello.o. After invoking make you'll get mynewname.ko.

Compiling out-of-tree kernel module against any kernel source tree on the filesystem

I am trying to compile a module against any source tree on the file system but I am having trouble with the Makefile. This was the original Makefile I had against the kernel specified:
obj-m += new-mod.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
This Makefile would compile correctly, but goal is to have it compile against any source tree. I have tried just:
obj-m += new-mod.o
I thought that "all:" is assumed but I get error:
make: *** No targets. Stop.
I have also added:
all:
to the Makefile with no difference except for error message:
make: Nothing to be done for `all'
I have tried a lot of documentation but no luck. I would greatly appreciate any help.
goal is to have it compile against any source tree
ya you can do it providing a compiled source-code path
just replace make -C /lib/modules/$(shell uname -r)/build M=$PWD modules
with this
make -C <path-to-compiled-src-code> M=$PWD modules
make -C /home/vinay/linux-3.9 M=$PWD modules
try below makefile
Makefile –
# if KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq (${KERNELRELEASE},)
obj-m := new-mod.o
# Otherwise we were called directly from the command line.
# Invoke the kernel build system.
else
KERNEL_SOURCE := /usr/src/linux
PWD := $(shell pwd)
default:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules
clean:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
endif
In above you can change KERNEL_SOURCE := /usr/src/linux-->to.--> your sr-code KERNEL_SOURCE := <path to compiled-src-code>
for further info find below liks
while building kernel modules why do we need /lib/modules?
A simple program on linux device driver
How to make a built-in device driver in linux
Build against your custom kernel source ( not the one that is installed),
You can use following steps.
1.download kernel from kernel.org (tar)
2.Extract
3.make x86_64_defconfig
4.make prepare
5.make modules_prepare
Now you have to change Makefile to point to kernel source you had downloaded and extracted. Something similar mentioned in example by Vinay Answer.
Just remember you cannot insmod this module as kernel running and module built is for different kernel.

Compiling Linux Kernel Module With A Custom Header

I would like to compile a simple character device module depending on a custom header. The folder is thus organized,
+ mymod.c
| customized-header.h
| customized-header.c
| Makefile
In mymod.c, the header is thus used,
#include "customized-header.h"
In Makefile:
obj-m := mymod.o
mymod-objs := customized-header.o
KVERSION = $(shell uname -r)
PWD = $(shell pwd)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
Everything should work fine, the module gets compiled without problem, I can load the module through sudo insmod, but the module doesn't work properly. When I checked nm mymod.ko, there are a lot of vars and functions are missing. It looks as if it stopped after linking customized_header.o. If I remove this header and its function, say no header function calls from the module, it compiles perfectly with desired result.
Could you see what went wrong here?
The problem resides in the Makefile. Due to the link here, I changed it into
obj-m: mymodko.o
mymodko-obj: customized-header.o mymod.o
It now works fine. So the question was the naming of module object. We need to specify different names as in this case mymodko.o and mymod.o.

Makefile variable substitution apparently not done even though := is used in declaration

I have a main kernel module with which other kernel modules communicate. I have structured the modules like this (conceptually):
main module/
|
\drivers/
|
|\driver1
|\driver2
\driver3
Since these are kernel modules, I need to compile them like this:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
However, since the Makefile of drivers can be called from previous directories, I need to do the $(shell pwd) before calling the other make (linux's make). So the Makefile now looks like this:
CURRENT_DIR := $(shell pwd)
.PHONY: all
all:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) modules
So far it is fine and it works perfectly. The problem is this: I have a file that the drivers need to include, so I have to give the include path to make. I first tried
EXTRA_CFLAGS += -I../..
and immediately understood why it doesn't work (relative path would be to /lib/module/... not to current directory). So I changed it to:
MAIN_MODULE_HOME := $(CURRENT_DIR)/../..
EXTRA_CFLAGS += -I$(MAIN_MODULE_HOME)
Oddly enough, this doesn't work! If I write
EXTRA_CFLAGS += -Ipath/I/get/from/pwd/../..
manually, it compiles! Can someone explain what I am doing wrong? Before calling make, I echoed $(CURRENT_DIR) and $(MAIN_MODULE_HOME) and the variables are meaningful.
I know that EXTRA_CFLAGS is not immediately evaluated, but since CURRENT_DIR and MAIN_MODULE_HOME are declared with := I don't understand how things are getting messed up.
(If anyone can phrase the question title better, please do!)
You should pass EXTRA_CFLAGS to make like this:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) \
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" modules
Update:
The content of driver1/Makefile is read twice: first - when you run make inside driver1 directory, second - by Kbuild system.
First, CURRENT_DIR := $(shell pwd) is evaluated to something like /home/users/.../main module/drivers/driver1. Second, Kbuild evaluates CURRENT_DIR := $(shell pwd) to something like /usr/src/linux-headers-2.6.32-33-generic/
That situation described in LDD3, ch2, p24
The trick is to write your makefile as follows:
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
#endif
It most likely because of recursive flavor of EXTRA_CFLAGS, which gets actually expanded in a sub-make, which doesn't have an access to MAIN_MODULE_HOME referred from it.
First, try to export MAIN_MODULE_HOME:
export MAIN_MODULE_HOME
I would also tried to flatten EXTRA_CFLAGS before using it (however, I'm not sure whether this is a good practice for Kbuild):
EXTRA_CFLAGS := $(EXTRA_CFLAGS)

Resources