我有一个简单内核模块的以下项目结构,我希望能够通过从Makefile中提供的源目录中提取源文件来构建它。
Makefile
src/
main.c
sub_src/
sub_src.c
sub_src.h
我会尽快描述我的问题,但我会先提供代码。
main.c:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include "sub_src/sub_src.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Unknown");
MODULE_DESCRIPTION("A Simple Hello World module");
static int __init hello_init(void)
{
printk(KERN_INFO "Hello world!\n");
sub_src_printk("sub_src.c\n");
return 0;
}
static void __exit hello_cleanup(void)
{
printk(KERN_INFO "Cleaning up module.\n");
}
module_init(hello_init);
module_exit(hello_cleanup);
sub_src.h:
#ifndef __SUB_SRC_H___
#define __SUB_SRC_H___
#include <linux/kernel.h> // included for KERN_INFO
void sub_src_printk( const char* );
#endif /* __SUB_SRC_H___ */
sub_src.c:
#include "sub_src.h"
void sub_src_printk( const char* msg )
{
printk(KERN_INFO "%s", msg);
}
Makefile:
MODULE_NAME ?= test_module
TEST ?= 0
INCLUDE_DIRS = -I$(src)/src/sub_src
ccflags-y := $(INCLUDE_DIRS)
ifeq ($(TEST), 1)
SRC_DIRS := \
src \
src/sub_src
SRCS := $(foreach src_dir,$(SRC_DIRS),$(wildcard $(src_dir)/*.c))
else
SRCS := \
src/main.c \
src/sub_src/sub_src.c
endif
#extract required object files
OBJ_SRCS := $(SRCS:.c=.o)
#setup kbuild
obj-m += $(MODULE_NAME).o
$(MODULE_NAME)-y := $(OBJ_SRCS)
$(MAKE) = make
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
all:
@echo ""
@echo "------- Building the LKM ($(MODULE_NAME).ko) -------"
@echo "INCLUDE_DIRS = $(INCLUDE_DIRS)"
@echo "SRCS = $(SRCS)"
@echo "OBJS_SRCS = $(OBJ_SRCS)"
@echo "ccflags-y = $(ccflags-y)"
@echo "obj-m = $(obj-m)"
@echo "test_module-y = $(test_module-y)"
@echo "-----------------------------------------------------"
@echo ""
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
我的想法是,我应该能够通过调用make as来提供Makefile中的源目录来构建这个模块:
make all TEST=1
但我可以选择(现在)通过调用make来提供源文件的路径:
make all TEST=0
理想情况下,这两个调用应提供相同的结果,即准备插入的功能内核模块(通过sudo insmod ...)。然而情况并非如此。 (使所有TEST = 0按预期工作,同时使所有TEST = 1不起作用)
make all TEST = 0给出以下输出:(在此命令之前调用make clean)
------- Building the LKM (test_module.ko) -------
INCLUDE_DIRS = -I/src/sub_src
SRCS = src/main.c src/sub_src/sub_src.c
OBJS_SRCS = src/main.o src/sub_src/sub_src.o
ccflags-y = -I/src/sub_src
obj-m = test_module.o
test_module-y = src/main.o src/sub_src/sub_src.o
-----------------------------------------------------
make -C /lib/modules/3.19.0-59-generic/build M=/home/henrik/Desktop/test_lkm_dev/new_test modules
make[1]: Entering directory `/usr/src/linux-headers-3.19.0-59-generic'
CC [M] /home/henrik/Desktop/test_lkm_dev/new_test/src/main.o
CC [M] /home/henrik/Desktop/test_lkm_dev/new_test/src/sub_src/sub_src.o
LD [M] /home/henrik/Desktop/test_lkm_dev/new_test/test_module.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/henrik/Desktop/test_lkm_dev/new_test/test_module.mod.o
LD [M] /home/henrik/Desktop/test_lkm_dev/new_test/test_module.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.19.0-59-generic'
make all TEST = 1给出以下输出:(在此命令之前调用make clean)
------- Building the LKM (test_module.ko) -------
INCLUDE_DIRS = -I/src/sub_src
SRCS = src/main.c src/sub_src/sub_src.c
OBJS_SRCS = src/main.o src/sub_src/sub_src.o
ccflags-y = -I/src/sub_src
obj-m = test_module.o
test_module-y = src/main.o src/sub_src/sub_src.o
-----------------------------------------------------
make -C /lib/modules/3.19.0-59-generic/build M=/home/henrik/Desktop/test_lkm_dev/new_test modules
make[1]: Entering directory `/usr/src/linux-headers-3.19.0-59-generic'
make[2]: *** No rule to make target `/home/henrik/Desktop/test_lkm_dev/new_test/test_module.c', needed by `/home/henrik/Desktop/test_lkm_dev/new_test/test_module.o'. Stop.
make[1]: *** [_module_/home/henrik/Desktop/test_lkm_dev/new_test] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.19.0-59-generic'
make: *** [all] Error 2
调试信息显示(据我所知)Makefile中的变量包含不同方法的相同值。
但是第二种选择(TEST = 1)给人的印象是应该有一个名为 test_module.c 的源文件,但事实并非如此。
有人/任何人都知道为什么会发生这种情况以及如何解决这个问题? (过去两个小时我一直在拔头发..)
解决方案(Makefile):
MODULE_NAME ?= test_module
TEST ?= 0
INCLUDE_DIRS = -I$(src)/src/sub_src
ccflags-y := $(INCLUDE_DIRS)
ifeq ($(TEST), 1)
# Paths to source directories
SRC_DIRS := \
src \
src/sub_src
SRCS := $(foreach src_dir,$(SRC_DIRS),$(wildcard $(src)/$(src_dir)/*.c))
SRCS := $(SRCS:$(src)/%=%)
else
SRCS := \
src/main.c \
src/sub_src/sub_src.c
endif
# extract required object files
OBJ_SRCS := $(SRCS:.c=.o)
# setup kbuild
obj-m := $(MODULE_NAME).o
$(MODULE_NAME)-y := $(OBJ_SRCS)
$(MAKE) = make
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
all:
@echo ""
@echo "------- Building the LKM ($(MODULE_NAME).ko) -------"
ifeq ($(TEST), 1)
@echo "Compiling with TEST = 1"
else
@echo "Compiling with TEST = 0"
endif
@echo ""
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
非常感谢! 亨利克