4

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.

Jordan
  • 9,014
  • 8
  • 37
  • 47
  • You can add folders to the list of objects. Check any *folder/Makefile* in the sources. – 0andriy Oct 12 '16 at 21:32
  • @AndyShevchenko: I've tried looking at a bunch of them already, but they don't appear to handle multiple chaining of Makefiles into the same kernel module. Isn't that what I"m attempting to do at the bottom with foo-y += ../foo/? If I do something like "obj-y += ../foo/" work with compiling into the mymodule kernel module? I'm still a bit confused. Do you have a good example I can look at? Thanks! – Jordan Oct 13 '16 at 16:25
  • `obj-[ym]` is a global space of separate units. You need to use module namespace for that. – 0andriy Oct 13 '16 at 20:11
  • From my example, would that me mymodule-y += ../foo/ or would it be something like foo-y += ../foo ? And then what would I do inside my foo/Makefile? Would that be mymodule-y += component1 or would I use a separate module namespace? – Jordan Oct 13 '16 at 20:31

2 Answers2

1

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?

Beta
  • 96,650
  • 16
  • 149
  • 150
  • Somewhat, but it doesn't make use of the kbuild objects at all. I don't really want to call gcc directly, and I don't have any other targets in mymodule/Makefile. – Jordan Oct 17 '16 at 15:37
  • @Jordan: I'm not familiar with kbuild; how do you pass gcc flags to it? – Beta Oct 17 '16 at 15:41
  • It seems you don't do it directly: http://lxr.free-electrons.com/source/Documentation/kbuild/makefiles.txt – Jordan Oct 17 '16 at 15:42
  • Section 3.2 should explain some of it. I don't quite understand it fully myself. – Jordan Oct 17 '16 at 16:01
  • @Jordan: I'm not going to sift through that huge document in the hopes of guessing correctly how to use a tool I don't have to experiment with. If your real question is how to use kbuild, I can't help you. – Beta Oct 17 '16 at 16:05
  • Yep, that's fair thanks. My question was more directed specifically at how to do this with kbuild, I wouldn't ask anyone who isn't familiar with it. Cheers – Jordan Oct 17 '16 at 17:04
0

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");
}
Alex
  • 3,264
  • 1
  • 25
  • 40