0

I'm writing a character driver to sit on top of a modified version of ahci in the source tree. I basically have something that looks like this:

topdir
   |
   |- Makfile
   |
   |- mod_ahci
   |     | - Makefile, codefiles
   |
   |- char_interface
   |     | - Makefile, codefiles

now, char_interface requires symbols from mod_ahci. I have the appropriate EXPORT_SYMBOL() macro use for the symbols I need to export. However, I'm having trouble getting the makefiles right to pick up the header file in mod_ahci from char_interface. My toplevel Makefile

ifneq ($(KERNELRELEASE),)
    obj-y := mod_ahci/ char_interface/

else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)

default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

endif

The makefile for char_interface (because the other builds just fine)

ifneq ($(KERNELRELEASE),)
    ccflags-y += -I../mod_ahci
    obj-m := char_interface.o

else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build

default:
    $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules

modules_install:
    $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_install

endif

clean:
    -sudo rmmod ahcip
    -rm -f *.ko* *.mod.* *.o modules.order Modules.symvers

I have referenced various text files in the kernel documentation. For example, I'm referring to .../Documentation/kbuild/makefiles.txt right now as well as .../Documentation/kbuild/modules.txt. Whenever I build, I'm getting /home/captaink/devel/kmodtests/char_interface/char_interface.c:2:22: error: mod_ahci.h: No such file or directory. There is a file named mod_ahci.h in the directory ../mod_ahci. What am I getting wrong with my use of ccflags-y in the makefile for the char driver?

Thanks

Andrew Falanga
  • 2,274
  • 4
  • 26
  • 51

1 Answers1

0

After some digging, I found the answer to the problem. I was misunderstanding what was happening with the makefile's that I was viewing from LDD3 and the kernel documentation (which is, apparently, exactly where O'Reilly took their examples). The build system actually changes directories into /usr/src/kernels/$(uname -r)/build (or similar) because this is why my header file wasn't being found by the compiler.

I'm not saying this is an elegant way of doing this, but here's how I fixed it. The makefile in the top directory now looks like:

ifneq ($(KERNELRELEASE),)
    obj-y := mod_ahci/ char_interface/

else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)

default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) TOP_DIR=$(PWD) modules

modules_install:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

endif

And the makefile in the subdirectory containing the char driver interface looks like:

ifneq ($(KERNELRELEASE),)
    ccflags-y += -I$(TOP_DIR)/mod_ahci
    obj-m := char_interface.o

else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build

default:
    $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules

modules_install:
    $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_install

endif

clean:
    -sudo rmmod ahcip
    -rm -f *.ko* *.mod.* *.o modules.order Modules.symvers

As you can tell, the makefiles have been copied extensively. The subdirectories probably don't need the "shared" makefile stuff in them because that's taken care of by the higher level makefile. Nevertheless, the modules now build and the character driver I have knows of the exported symbols I made in my modified ahci driver.

I hope this may help someone who's a neophyte, like myself, to the Linux kernel build world and Linux kernel drivers.

Andrew Falanga
  • 2,274
  • 4
  • 26
  • 51