Is it possible to provide an output folder when building a kernel module?
These questions are very similar to mine but the answers are non conclusive Link1, Link2 (I have tested these proposals without success).
I have the following project structure and would like to put all outputs from the compiling of the kernel module into the build folder.
Makefile
src/
-main.c
build/
This is my current Makefile:
# name of the module to be built
MODULE_NAME ?= test_module
BASE := .
# define all module sources
SRCS := \
src/main.c
# extract required object files
OBJ_SRCS := $(SRCS:.c=.o)
# define path to directories containing header files
INCLUDE_DIRS = \
-I$(src)/src
# Products from the 'make all' command should be placed in this folder
BUILD_DIR := $(BASE)/build
# ccflags to pass at compile time
ccflags-y := \
$(INCLUDE_DIRS)
# setup kbuild stuff
obj-m += $(MODULE_NAME).o
$(MODULE_NAME)-y := $(OBJ_SRCS)
$(MAKE) = make
KERNEL_DIR=/lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
I have tried to add O=$(BUILD_DIR) as (as stated in the link above without success).
$(MAKE) -C $(KERNEL_DIR) O=$(BUILD_DIR) M=$(PWD) modules
Can anyone confirm if it is possible to redirect to output(the files generated during the compilation) when compiling the kernel module or not? (A suggestion would be much appreciated)
Is the only solution to put the Makefile in the build folder and update the all paths in the Makefile?
Thanks!
Related
I have a LKM named RtmNetlinkLKM.c and compiles and run fine. The moment I update its Makefile to compile with other src files, it starts giving warning:
WARNING: modpost: missing MODULE_LICENSE()
The following MODULE_LICENSE("GPL"); is already present in kernel module file.
Previous Makefile, module compiles fine
obj-m += RtmNetlinkLKM.o
all:
make -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
make -C /lib/modules/`uname -r`/build M=$(PWD) clean
updated Makefile, module now compiles with a warning
obj-m += RtmNetlinkLKM.o
RtmNetlinkLKM-objs += rt_kern.o gluethread/glthread.o << Added two more sources
all:
make -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
make -C /lib/modules/`uname -r`/build M=$(PWD) clean
rm -f rt_kern.o
rm -f gluethread/glthread.o
When compiled using second Makefile, it gives stated warning. When I add MODULE_LICENSE("GPL") in gluethread/glthread.c , warning goes away. I don't understand, why do I need to add "GPL" license in glthread.c when it is not a module but contain functions to be used by module (It is a linked list mini-library). Why doesn't it complain with other src file rt_kern.c in a similar way. I had never made any changes in original module file RtmNetlink.c throughout this process.
Thanks to #Gautham Kantharaju in link provided by #Tsyvarev for solving my problem. While compiling multiple source files into a single module, the main reason for the warning seems to be, ".. it is not possible to have the module name and the source name to be the same."
If anyone else has the same question, I think following Makefile should solve the issue.
# give your module a different Name
obj-m += newModuleName.o
newModuleName-objs += RtmNetlinkLKM.o rt_kern.o gluethread/glthread.o
all:
make -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
make -C /lib/modules/`uname -r`/build M=$(PWD) clean
I organized the kernel modules as different sub-component, so I can easily insert/remove existing sub-module to try or integrating stuff.
The directory layout is shown as below:
foo --+-- Makefile
|
+-- main.c
|
+-- include --+-- foo1.h
| |
| +-- ... (other headers)
|
|
+-- src ------+-- foo1.c
|
+-- ... (other sources)
Here's my Makefile,
MODULE_NAME = foo
obj-m += $(MODULE_NAME).o
# [approach 1-1]
# SRCS := main.c src/foo1.c
# [approach 1-2]
SRCS := main.c $(wildcard src/*.c)
$(MODULE_NAME)-objs += main.o $(SRCS:.c=.o)
all:
# [2] echo to check if foo-objs values changes
echo $($(MODULE_NAME)-objs)
KCFLAGS="-I$(PWD)/include" \
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
I got warning shown as below when I tried to replace approach [1-1] with [1-2] in my Makefile above.
WARNING: "InitFoo1" [.../foo/foo.ko] undefined!
WARNING: "CleanuptFoo1" [.../foo/foo.ko] undefined!
From the console output, I don't see the src/foo1.c got compiled as if I am using approach [1-1] in Makefile.
# [2] echo to check if foo-objs values changes
echo main.o main.o src/foo1.o
main.o main.o src/foo1.o
KCFLAGS="-I/home/cyng93/experiment/issues/so_kbuild_wildcard/include" \
make -C /lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build M=/home/cyng93/experiment/issues/so_kbuild_wildcard modules
make[1]: Entering directory '/linux'
CC [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/main.o
LD [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "InitFoo1" [/home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko] undefined!
WARNING: "CleanupFoo1" [/home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko] undefined!
CC /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.mod.o
LD [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko
make[1]: Leaving directory '/linux'
I try to echo foo-objs(check [2] in Makefile) and found out that the value are the same for both approach [1-1] & [1-2].
Does anyone on SO has came up with similar issues can help to shade some light on ?
(I prefer [1-2] because it can save my effort from updating the Makefile when new sub-component is added)
Below I also attached the source code of main.c, foo1.c & foo1.h.
You can also check the github repo for this issue for easier access to those code.
main.c
#include <linux/module.h>
#include "foo1.h"
static int myinit(void)
{
printk("Module inserted!\n");
InitFoo1();
return 0;
}
static void myexit(void)
{
CleanupFoo1();
printk("Module removed!\n");
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL v2");
Here, foo1 is a sub-component, where simply print out some stuff during its intialization and cleanup:
./include/foo1.h
#ifndef FOO1_H
#define FOO1_H
int InitFoo1(void);
void CleanupFoo1(void);
#endif
./src/foo1.c
#include <linux/module.h>
#include "foo1.h"
int InitFoo1(void)
{
printk("Init Foo1\n");
return 0;
}
void CleanupTest(void)
{
printk("Cleanup Foo1\n");
}
update_2018/01/15
According to Tsyvarev answer below, one can correct the Makefile by modifying Makefile as below:
MODULE_NAME = foo
obj-m += $(MODULE_NAME).o
# [approach 1-1]
# SRCS := main.c src/foo1.c
# [approach 1-2 (not working)]
# SRCS := main.c $(wildcard src/*.c)
# [approach 1-2 (working)]
MISC := $($(src)/wildcard src/*.c)
SRCS := main.c $(MISC:$(src)%/=%)
$(MODULE_NAME)-objs += main.o $(SRCS:.c=.o)
all:
# [2] echo to check if foo-objs values changes
echo $($(MODULE_NAME)-objs)
KCFLAGS="-I$(PWD)/include" \
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
When build the kernel module your Makefile is processed twice:
When you type make from your module's directory.
Inside Kbuild process, because you pass M=$(PWD) option to it.
First time the Makefile is processed with current directory equal to the module's directory. So wildcard works as expected, which is confirmed by printing from all receipt.
But the second time the Makefile is processed with current directory equal to kernel's build directory (/lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build in your case). In that mode
$(wildcard src/*.c)
attempts to find a file in kernel's build directory, which obviously fails.
At the time of second processing one may refer to module's build directory with $(src).
Such way one may use wildcard() for collect module's sources. But note, that Kernel build system expects path to source file (more precisely, to object file) to be relative to module's build directory. So, one need to strip $(src) component of every file obtained with wildcard().
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.
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.
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)