How to compile a Linux kernel module?

I'm trying to compile a simple hello world module following this guide and I'm confused about what the Makefile is actually doing.

Here it is:

obj-m += hello-1.o

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

I understand that when I type the make command it will run the all recipe which runs make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules. So now it runs the Makefile found at the path given after the -C flag, but what does the M=$(PWD) modules do?


  • Here is a breakdown:

    1. obj-m: specifies object files which are built as loadable kernel modules.

    2. all and clean: If you run make by default it will run the first target, which is all. But we can use make all and make clean too: it will run only those specific targets.

      For example:

      make all
      # Will run: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
      make clean
      # Will run: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    3. uname -r: get version information about the current kernel.

      Example: for me, the output is 4.6.0-rc1.

    4. Option -C dir: change to directory dir before reading the makefiles in there.


      make -C /lib/modules/$(shell uname -r)/build
      # Will translate to: make -C /lib/modules/4.6.0-rc1/build
      # And execute the Makefile at /lib/modules/4.6.0-rc1/build/Makefile
    5. $(PWD): get the path of your current directory.

    Now you want to create your loadable module by using:

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

    Your source code needs a specific environment to be compiled. That's why we have to use the -C option to change build directory. Which have all needed definitions, header file, macros etc. Now after changing to the build directory you tell the kernel Makefile where your module is located using M=$(PWD).