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

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.

Related

header and c files not included in build linux kernel

For a lpc3250 board, we had to developer a Linux kernel module to control the PWM output. I've created a 'helper' module which contains methodes like PMW1_ENABLE which set the correct bit at 1.
Unfortunately I run into problems when I create multiple .c and .h files. When I put all the code in just 1 file, the solution works fine. When I split it nicely in additional .c and .h files, something weird is happening. Even just printk statements do not show up on the console.
Most weird part, during cross compiling, no errors are shown so it looks like the binary is ok but it isn't.
Does this sound familiair? Could it be an issue with my makefile?
ARCH := arm
CROSS_COMPILE := /usr/local/xtools/arm-unknown-linux-uclibcgnueabi/bin/arm-linux-
CC= $(CROSS_COMPILE)gcc
obj-m := pwmdriver.o
pwmdriver-objs := pwmhelper.o pwmdriver.o
KDIR := /home/student/felabs/sysdev/tinysystem/linux-2.6.34
WORKINGDIRFIXED := /home/student/PRT/5_AssigPWM
export
all:
$(MAKE) -C $(KDIR) M=$(WORKINGDIRFIXED) modules
clean:
$(MAKE) -C $(KDIR) M=$(WORKINGDIRFIXED) clean

Set output path when compiling a kernel module?

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!

obj-m variable in a kernel module

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.)

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.

How to keep asm output from Linux kernel module build

I'm working on a Linux kernel module for a 2.6.x kernel and I need to view the assembly output, though it's currently being done as a temporary file an deleted afterwords. I'd like to have the assembly output mixed with my C source file so I can easily trace where my problem lies. This is for an ARMv6 core and apparently objdump doesn't support this architecture. I've included my makefile below.
ETREP=/xxSourceTreexx/
GNU_BIN=$(ETREP)/arm-none-linux-gnueabi/bin
CROSS_COMPILE := $(GNU_BIN)/arm-none-linux-gnueabi-
ARCH := arm
KDIR=$(ETREP)/linux-2.6.31/
MAKE= CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) make
obj-m += xxfile1xx.o
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
Objdump does support that architecture. Your executable will be called arm-none-linux-gnueabi-objdump
Assuming gcc and the gnu assembler a more readable output than objdump can be had. Tell the assembler to retain its intermediate code using flags to gcc:
-Wa,-alh=basename.s
And to get basename to be the actual source filename you need to tell make:
-Wa,-alh=$<.s
which will leave piles of foo.c.s files laying around your source directory. The big problem here is that the way gcc works it uses temporary files between code generation and assembly. I can't find a way to make gcc save its intermediates but the assembler is happy to stash a listing for you.
Getting that argument into the Makefile CFLAGS is left as an exercise for the reader (because I kinda hate "make" and hate "gnu info" even more.
To get an assembly language listing of my Linux kernel modules, I added the assembler switches to the kernel scripts/Makefile.build.
#cmd_cc_o_c = $(CC) $(c_flags) -c -o $(#D)/.tmp_$(#F) $<
cmd_cc_o_c = $(CC) $(c_flags) -c -Wa,-alh=$<.lst -o $(#D)/.tmp_$(#F) $<
You could try the flag "-save-temps" to gcc.
It works for me in my embedded project, I haven't tried it on kernel builds.
The proper way is likely to add target dependencies in your module makefile / Kbuild file:
always-m += basename.s
(As kbuild has the proper targets to generate the .s files)
If you are lazy as I am, this could look like:
MOD_NAME := some_module_name
myunits := file1 file2 file3 ... and many more... without .c extension
obj-m := $(MOD_NAME).o
$(MOD_NAME)-y := $(addsuffix .o,$(myunits))
# Comment/uncomment to generate assembly / preprocessor output
always-m += $(addsuffix .s,$(myunits)) $(MOD_NAME).mod.s
always-m += $(addsuffix .i,$(myunits)) $(MOD_NAME).mod.i
(2 bonuses here: assembly for the generated module meta-registration file, and the preprocessor output)

Resources