make编译内核代码失败

内核编译和嵌入式产品的设计与开发
回复
maple_169324
帖子: 8
注册时间: 2018-12-29 14:13
系统: ubuntu
送出感谢: 3 次
接收感谢: 0

make编译内核代码失败

#1

帖子 maple_169324 » 2019-09-23 22:51

文件结构如下:
.
├── calc
│   ├── add_sub.c
│   └── Makefile
├── include
│   └── add_sub.h
├── Makefile
└── test.c

add_sub.c中定义了add_integer 和sub_integer两个函数供test.c中调用,对应的add_sub.h在include中定义
#include <linux/init.h>
#include <linux/module.h>
#include <add_sub.h>

long add_integer(int a,int b)
{
return a+b;
}

long sub_integer(int a, int b)
{
return a-b;
}

EXPORT_SYMBOL(add_integer);
EXPORT_SYMBOL(sub_integer);

calc中的Makefile如下:

obj-m:=add_sub.o
CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
PRINT_INC=$(dir $(CURRENT_PATH))include
EXTRA_CFLAGS += -I$(PRINT_INC)

all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules

clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

make的时候提示找不到add_sub.h文件。
make -I/home/wuqi/vs_code_prj/linux_kernel/include -C /usr/src/linux-headers-4.15.0-55-generic M=/home/wuqi/vs_code_prj/linux_kernel/calc modules
make[1]: 进入目录“/usr/src/linux-headers-4.15.0-55-generic”
CC [M] /home/wuqi/vs_code_prj/linux_kernel/calc/add_sub.o
/home/wuqi/vs_code_prj/linux_kernel/calc/add_sub.c:3:10: fatal error: add_sub.h: 没有那个文件或目录
#include <add_sub.h>
^~~~~~~~~~~
compilation terminated.

应该是搜索头文件的路径没生效,应该如何修改呢
头像
astolia
论坛版主
帖子: 4033
注册时间: 2008-09-18 13:11
送出感谢: 1 次
接收感谢: 666 次

Re: make编译内核代码失败

#2

帖子 astolia » 2019-09-24 0:21

根本原因是makefile被读了两次,也就是在进入目录“/usr/src/linux-headers-4.15.0-55-generic”后,kbuild系统再次读取了makefile一遍,这时的EXTRA_CFLAGS变成了/usr/src/linux-headers-4.15.0-55-generic/include这样。详见 https://static.lwn.net/images/pdf/LDD3/ch02.pdf 中的24页说明。

可以用一个技巧把EXTRA_CFLAGS直接传给make,也就是

代码: 全选

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) EXTRA_CFLAGS=$(EXTRA_CFLAGS) modules
另外不知道你给make加个-I干吗?make的-I选项的意义是

代码: 全选

$ make --help | grep -A 1 -- '-I'
  -I DIRECTORY, --include-dir=DIRECTORY
                              Search DIRECTORY for included makefiles.
跟头文件毫无关系

最后就是你的目录结构,非要把头文件和代码分开放的话,参考一下官方文档里的做法
https://elixir.bootlin.com/linux/v5.3.1 ... s.rst#L369
这些用户感谢了作者 astolia 于这个帖子:
maple_169324 (2019-09-24 17:46)
评价: 3.7%
maple_169324
帖子: 8
注册时间: 2018-12-29 14:13
系统: ubuntu
送出感谢: 3 次
接收感谢: 0

Re: make编译内核代码失败

#3

帖子 maple_169324 » 2019-09-24 17:50

astolia 写了:
2019-09-24 0:21
根本原因是makefile被读了两次,也就是在进入目录“/usr/src/linux-headers-4.15.0-55-generic”后,kbuild系统再次读取了makefile一遍,这时的EXTRA_CFLAGS变成了/usr/src/linux-headers-4.15.0-55-generic/include这样。详见 https://static.lwn.net/images/pdf/LDD3/ch02.pdf 中的24页说明。

可以用一个技巧把EXTRA_CFLAGS直接传给make,也就是

代码: 全选

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) EXTRA_CFLAGS=$(EXTRA_CFLAGS) modules
另外不知道你给make加个-I干吗?make的-I选项的意义是

代码: 全选

$ make --help | grep -A 1 -- '-I'
  -I DIRECTORY, --include-dir=DIRECTORY
                              Search DIRECTORY for included makefiles.
跟头文件毫无关系

最后就是你的目录结构,非要把头文件和代码分开放的话,参考一下官方文档里的做法
https://elixir.bootlin.com/linux/v5.3.1 ... s.rst#L369

那通过KERNELRELEASE来控制是否是初次读makefile, 在第二次读的时候对EXTRA_CFLAGS进行赋值。
ifeq ($(KERNELRELEASE),)
CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
else
CURRENT_PATH:=$(shell pwd)
SYMBOL_INC=$(CURRENT_PATH)/include
EXTRA_CFLAGS+=$(SYMBOL_INC)
KBUILD_EXTRA_SYMBOLS=$(CURRENT_PATH)/calc/Module.symvers
obj-m:=test.o
endif

得到的结果仍然是找不到头文件呢
make -C /usr/src/linux-headers-4.15.0-55-generic M=/home/wuqi/vs_code_prj/linux_kernel modules
make[1]: 进入目录“/usr/src/linux-headers-4.15.0-55-generic”
CC [M] /home/wuqi/vs_code_prj/linux_kernel/test.o
/home/wuqi/vs_code_prj/linux_kernel/test.c:6:10: fatal error: add_sub.h: 没有那个文件或目录
#include "add_sub.h"
^~~~~~~~~~~
compilation terminated.
scripts/Makefile.build:337: recipe for target '/home/wuqi/vs_code_prj/linux_kernel/test.o' failed
头像
astolia
论坛版主
帖子: 4033
注册时间: 2008-09-18 13:11
送出感谢: 1 次
接收感谢: 666 次

Re: make编译内核代码失败

#4

帖子 astolia » 2019-09-24 21:38

你这样改有区别吗?kbuild系统解析makefile的时候走else部分碰到CURRENT_PATH:=$(shell pwd),一样把CURRENT_PATH设成了/usr/src/linux-headers-4.15.0-55-generic,后面EXTRA_CFLAGS的路径还是错的。而且你这个EXTRA_CFLAGS还没有写-I
头像
astolia
论坛版主
帖子: 4033
注册时间: 2008-09-18 13:11
送出感谢: 1 次
接收感谢: 666 次

Re: make编译内核代码失败

#5

帖子 astolia » 2019-09-24 22:28

这样吧,你这样干

代码: 全选

echo >/tmp/cc <<END
#!/bin/sh
env|sort>/tmp/env
/usr/bin/cc "$@"
END
chmod +x /tmp/cc
新建一个可执行脚本,然后用make CC=/tmp/cc来编译,就能在/tmp/env里看到kbuild在编译时包括EXTRA_CFLAGS在内的所有环境变量到底是什么了
回复

回到 “内核及嵌入式开发”