c - Linux 内核模块 Makefile 不能包含相对路径

标签 c linux makefile linux-kernel gnu-make

我正在尝试构建 Linux 内核模块:

KBUILD_EXTRA_SYMBOLS := ../../Module.symvers
KBUILD_EXTRA_SYMBOLS := ../../dir0/Module.symvers
KDIR = ../../../../kernel/linux-4.9

INCLUDES = \
     -I../dir1/dir2/dir3  \
     -I../dir1/dir2 \
     -I../dir1

EXTRA_CFLAGS += $(INCLUDES)

PWD = $(shell pwd)

TARGET = some_module

obj-m := $(TARGET).o

all: default clean
default:
     make $(INCLUDES) -C $(KDIR) M=$(PWD) modules
clean:
     @rm -f *.o .*.cmd .*.flags *.mod.c *.order
     @rm -f .*.*.cmd *.symvers *~ *.*~ TODO.*
     @rm -fR .tmp*
     @rm -rf .tmp_versions
disclean: clean
     @rm -f *.ko

但它无法在相对路径中定位文件,例如喜欢 fatal error: some_header.h: No such file or directory .当我使用绝对路径时效果很好,但我需要从这个项目的当前目录进行相对寻址。怎么了?
很抱歉,如果很明显。

最佳答案

Linux 内核使用 Kbuild 来制作模块。该框架不同于一般的 makefile 约定,因此虽然它们都由 GNU make 解释,但需要注意差异。 Documentation for Makefiles using Kbuild can be found heredocumentation for building external kernel modules can be found here .

下面引用了文档中与您的问题相关的一些要点。

来自 makefiles.txt :

--- 3.10 Special Rules

Special rules are used when the kbuild infrastructure does not provide the required support. A typical example is header files generated during the build process. Another example are the architecture-specific Makefiles which need special rules to prepare boot images etc. Special rules are written as normal Make rules. Kbuild is not executing in the directory where the Makefile is located, so all special rules shall provide a relative path to prerequisite files and target files. Two variables are used when defining special rules:

~$(src)~

$(src) is a relative path which points to the directory where the Makefile is located. Always use $(src) when referring to files located in the src tree.

~$(obj)~

$(obj) is a relative path which points to the directory where the target is saved. Always use $(obj) when referring to generated files.



来自 modules.txt :

--- 4.3 Several Subdirectories

kbuild can handle files that are spread over several directories. Consider the following example:

  .   
  |__ src     
  |   |__ complex_main.c  
  |   |__ hal     
  |       |__ hardwareif.c
  |       |__ include     
  |           |__ hardwareif.h    
  |__ include
      |__ complex.h

To build the module complex.ko, we then need the following kbuild file:

   --> filename: Kbuild
   obj-m := complex.o
   complex-y := src/complex_main.o
   complex-y += src/hal/hardwareif.o

   ccflags-y := -I$(src)/include
   ccflags-y += -I$(src)/src/hal/include

As you can see, kbuild knows how to handle object files located in other directories. The trick is to specify the directory relative to the kbuild file's location. That being said, this is NOT recommended practice.

For the header files, kbuild must be explicitly told where to look. When kbuild executes, the current directory is always the root of the kernel tree (the argument to "-C") and therefore an absolute path is needed. $(src) provides the absolute path by pointing to the directory where the currently executing kbuild file is located.



因此,您的 Makefile 应如下所示:
KBUILD_EXTRA_SYMBOLS := $(src)/../../Module.symvers
KBUILD_EXTRA_SYMBOLS := $(src)/../../dir0/Module.symvers
KDIR = $(src)/../../../../kernel/linux-4.9

INCLUDES = \
     -I$(src)/../dir1/dir2/dir3  \
     -I$(src)/../dir1/dir2 \
     -I$(src)/../dir1

EXTRA_CFLAGS += $(INCLUDES)

PWD = $(shell pwd)

TARGET = some_module

obj-m := $(TARGET).o

all: default clean
default:
     make $(INCLUDES) -C $(KDIR) M=$(PWD) modules
clean:
     @rm -f *.o .*.cmd .*.flags *.mod.c *.order
     @rm -f .*.*.cmd *.symvers *~ *.*~ TODO.*
     @rm -fR .tmp*
     @rm -rf .tmp_versions
disclean: clean
     @rm -f *.ko

关于c - Linux 内核模块 Makefile 不能包含相对路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62196308/

相关文章:

python - 阅读不包括主题 css 的文档

c++ - 如何在编译期间避免标准包含文件

c - 函数从 C 中的字符串创建数组,无需 strtok

python - 确定 TCP listen() 队列中当前积压的连接数

c - fopen() 或 open() 使用什么字符编码?

makefile - 编译器错误 gcc-8 : error: unrecognized command line option '-no-pie'

c - 从 C main() 程序返回字符串的机制

c - C 中的越界内存位置

linux - 客户端证书 clientcert.pem 尚未激活

C 如何管理多个源文件之间的#include 关系并创建正确的 makefile