Tom
Tom

Reputation: 73

Build kernel module into a specific directory

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.

Upvotes: 7

Views: 11225

Answers (5)

roagen
roagen

Reputation: 1

Another workaround is to copy source directory into build directory and point there.

BUILD_DIR=$(CURDIR)/build

obj-m += src/main.o

KPATH := /usr/src/kernel-headers-`uname -r`

ccflags-y := -std=gnu11

.PHONY: all clean

all: $(BUILD_DIR)
    rsync -a --exclude=$(BUILD_DIR) ./ $(BUILD_DIR)
    cd $(BUILD_DIR)
    make -C $(KPATH) M=$(BUILD_DIR) modules
    cd -

$(BUILD_DIR):
    mkdir -p $(BUILD_DIR)

clean:
    rm -Rf $(BUILD_DIR)

Upvotes: 0

grybouilli
grybouilli

Reputation: 410

I found the following answer which seems much cleaner than all the symlink versions out there. Thought i'd post it here.

You basically add the following variables to your makefile :

BUILD_DIR := $(PWD)/build #replace with desired target directory

BUILD_DIR_MAKEFILE := $(BUILD_DIR)/Makefile

Then your make rule should look like :

all: $(BUILD_DIR_MAKEFILE)
    make -C /lib/modules/$(shell uname -r)/build M=$(BUILD_DIR) src=$(PWD) modules 

and you should add the following two rules:

$(BUILD_DIR):
    mkdir -p "$@"

$(BUILD_DIR_MAKEFILE): $(BUILD_DIR)
    touch "$@"

Complete example makefile :

obj-m += ppmgenerator.o

ppmgenerator-y := ppm_generator.o channel.o

ccflags-y := -std=gnu11

BUILD_DIR := $(PWD)/build
BUILD_DIR_MAKEFILE := $(BUILD_DIR)/Makefile

all: $(BUILD_DIR_MAKEFILE)
    make -C /lib/modules/$(shell uname -r)/build M=$(BUILD_DIR) src=$(PWD) modules 

$(BUILD_DIR):
    mkdir -p "$@"

$(BUILD_DIR_MAKEFILE): $(BUILD_DIR)
    touch "$@"

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(BUILD_DIR) src=$(PWD) clean

Upvotes: 2

Bassem Ramzy
Bassem Ramzy

Reputation: 396

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.

Upvotes: 0

TheBat
TheBat

Reputation: 1044

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)

Upvotes: 5

Federico
Federico

Reputation: 3892

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

Upvotes: 0

Related Questions