初心者の備忘録
環境:
raspberry pi 2B (kernel 6.1.21-v7+)
問題
組み込みLinuxデバイスドライバの作り方 (2)を参考にデバイスドライバを勉強しているなか、ふとMakefileでプリプロセッサを機能させる方法を見かけたので試した。
make -C /lib/modules/$(shell uname -r)/build CFLAGS="-DDEBUG" M=$(shell pwd) modules
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#define DRIVER_NAME "MyDevice_NAME"
#define DRIVER_MAJOR 63
static int myDevice_open(struct inode *inode, struct file *file) {
printk("mydevice_open\n");
#ifdef DEBUG
printk("DEBUG\n");
#endif
return 0;
}
static int myDevice_close(struct inode *inode, struct file *file) {
printk("mydevice_close\n");
#ifdef DEBUG
printk("DEBUG\n");
#endif
return 0;
}
static ssize_t myDevice_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos) {
printk("mydevice_read\n");
#ifdef DEBUG
printk("DEBUG\n");
#endif
buf[0] = 'A';
return 1;
}
static ssize_t myDevice_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos) {
printk("mydevice_write\n");
#ifdef DEBUG
printk("DEBUG\n");
#endif
return 1;
}
struct file_operations s_myDevice_fops = {
.open = myDevice_open,
.release = myDevice_close,
.read = myDevice_read,
.write = myDevice_write,
};
static int myDevice_init(void) {
printk("mydevice_init\n");
#ifdef DEBUG
printk("DEBUG\n");
#endif
register_chrdev(DRIVER_MAJOR, DRIVER_NAME, &s_myDevice_fops);
return 0;
}
static void myDevice_exit(void) {
printk("myDevice_exit\n");
#ifdef DEBUG
printk("DEBUG\n");
#endif
unregister_chrdev(DRIVER_MAJOR, DRIVER_NAME);
}
module_init(myDevice_init);
module_exit(myDevice_exit);
MODULE_LICENSE("GPL2");
しかし、下記のようにプリプロセッサが効かなかった。
どうもCFLAGSではだめらしい。
insmod MyDeviceModule.ko
dmesg
-> mydevice_init
結論
KernelのMakefileにはccflags-y, asflags-y, ldflags-y
を使用すればよい(それぞれcc, as, ld用)
昔はEXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGSだったが現在は非推奨とのこと。
参考:
Linux Kernel Makefiles
LinuxカーネルのMakefileを解析する その7
How to set preprocessor directives in makefile for kernel module build target?
例: DEBUGを定義する
make -C /lib/modules/$(shell uname -r)/build ccflags-y="-DDEBUG" M=$(shell pwd) modules
但し、そのまま使うとMakefile内の同一変数の値を上書きする可能性があるため、下記のようにして回避するといいらしい。
ccflags-y += $(FOO_CFLAGS)
debug:
make -C /lib/modules/$(shell uname -r)/build FOO_CFLAGS="-DDEBUG" M=$(shell pwd) modules
感想
普通のMakefileとKernel用のMakefileでフラグの作り方が違うことを知って勉強になった。
なんでCFLAGS相当がccflags-yなんだろう?という点が気になった。