3

is there a way to set a output-directory for making kernel-modules inside my makefile?

I want to keep my source-direcory clean from the build-files.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Tom
  • 33
  • 1
  • 3
  • Possible duplicate of [Building an out-of-tree Linux kernel module in a separate object directory](https://stackoverflow.com/questions/5718899/building-an-out-of-tree-linux-kernel-module-in-a-separate-object-directory) – Ciro Santilli OurBigBook.com Sep 30 '18 at 17:24

3 Answers3

3

KBUILD_OUTPUT and O= did not work for me and were failing to find the kernel headers when building externally. My solution is to symlink the source files into the bin directory, and dynamically generate a new MakeFile in the bin directory. This allows all build files to be cleaned up easily since the dynamic Makefile can always just be recreated.

INCLUDE=include
SOURCE=src
TARGET=mymodule
OUTPUT=bin
EXPORT=package

SOURCES=$(wildcard $(SOURCE)/*.c)

# Depends on bin/include bin/*.c and bin/Makefile
all: $(OUTPUT)/$(INCLUDE) $(subst $(SOURCE),$(OUTPUT),$(SOURCES)) $(OUTPUT)/Makefile
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD)/$(OUTPUT) modules

# Create a symlink from src to bin
$(OUTPUT)/%: $(SOURCE)/%
    ln -s ../$< $@

# Generate a Makefile with the needed obj-m and mymodule-objs set
$(OUTPUT)/Makefile:
    echo "obj-m += $(TARGET).o\n$(TARGET)-objs := $(subst $(TARGET).o,, $(subst .c,.o,$(subst $(SOURCE)/,,$(SOURCES))))" > $@

clean:
    rm -rf $(OUTPUT)
    mkdir $(OUTPUT)
TheBat
  • 1,006
  • 7
  • 25
  • 2
    that's a pretty sad testament to linux kernel development. Of the thousands of itches that comprise the linux kernel, is there not one that itches for a clean source directory? – stu Sep 28 '19 at 20:29
0

If you are building inside the kernel tree you can use the O variable:

make O=/path/to/mydir

If you are compiling outside the kernel tree (module, or any other kind of program) you need to change your Makefile to output in a different directory. Here a little example of a Makefile rule which output in the MY_DIR directory:

$(MY_DIR)/test: test.c
    gcc -o $@ $<

and then write:

$ make MY_DIR=/path/to/build/directory
Federico
  • 3,782
  • 32
  • 46
  • 1
    Unfortunately, it does not seem to help when building external (out of tree) kernel modules. On my system (OpenSUSE 12.1 x86), I have a directory (`~/sample`) with the sources of a simple kernel module as well as with Kbuild and Makefile for it. I made it read only and created a build directory, `~/sample_build`. From the latter, I have executed `make -C ~/sample O=$(pwd)`. The build failed because the build system still tried to create `~/sample/.tmp_versions` directory as well as `.tmp*.o` files in `~/sample`. Perhaps, something else is needed to make it work? – Eugene Sep 04 '12 at 06:10
  • On the other hand, `make ... O=` seems to work fine for the in-tree kernel modules. – Eugene Sep 04 '12 at 06:15
  • 3
    Thanks for your answer, but your solution doesn't work with kernel modules. Because in your kernel-module-makefile you have to call make with the makefile in /lib/modules//build. So you don't have any gcc-calls. So far my current solution is to move all build-files in the bin-dir, after compiling. Regards Tom – Tom Sep 05 '12 at 06:00
  • 2
    @Tom, in our project we have resorted to copying the sources of the kernel modules to the build tree and then building them there in a usual way. That works but perhaps there is a better way, I don't know yet. – Eugene Sep 05 '12 at 06:43
  • @Eugene I also faced the problem of building module out-of-source and the `O` flag does not do the job. Is there a better solution with kernels v5.x and later? – St.Antario Dec 14 '19 at 14:39
0

The same here, but I used a workaround that worked for me:

  1. Create a sub-directory with/for every arch name (e.g. "debug_64").
  2. Under "debug_64": create symbolic link of all .c and .h files. Keeping the same structure.
  3. Copy the makefile to "debug_64" and set the right flags for 64 Debug build, e.g.
ccflags-y := -DCRONO_DEBUG_ENABLED 
ccflags-y += -I$(src)/../../../lib/include 
KBUILD_AFLAGS += -march=x86_64 
  1. Remember to set the relative directories paths to one level down, e.g. ../inc will be ../../inc.
  2. Repeat the same for every arch/profile. Now we have one source code, different folders, and different make files. By the way, creating profiles inside make files for kernel module build is not an easy job, so, I preferred to create a copy of makefile for every arch.
Bassem Ramzy
  • 326
  • 3
  • 10