我们有时会遇到内核编译时警告(warning)被视为错误(error)等问题
在内核源码中,移植外部驱动模块,出现报错:error: unused variable ‘xxx’ [-Werror=unused-variable]
...
error: defined but not used [-Werror=unused-variable]
...
error: 'ret' may be used uninitialized in this function [-Werror=maybe-uninitialized]
...
但是上述这些信息,在另一个内核中编译,只是报警告:
warning: unused variable 'core_id' [-Wunused-variable]
...
warning: defined but not used [-Werror=unused-variable]
...
warning: 'ret' may be used uninitialized in this function [-Werror=maybe-uninitialized]
...
为什么有的内核编译时警告被视为错误?
出现上述现象的原因和GCC编译选项有关:
选 项 | 含 义 |
---|---|
-pedantic | 允许发出ANSI C标准所列的全部警告信息 |
-pedantic-error | 允许发出ANSI C标准所列的全部错误信息 |
-w | 关闭所有告警 |
-Wall | 允许发出Gcc提供的所有有用的报警信息 |
-werror | 把所有的告警信息转化为错误信息,并在告警发生时终止编译过程 |
其中的-Werror选项,会把所有的告警信息转化为错误信息,并在告警发生时终止编译过程。
做一个简单的试验,验证-Werror选项的作用
参考链接中的内容,写一个最简单的KO模块:
【开发日常】【module】Linux写一个简单的ko模块
然后模拟做一个简单的warning(未使用的变量):
static int hello_init(void)
{
int a=1;
printk("Hello, World !\n");
return 0;
}
执行Makefile编译KO,提示告警:
zhugeyifan@83-28:~/test/ko_module_demo$ make
make -C /lib/modules/4.15.0-126-generic/build M=/home1/zhugeyifan/test/ko_module_demo modules
make[1]: Entering directory '/usr/src/linux-headers-4.15.0-126-generic'
CC [M] /home1/zhugeyifan/test/ko_module_demo/hello_world.o
/home1/zhugeyifan/test/ko_module_demo/hello_world.c: In function ‘hello_init’:
/home1/zhugeyifan/test/ko_module_demo/hello_world.c:6:9: warning: unused variable ‘a’ [-Wunused-variable]
int a=1;
^
Building modules, stage 2.
MODPOST 1 modules
CC /home1/zhugeyifan/test/ko_module_demo/hello_world.mod.o
LD [M] /home1/zhugeyifan/test/ko_module_demo/hello_world.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-126-generic'
再尝试在Makefile中添加-Werror选项:
ccflags-y += -Werror
再次执行Makefile编译,看到报错:
zhugeyifan@83-28:~/test/ko_module_demo$ make
make -C /lib/modules/4.15.0-126-generic/build M=/home1/zhugeyifan/test/ko_module_demo modules
make[1]: Entering directory '/usr/src/linux-headers-4.15.0-126-generic'
CC [M] /home1/zhugeyifan/test/ko_module_demo/hello_world.o
/home1/zhugeyifan/test/ko_module_demo/hello_world.c: In function ‘hello_init’:
/home1/zhugeyifan/test/ko_module_demo/hello_world.c:6:9: error: unused variable ‘a’ [-Werror=unused-variable]
int a=1;
^
cc1: all warnings being treated as errors
scripts/Makefile.build:337: recipe for target '/home1/zhugeyifan/test/ko_module_demo/hello_world.o' failed
make[2]: *** [/home1/zhugeyifan/test/ko_module_demo/hello_world.o] Error 1
Makefile:1587: recipe for target '_module_/home1/zhugeyifan/test/ko_module_demo' failed
make[1]: *** [_module_/home1/zhugeyifan/test/ko_module_demo] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-126-generic'
Makefile:31: recipe for target 'all' failed
make: *** [all] Error 2
至此,可以得出一个结论:在Makefile中添加-Werror,可以将告警信息转化为错误信息,并在告警发生时终止编译过程。
那假如想要让整个内核都带上-Werror选项,需要怎么做?(如何让内核编译时所有告警信息转化为错误信息,并在告警发生时终止编译过程。)
如何让整个内核都带上-Werror选项?
修改根目录下的Makefile,找到如下语句:KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-Werror-implicit-function-declaration \
-Wno-format-security \
-std=gnu89
在里面添加上-Werror选项,然后再执行Makefile,可以观察到所有的warning都变成了error,并且直接退出编译。
Ps:这里有个注意事项,“KBUILD_CFLAGS:=”的意思是如果未定义,则执行后面的赋值操作。所以在这个之前最好不要操作KBUILD_CFLAGS参数,否则可能会导致一些其他错误。如果在这段话之后,使用“KBUILD_CFLAGS+=”操作,就不会有影响。
实际应用中,我们可能只是希望把一部分warning,变成error,是我们的代码更加的符合规范,那需要怎么做?
内核编译时,如何只让一部分warning编译报错?
可以让Wrerror加上具体的参数,例如:-Werror-xxx,使其只转换一部分的warning。
KBUILD_CFLAGS += -Werror-implicit-function-declaration
KBUILD_CFLAGS += -Werror=unknown-warning-option
KBUILD_CFLAGS += -Werror-implicit-int
KBUILD_CFLAGS += -Werror-strict-prototypes
KBUILD_CFLAGS += -Werror-date-time
KBUILD_CFLAGS += -Werror-incompatible-pointer-types
KBUILD_CFLAGS += -Werror-designated-init
...
如何使内核编译时不将warning视为error?
其实就是上述问题的反向操作。
有多种方式:
1.在Makefile中去除-Werror选项。
第一种方式适用于比较简单的Makefile。就像上面的例子,把Makefile里添加的-Werror去掉就行了!
但是内核代码里,全局搜索Werror会找到很多,一个一个去除太麻烦了!
这时候使用“-w”选项更适合
2.在Makefile中添加-w选项
-w选项是关闭所有告警,这个同样是在内核的根目录下的Makefile中做:
KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-Werror-implicit-function-declaration \
-Wno-format-security \
-std=gnu89
在KBUILD_CFLAGS中添加"-w"参数,再次执行Makefile。
当然,有时候我们是希望只去除一部分的warning转error操作。
3.只去除一部分的warning转error操作
这时候可以通过下面的参数:KBUILD_CFLAGS += -Wno-unused-variable
KBUILD_CFLAGS += -Wno-sign-compare
KBUILD_CFLAGS += -Wno-pointer-sign
KBUILD_CFLAGS += -Wno-unused-function
KBUILD_CFLAGS += -Wno-unused-parameter
KBUILD_CFLAGS += -Wno-unused-variable
KBUILD_CFLAGS += -Wno-implicit-function-declaration
KBUILD_CFLAGS += -Wno-unused-result
/*通过Andriod.mk进行编译*/
如果通过Android.mk进行编译,则修改
LOCAL_CFLAGS += -Wno-unused-variable
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -Wno-missing-field-initializers
LOCAL_CFLAGS += -Wno-implicit-function-declaration
LOCAL_CFLAGS += -Wno-pointer-sign
LOCAL_CFLAGS += -Wno-sign-compare
LOCAL_CFLAGS += -Wno-ignored-attributes
LOCAL_CFLAGS += -Wno-format-invalid-specifier
LOCAL_CFLAGS += -Wno-error
比如上面第一个例子,报错信息是
/home1/zhugeyifan/test/ko_module_demo/hello_world.c:6:9: error: unused variable ‘a’ [-Werror=unused-variable]
那就添加标志如下:
KBUILD_CFLAGS += -Wno-unused-variable
这个标志的意思是:-W,去除unused-variable报错(no-unused-variable)
有没有什么办法不修改Makefile,同样实现不将警告视为错误?
可以在执行makefile时,从外部传参:make KBUILD_CFLAGS+=-w
这样也能实现。不过就是有个隐患,它好像会将Makefile中的KBUILD_CFLAGS其他参数覆盖掉,如同我上面提到的:
KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-Werror-implicit-function-declaration \
-Wno-format-security \
-std=gnu89
Ps:这里有个注意事项,“KBUILD_CFLAGS:=”的意思是如果未定义,则执行后面的赋值操作。所以在这个之前最好不要操作KBUILD_CFLAGS参数,否则可能会导致一些其他错误。如果在这段话之后,使用“KBUILD_CFLAGS+=”操作,就不会有影响。