Commit 8cd07cc6 authored by Masahiro Yamada's avatar Masahiro Yamada
Browse files

kbuild: allow to start building external modules in any directory



Unless an explicit O= option is provided, external module builds must
start from the kernel directory.

This can be achieved by using the -C option:

  $ make -C /path/to/kernel M=/path/to/external/module

This commit allows starting external module builds from any directory,
so you can also do the following:

  $ make -f /path/to/kernel/Makefile M=/path/to/external/module

The key difference is that the -C option changes the working directory
and parses the Makefile located there, while the -f option only
specifies the Makefile to use.

As shown in the examples in Documentation/kbuild/modules.rst, external
modules usually have a wrapper Makefile that allows you to build them
without specifying any make arguments. The Makefile typically contains
a rule as follows:

    KDIR ?= /path/to/kernel
    default:
            $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKECMDGOALS)

The log will appear as follows:

    $ make
    make -C /path/to/kernel M=/path/to/external/module
    make[1]: Entering directory '/path/to/kernel'
    make[2]: Entering directory '/path/to/external/module'
      CC [M]  helloworld.o
      MODPOST Module.symvers
      CC [M]  helloworld.mod.o
      CC [M]  .module-common.o
      LD [M]  helloworld.ko
    make[2]: Leaving directory '/path/to/external/module'
    make[1]: Leaving directory '/path/to/kernel'

This changes the working directory twice because the -C option first
switches to the kernel directory, and then Kbuild internally recurses
back to the external module directory.

With this commit, the wrapper Makefile can directly include the kernel
Makefile:

    KDIR ?= /path/to/kernel
    export KBUILD_EXTMOD := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
    include $(KDIR)/Makefile

This avoids unnecessary sub-make invocations:

    $ make
      CC [M]  helloworld.o
      MODPOST Module.symvers
      CC [M]  helloworld.mod.o
      CC [M]  .module-common.o
      LD [M]  helloworld.ko

Signed-off-by: default avatarMasahiro Yamada <masahiroy@kernel.org>
Reviewed-by: default avatarNicolas Schier <nicolas@fjasle.eu>
parent a2a45ebe
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -59,6 +59,12 @@ Command Syntax

		$ make -C /lib/modules/`uname -r`/build M=$PWD modules_install

	Starting from Linux 6.13, you can use the -f option instead of -C. This
	will avoid unnecessary change of the working directory. The external
	module will be output to the directory where you invoke make.

		$ make -f /lib/modules/`uname -r`/build/Makefile M=$PWD

Options
-------

@@ -221,6 +227,21 @@ Separate Kbuild File and Makefile
	consisting of several hundred lines, and here it really pays
	off to separate the kbuild part from the rest.

	Linux 6.13 and later support another way. The external module Makefile
	can include the kernel Makefile directly, rather than invoking sub Make.

	Example 3::

		--> filename: Kbuild
		obj-m  := 8123.o
		8123-y := 8123_if.o 8123_pci.o

		--> filename: Makefile
		KDIR ?= /lib/modules/$(shell uname -r)/build
		export KBUILD_EXTMOD := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
		include $(KDIR)/Makefile


Building Multiple Modules
-------------------------

+6 −2
Original line number Diff line number Diff line
@@ -189,9 +189,13 @@ ifdef KBUILD_EXTMOD
        objtree := $(realpath $(KBUILD_OUTPUT))
        $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
    else
        objtree := $(CURDIR)
        objtree := $(abs_srctree)
    endif
    output := $(or $(KBUILD_EXTMOD_OUTPUT),$(KBUILD_EXTMOD))
    # If Make is invoked from the kernel directory (either kernel
    # source directory or kernel build directory), external modules
    # are built in $(KBUILD_EXTMOD) for backward compatibility,
    # otherwise, built in the current directory.
    output := $(or $(KBUILD_EXTMOD_OUTPUT),$(if $(filter $(CURDIR),$(objtree) $(abs_srctree)),$(KBUILD_EXTMOD)))
    # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
    # Make changes the working directory.
    srcroot := $(realpath $(KBUILD_EXTMOD))