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)
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).
kbuild/modules.txt, and started to write my
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
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
make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) modules
mkdir -p "[email protected]"
touch "[email protected]"
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.
src := $(SRCDIR)
src := $(obj)
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
# Rules to copy the sources
FOO_COPIED_SOURCES = $(patsubst %.o,$(src)/%.c,$(FOO_MODULE_OBJS))
$(Q)mkdir -p $(@D)
cp -f $< [email protected]
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:
| |__ complex_main.c
| |__ hal
| |__ hardwareif.c
| |__ include
| |__ hardwareif.h
To build the module complex.ko, we then need the following
--> 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.