简体   繁体   中英

How to chain KBuild Makefiles properly to build subfolders inside kernel module

I have a kernel module (often compiled using CONFIG_MYMODULE=m) which is set-up like the following:

mymodule/Makefile
../foo/Makefile
../foo/component1/Makefile
../foo/component2/Makefile

Currently what's being used is:

mymodule/Makefile:

mymodule-y += mod1file.o mod2file.o mod3file.o #etc
include ../foo/Makefile
mymodule-y += $(FOO_FILES)
obj-$(CONFIG_MYMODULE) += mymodule.o

../foo/Makefile:

include component1/Makefile
include component2/Makefile

and inside each component folder I have:

../foo/component1/Makefile

FOO_FILES += foo1file.o foo2file.o foo3file.o #etc

This definitely doesn't appear to be the proper way of going about this, as everything is included directly into the mymodule/Makefile and thus can't set folder-specific gcc flags.

What is the proper way of organizing this while still building everything into a single kernel module ? I've read the kbuild/modules.txt documentation, but I haven't seen anything which relates directly, and I can't quite figure out how to go about this or if it's indeed possible.

Thanks


I've tried the following, but I get the following error:

"ld: cannot find foo: File format not recognized"

mymodule/Makefile:

mymodule-y += mod1file.o mod2file.o mod3file.o #etc
mymodule-y += ../foo/
obj-$(CONFIG_MYMODULE) += mymodule.o

../foo/Makefile

ccflags-y := -I$(src)/component1/ -I$(src)/component2/
foo-y := foo1file.o foo2file.o foo3file.o
foo-y += component1
foo-y += component2

../foo/component1/Makefile

component1-y := component1file.o component1file.o

../foo/component2/Makefile

component2-y := component2file.o component2file.o

If I change this to instead use obj-y += ../foo rather than mymodule-y += ../foo it at least enters the folder, but doesn't seem to attempt to complile, and I want this to be all a part of a single kernel module.

This doesn't seem too difficult.

mymodule/Makefile:

...
include ../foo/Makefile
...
# whatever rules use the folder-specific flags:
foo:
    gcc blah blah $(FOLDERFLAGS) blah

../foo/component1/Makefile:

FOLDER_FILES := foo1file.o foo2file.o foo3file.o #etc
$(FOLDER_FILES): FOLDER_FLAGS=folder_1_flag
FOO_FILES += FOLDER_FILES

../foo/component2/Makefile:

FOLDER_FILES := foo20file.o foo21file.o foo22file.o #etc
$(FOLDER_FILES): FOLDER_FLAGS=folder_2_flag
FOO_FILES += FOLDER_FILES

Is that sufficient for your purposes?

You can get parent directories working using subdir- and extra-y but is just an overhead and still ccflags per directory wouldn't work. Perhaps the proper way would be to have components as sub-modules, with dependency to mymodule.

I would keep the module build in the top directory mymodule/Makefile , is easy to build multiple modules from one directory but I found nothing about one module from multiple objects in subdirectories (maybe a keep a clean design policy, or just was easier this way).

obj-m define the list of kernel modules to build (only one in the example below: hello.ko , is named hello.o but will output hello.ko )

hello-objs define the list of compiled objects to link to get hello.ko , by using the same name : hello .

Being a Makefile is easy to link objects conditionally (see CONFIG_HELLO_COMPONENT1 )

Eventually if there are many objects per component and we want to keep the top Makefile clean we can still use include but just to conditionally add objects to hello-objs and flags to ccflags-y (or whatever variable needed, just not obj-* ).

CFLAGS_$*.o (see below) can be used to set per object cflags, but it doesn't honour the path, so objects with the same name in different directories will have the same flags.

mymodule/Makefile :

ifeq ($(CONFIG_HELLO_COMPONENT1), y)
 ccflags-y += -I$(src)/foo/component1 -DCONFIG_HELLO_COMPONENT1
endif
ccflags-y += -I$(src)/foo/component2

obj-m += hello.o

CFLAGS_component2.o += -DTEST_CFLAGS

hello-objs = hello-1.o
ifeq ($(CONFIG_HELLO_COMPONENT1), y)
 hello-objs += foo/component1/component1.o
endif
hello-objs += foo/component2/component2.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

For completeness below all the files, should build and work, with make or make CONFIG_HELLO_COMPONENT1=y .

mymodule/hello-1.c :

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#ifdef CONFIG_HELLO_COMPONENT1
#include <component1.h>
#endif
#include <component2.h>
static int __init init_hello(void) {
#ifdef CONFIG_HELLO_COMPONENT1
    component1();
#endif
    component2();
    printk(KERN_INFO "Hello world 1.\n");
    return 0;
}
static void __exit cleanup_hello(void) {
    printk(KERN_INFO "Goodbye world 1.\n");
}
module_init(init_hello);
module_exit(cleanup_hello);

mymodule/foo/component2/component2.h :

#ifndef COMPONENT2_H
#define COMPONENT2_H
void component2(void);
#endif

mymodule/foo/component2/component2.c :

#include <linux/kernel.h>
void component2(void) {
    printk(KERN_INFO "component2\n");
}

mymodule/foo/component1/component1.h :

#ifndef COMPONENT1_H
#define COMPONENT1_H
void component1(void);
#endif

mymodule/foo/component1/component1.c :

#include <linux/kernel.h>
void component1(void) {
    printk(KERN_INFO "component1\n");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM