요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=========================
Building External Modules
=========================
This document describes how to build an out-of-tree kernel module.
Introduction
============
"kbuild" is the build system used by the Linux kernel. Modules must use
kbuild to stay compatible with changes in the build infrastructure and
to pick up the right flags to the compiler. Functionality for building modules
both in-tree and out-of-tree is provided. The method for building
either is similar, and all modules are initially developed and built
out-of-tree.
Covered in this document is information aimed at developers interested
in building out-of-tree (or "external") modules. The author of an
external module should supply a makefile that hides most of the
complexity, so one only has to type "make" to build the module. This is
easily accomplished, and a complete example will be presented in
section `Creating a Kbuild File for an External Module`_.
How to Build External Modules
=============================
To build external modules, you must have a prebuilt kernel available
that contains the configuration and header files used in the build.
Also, the kernel must have been built with modules enabled. If you are
using a distribution kernel, there will be a package for the kernel you
are running provided by your distribution.
An alternative is to use the "make" target "modules_prepare." This will
make sure the kernel contains the information required. The target
exists solely as a simple way to prepare a kernel source tree for
building external modules.
NOTE: "modules_prepare" will not build Module.symvers even if
CONFIG_MODVERSIONS is set; therefore, a full kernel build needs to be
executed to make module versioning work.
Command Syntax
--------------
The command to build an external module is::
$ make -C <path_to_kernel_dir> M=$PWD
The kbuild system knows that an external module is being built
due to the "M=<dir>" option given in the command.
To build against the running kernel use::
$ make -C /lib/modules/`uname -r`/build M=$PWD
Then to install the module(s) just built, add the target
"modules_install" to the command::
$ 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
-------
($KDIR refers to the path of the kernel source directory, or the path
of the kernel output directory if the kernel was built in a separate
build directory.)
You can optionally pass MO= option if you want to build the modules in
a separate directory.
make -C $KDIR M=$PWD [MO=$BUILD_DIR]
-C $KDIR
The directory that contains the kernel and relevant build
artifacts used for building an external module.
"make" will actually change to the specified directory
when executing and will change back when finished.
M=$PWD
Informs kbuild that an external module is being built.
The value given to "M" is the absolute path of the
directory where the external module (kbuild file) is
located.
MO=$BUILD_DIR
Specifies a separate output directory for the external module.
Targets
-------
When building an external module, only a subset of the "make"
targets are available.
make -C $KDIR M=$PWD [target]
The default will build the module(s) located in the current
directory, so a target does not need to be specified. All
output files will also be generated in this directory. No
attempts are made to update the kernel source, and it is a
precondition that a successful "make" has been executed for the
kernel.
modules
The default target for external modules. It has the
same functionality as if no target was specified. See
description above.
modules_install
Install the external module(s). The default location is
/lib/modules/<kernel_release>/updates/, but a prefix may
be added with INSTALL_MOD_PATH (discussed in section
`Module Installation`_).
clean
Remove all generated files in the module directory only.
help
List the available targets for external modules.
Building Separate Files
-----------------------
It is possible to build single files that are part of a module.
This works equally well for the kernel, a module, and even for
external modules.
Example (The module foo.ko, consist of bar.o and baz.o)::
make -C $KDIR M=$PWD bar.lst
make -C $KDIR M=$PWD baz.o
make -C $KDIR M=$PWD foo.ko
make -C $KDIR M=$PWD ./
Creating a Kbuild File for an External Module
=============================================
In the last section we saw the command to build a module for the
running kernel. The module is not actually built, however, because a
build file is required. Contained in this file will be the name of
the module(s) being built, along with the list of requisite source
files. The file may be as simple as a single line::
obj-m := <module_name>.o
The kbuild system will build <module_name>.o from <module_name>.c,
and, after linking, will result in the kernel module <module_name>.ko.
The above line can be put in either a "Kbuild" file or a "Makefile."
When the module is built from multiple sources, an additional line is
needed listing the files::
<module_name>-y := <src1>.o <src2>.o ...
NOTE: Further documentation describing the syntax used by kbuild is
located in Documentation/kbuild/makefiles.rst.
The examples below demonstrate how to create a build file for the
module 8123.ko, which is built from the following files::
8123_if.c
8123_if.h
8123_pci.c
Shared Makefile
---------------
An external module always includes a wrapper makefile that
supports building the module using "make" with no arguments.
This target is not used by kbuild; it is only for convenience.
Additional functionality, such as test targets, can be included
but should be filtered out from kbuild due to possible name
clashes.
Example 1::
--> filename: Makefile
ifneq ($(KERNELRELEASE),)
# kbuild part of makefile
obj-m := 8123.o
8123-y := 8123_if.o 8123_pci.o
else
# normal makefile
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
endif
The check for KERNELRELEASE is used to separate the two parts
of the makefile. In the example, kbuild will only see the two
assignments, whereas "make" will see everything except these
two assignments. This is due to two passes made on the file:
the first pass is by the "make" instance run on the command
line; the second pass is by the kbuild system, which is
initiated by the parameterized "make" in the default target.
Separate Kbuild File and Makefile
---------------------------------
Kbuild will first look for a file named "Kbuild", and if it is not
found, it will then look for "Makefile". Utilizing a "Kbuild" file
allows us to split up the "Makefile" from example 1 into two files:
Example 2::
--> filename: Kbuild
obj-m := 8123.o
8123-y := 8123_if.o 8123_pci.o
--> filename: Makefile
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
The split in example 2 is questionable due to the simplicity of
each file; however, some external modules use makefiles
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
-------------------------
kbuild supports building multiple modules with a single build
file. For example, if you wanted to build two modules, foo.ko
and bar.ko, the kbuild lines would be::
obj-m := foo.o bar.o
foo-y := <foo_srcs>
bar-y := <bar_srcs>
It is that simple!
Include Files
=============
Within the kernel, header files are kept in standard locations
according to the following rule:
* If the header file only describes the internal interface of a
module, then the file is placed in the same directory as the
source files.
* If the header file describes an interface used by other parts
of the kernel that are located in different directories, then
the file is placed in include/linux/.
NOTE:
There are two notable exceptions to this rule: larger
subsystems have their own directory under include/, such as
include/scsi; and architecture specific headers are located
under arch/$(SRCARCH)/include/.
Kernel Includes
---------------
To include a header file located under include/linux/, simply
use::
#include <linux/module.h>
kbuild will add options to the compiler so the relevant directories
are searched.
Single Subdirectory
-------------------
External modules tend to place header files in a separate
include/ directory where their source is located, although this
is not the usual kernel style. To inform kbuild of the
directory, use either ccflags-y or CFLAGS_<filename>.o.
Using the example from section 3, if we moved 8123_if.h to a
subdirectory named include, the resulting kbuild file would
look like::
--> filename: Kbuild
obj-m := 8123.o
ccflags-y := -I $(src)/include
8123-y := 8123_if.o 8123_pci.o
Several Subdirectories
----------------------
kbuild can handle files that are spread over several directories.
Consider the following example::
.
|__ src
| |__ complex_main.c
| |__ hal
| |__ hardwareif.c
| |__ include
| |__ hardwareif.h
|__ include
|__ complex.h
To build the module complex.ko, we then need the following
kbuild file::
--> filename: Kbuild
obj-m := complex.o
complex-y := src/complex_main.o
complex-y += src/hal/hardwareif.o
ccflags-y := -I$(src)/include
ccflags-y += -I$(src)/src/hal/include
As you can see, kbuild knows how to handle object files located
in other directories. The trick is to specify the directory
relative to the kbuild file's location. That being said, this
is NOT recommended practice.
For the header files, kbuild must be explicitly told where to
look. When kbuild executes, the current directory is always the
root of the kernel tree (the argument to "-C") and therefore an
absolute path is needed. $(src) provides the absolute path by
pointing to the directory where the currently executing kbuild
file is located.
Module Installation
===================
Modules which are included in the kernel are installed in the
directory:
/lib/modules/$(KERNELRELEASE)/kernel/
And external modules are installed in:
/lib/modules/$(KERNELRELEASE)/updates/
INSTALL_MOD_PATH
----------------
Above are the default directories but as always some level of
customization is possible. A prefix can be added to the
installation path using the variable INSTALL_MOD_PATH::
$ make INSTALL_MOD_PATH=/frodo modules_install
=> Install dir: /frodo/lib/modules/$(KERNELRELEASE)/kernel/
INSTALL_MOD_PATH may be set as an ordinary shell variable or,
as shown above, can be specified on the command line when
calling "make." This has effect when installing both in-tree
and out-of-tree modules.
INSTALL_MOD_DIR
---------------
External modules are by default installed to a directory under
/lib/modules/$(KERNELRELEASE)/updates/, but you may wish to
locate modules for a specific functionality in a separate
directory. For this purpose, use INSTALL_MOD_DIR to specify an
alternative name to "updates."::
$ make INSTALL_MOD_DIR=gandalf -C $KDIR \
M=$PWD modules_install
=> Install dir: /lib/modules/$(KERNELRELEASE)/gandalf/
Module Versioning
=================
Module versioning is enabled by the CONFIG_MODVERSIONS tag, and is used
as a simple ABI consistency check. A CRC value of the full prototype
for an exported symbol is created. When a module is loaded/used, the
CRC values contained in the kernel are compared with similar values in
the module; if they are not equal, the kernel refuses to load the
module.
Module.symvers contains a list of all exported symbols from a kernel
build.
Symbols From the Kernel (vmlinux + modules)
-------------------------------------------
During a kernel build, a file named Module.symvers will be
generated. Module.symvers contains all exported symbols from
the kernel and compiled modules. For each symbol, the
corresponding CRC value is also stored.
The syntax of the Module.symvers file is::
<CRC> <Symbol> <Module> <Export Type> <Namespace>
0xe1cc2a05 usb_stor_suspend drivers/usb/storage/usb-storage EXPORT_SYMBOL_GPL USB_STORAGE
The fields are separated by tabs and values may be empty (e.g.
if no namespace is defined for an exported symbol).
For a kernel build without CONFIG_MODVERSIONS enabled, the CRC
would read 0x00000000.
Module.symvers serves two purposes:
1) It lists all exported symbols from vmlinux and all modules.
2) It lists the CRC if CONFIG_MODVERSIONS is enabled.
Version Information Formats
---------------------------
Exported symbols have information stored in __ksymtab or __ksymtab_gpl
sections. Symbol names and namespaces are stored in __ksymtab_strings,
using a format similar to the string table used for ELF. If
CONFIG_MODVERSIONS is enabled, the CRCs corresponding to exported
symbols will be added to the __kcrctab or __kcrctab_gpl.
If CONFIG_BASIC_MODVERSIONS is enabled (default with
CONFIG_MODVERSIONS), imported symbols will have their symbol name and
CRC stored in the __versions section of the importing module. This
mode only supports symbols of length up to 64 bytes.
If CONFIG_EXTENDED_MODVERSIONS is enabled (required to enable both
CONFIG_MODVERSIONS and CONFIG_RUST at the same time), imported symbols
will have their symbol name recorded in the __version_ext_names
section as a series of concatenated, null-terminated strings. CRCs for
these symbols will be recorded in the __version_ext_crcs section.
Symbols and External Modules
----------------------------
When building an external module, the build system needs access
to the symbols from the kernel to check if all external symbols
are defined. This is done in the MODPOST step. modpost obtains
the symbols by reading Module.symvers from the kernel source
tree. During the MODPOST step, a new Module.symvers file will be
written containing all exported symbols from that external module.
Symbols From Another External Module
------------------------------------
Sometimes, an external module uses exported symbols from
another external module. Kbuild needs to have full knowledge of
all symbols to avoid spitting out warnings about undefined
symbols. Two solutions exist for this situation.
NOTE: The method with a top-level kbuild file is recommended
but may be impractical in certain situations.
Use a top-level kbuild file
If you have two modules, foo.ko and bar.ko, where
foo.ko needs symbols from bar.ko, you can use a
common top-level kbuild file so both modules are
compiled in the same build. Consider the following
directory layout::
./foo/ <= contains foo.ko
./bar/ <= contains bar.ko
The top-level kbuild file would then look like::
#./Kbuild (or ./Makefile):
obj-m := foo/ bar/
And executing::
$ make -C $KDIR M=$PWD
will then do the expected and compile both modules with
full knowledge of symbols from either module.
Use "make" variable KBUILD_EXTRA_SYMBOLS
If it is impractical to add a top-level kbuild file,
you can assign a space separated list
of files to KBUILD_EXTRA_SYMBOLS in your build file.
These files will be loaded by modpost during the
initialization of its symbol tables.
Tips & Tricks
=============
Testing for CONFIG_FOO_BAR
--------------------------
Modules often need to check for certain `CONFIG_` options to
decide if a specific feature is included in the module. In
kbuild this is done by referencing the `CONFIG_` variable
directly::
#fs/ext2/Makefile
obj-$(CONFIG_EXT2_FS) += ext2.o
ext2-y := balloc.o bitmap.o dir.o
ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
소개와 외부 모듈 빌드
1-76이 문서는 source tree 밖에서 개발하는 out-of-tree kernel module, 즉 external module을 build하는 방법을 설명합니다. Linux kernel의 build system인 kbuild를 사용해야 build infrastructure의 변경과 compiler flag를 올바르게 따라갈 수 있습니다. In-tree와 out-of-tree module의 build 방식은 비슷하며, module은 처음에는 대개 source tree 밖에서 개발됩니다.
External module 작성자는 사용자가 인자 없이 `make`만 실행해도 module을 build할 수 있도록 복잡성을 감싼 Makefile을 제공해야 합니다. 이 문서의 `Creating a Kbuild File for an External Module` 절에서 완전한 예제를 제시합니다.
External module을 build하려면 build에 사용된 configuration과 header를 포함하는 미리 build된 kernel이 필요하고, kernel에서 module 기능이 활성화되어 있어야 합니다. Distribution kernel을 사용한다면 실행 중인 kernel에 대응하는 개발 package를 distribution에서 설치할 수 있습니다.
대안으로 kernel source tree에서 `make modules_prepare`를 실행할 수 있습니다. 이 target은 external module build에 필요한 정보를 준비하지만, `CONFIG_MODVERSIONS`가 설정되어 있어도 `Module.symvers`는 생성하지 않습니다. 따라서 module versioning이 필요하면 full kernel build를 수행해야 합니다.
준비된 kernel tree와 module directory를 kbuild에 연결하는 순서입니다.
기본 command는 `$ make -C <path_to_kernel_dir> M=$PWD`입니다. `M=<dir>`가 external module build임을 kbuild에 알립니다. 실행 중인 kernel을 대상으로 할 때는 `$ make -C /lib/modules/\`uname -r\`/build M=$PWD`를 사용하고, 설치하려면 끝에 `modules_install` target을 붙입니다.
Linux 6.13부터는 `-C` 대신 `-f /lib/modules/\`uname -r\`/build/Makefile`을 사용할 수 있습니다. 이 방식은 working directory를 불필요하게 바꾸지 않으며, make를 호출한 directory에 external module output을 생성합니다.
`$KDIR`은 kernel source directory 또는 분리 build를 사용한 경우 kernel output directory입니다.
Module output을 별도 directory에 두려면 `make -C $KDIR M=$PWD MO=$BUILD_DIR`처럼 `MO=`를 선택적으로 전달합니다.
=========================
Building External Modules
=========================
This document describes how to build an out-of-tree kernel module.
Introduction
============
"kbuild" is the build system used by the Linux kernel. Modules must use
kbuild to stay compatible with changes in the build infrastructure and
to pick up the right flags to the compiler. Functionality for building modules
both in-tree and out-of-tree is provided. The method for building
either is similar, and all modules are initially developed and built
out-of-tree.
Covered in this document is information aimed at developers interested
in building out-of-tree (or "external") modules. The author of an
external module should supply a makefile that hides most of the
complexity, so one only has to type "make" to build the module. This is
easily accomplished, and a complete example will be presented in
section `Creating a Kbuild File for an External Module`_.
How to Build External Modules
=============================
To build external modules, you must have a prebuilt kernel available
that contains the configuration and header files used in the build.
Also, the kernel must have been built with modules enabled. If you are
using a distribution kernel, there will be a package for the kernel you
are running provided by your distribution.
An alternative is to use the "make" target "modules_prepare." This will
make sure the kernel contains the information required. The target
exists solely as a simple way to prepare a kernel source tree for
building external modules.
NOTE: "modules_prepare" will not build Module.symvers even if
CONFIG_MODVERSIONS is set; therefore, a full kernel build needs to be
executed to make module versioning work.
Command Syntax
--------------
The command to build an external module is::
$ make -C <path_to_kernel_dir> M=$PWD
The kbuild system knows that an external module is being built
due to the "M=<dir>" option given in the command.
To build against the running kernel use::
$ make -C /lib/modules/`uname -r`/build M=$PWD
Then to install the module(s) just built, add the target
"modules_install" to the command::
$ 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
-------
($KDIR refers to the path of the kernel source directory, or the path
of the kernel output directory if the kernel was built in a separate
build directory.)
You can optionally pass MO= option if you want to build the modules in
a separate directory.
Target과 개별 file 빌드
77-140External module build에서는 kernel 전체 target 중 일부만 사용할 수 있습니다. 기본 command 형식은 `make -C $KDIR M=$PWD [target]`입니다. Target을 생략하면 현재 directory의 module을 build하고 모든 output도 그 directory에 만듭니다.
External module build는 kernel source를 갱신하지 않습니다. 대상 kernel에서 성공적인 `make`가 이미 수행되었다는 전제가 있습니다.
External module에 공개되는 주요 make target입니다.
Module에 포함되는 file 하나만 선택해 build할 수도 있습니다. Kernel, in-tree module, external module 모두 같은 방식으로 동작합니다.
예를 들어 `foo.ko`가 `bar.o`와 `baz.o`로 구성되면 `bar.lst`, `baz.o`, `foo.ko`를 각각 target으로 지정할 수 있습니다. `./` target은 현재 external module directory를 build합니다. 정확한 command는 아래 원문 code block에 보존되어 있습니다.
make -C $KDIR M=$PWD [MO=$BUILD_DIR]
-C $KDIR
The directory that contains the kernel and relevant build
artifacts used for building an external module.
"make" will actually change to the specified directory
when executing and will change back when finished.
M=$PWD
Informs kbuild that an external module is being built.
The value given to "M" is the absolute path of the
directory where the external module (kbuild file) is
located.
MO=$BUILD_DIR
Specifies a separate output directory for the external module.
Targets
-------
When building an external module, only a subset of the "make"
targets are available.
make -C $KDIR M=$PWD [target]
The default will build the module(s) located in the current
directory, so a target does not need to be specified. All
output files will also be generated in this directory. No
attempts are made to update the kernel source, and it is a
precondition that a successful "make" has been executed for the
kernel.
modules
The default target for external modules. It has the
same functionality as if no target was specified. See
description above.
modules_install
Install the external module(s). The default location is
/lib/modules/<kernel_release>/updates/, but a prefix may
be added with INSTALL_MOD_PATH (discussed in section
`Module Installation`_).
clean
Remove all generated files in the module directory only.
help
List the available targets for external modules.
Building Separate Files
-----------------------
It is possible to build single files that are part of a module.
This works equally well for the kernel, a module, and even for
external modules.
Example (The module foo.ko, consist of bar.o and baz.o)::
make -C $KDIR M=$PWD bar.lst
make -C $KDIR M=$PWD baz.o
make -C $KDIR M=$PWD foo.ko
make -C $KDIR M=$PWD ./
External module용 Kbuild file 작성
141-258실제 module build에는 module 이름과 필요한 source file 목록을 담은 build file이 필요합니다. Source 하나로 구성된 module은 `obj-m := <module_name>.o` 한 줄이면 됩니다. Kbuild는 `<module_name>.c`에서 object를 build하고 link하여 `<module_name>.ko`를 만듭니다.
이 선언은 `Kbuild` 또는 `Makefile`에 둘 수 있습니다. Source가 여러 개라면 `<module_name>-y := <src1>.o <src2>.o ...`로 구성 object를 나열합니다. 자세한 kbuild syntax는 `Documentation/kbuild/makefiles.rst`를 참조합니다.
문서의 예제 module `8123.ko`는 `8123_if.c`, `8123_if.h`, `8123_pci.c`로 구성됩니다. Shared Makefile 방식은 kbuild 영역과 일반 make 영역을 한 file에 함께 둡니다. 사용자가 인자 없이 `make`를 실행할 수 있게 하는 wrapper target은 kbuild가 직접 사용하지 않는 편의 기능이며, test 같은 추가 target은 이름 충돌을 피하도록 kbuild에서 걸러야 합니다.
예제 1은 `ifneq ($(KERNELRELEASE),)`로 두 영역을 구분합니다. Command line에서 실행한 첫 번째 make는 wrapper 영역을 보고, default target의 `$(MAKE) -C $(KDIR) M=$$PWD`가 시작한 두 번째 kbuild pass는 `obj-m`과 `8123-y` 선언을 봅니다.
`KERNELRELEASE` 유무가 wrapper make와 kbuild 영역을 나눕니다.
Kbuild는 먼저 `Kbuild`라는 file을 찾고 없으면 `Makefile`을 찾습니다. 따라서 예제 2처럼 module 선언은 `Kbuild`에, 편의 target과 `KDIR` 설정은 `Makefile`에 분리할 수 있습니다. 작은 예제에서는 이득이 적지만 수백 줄짜리 external module Makefile에서는 관심사를 분리하는 효과가 큽니다.
Linux 6.13 이상에서는 sub-make를 호출하는 대신 external module Makefile에서 kernel Makefile을 직접 include할 수도 있습니다. `KBUILD_EXTMOD`를 현재 Makefile directory의 real path로 export한 다음 `include $(KDIR)/Makefile`을 사용합니다.
세 가지 wrapper 구성과 용도를 비교합니다.
한 build file에서 module 여러 개도 만들 수 있습니다. `obj-m := foo.o bar.o`로 module을 나열하고 `foo-y`, `bar-y`에 각각 source object를 지정하면 `foo.ko`와 `bar.ko`를 함께 build합니다.
Creating a Kbuild File for an External Module
=============================================
In the last section we saw the command to build a module for the
running kernel. The module is not actually built, however, because a
build file is required. Contained in this file will be the name of
the module(s) being built, along with the list of requisite source
files. The file may be as simple as a single line::
obj-m := <module_name>.o
The kbuild system will build <module_name>.o from <module_name>.c,
and, after linking, will result in the kernel module <module_name>.ko.
The above line can be put in either a "Kbuild" file or a "Makefile."
When the module is built from multiple sources, an additional line is
needed listing the files::
<module_name>-y := <src1>.o <src2>.o ...
NOTE: Further documentation describing the syntax used by kbuild is
located in Documentation/kbuild/makefiles.rst.
The examples below demonstrate how to create a build file for the
module 8123.ko, which is built from the following files::
8123_if.c
8123_if.h
8123_pci.c
Shared Makefile
---------------
An external module always includes a wrapper makefile that
supports building the module using "make" with no arguments.
This target is not used by kbuild; it is only for convenience.
Additional functionality, such as test targets, can be included
but should be filtered out from kbuild due to possible name
clashes.
Example 1::
--> filename: Makefile
ifneq ($(KERNELRELEASE),)
# kbuild part of makefile
obj-m := 8123.o
8123-y := 8123_if.o 8123_pci.o
else
# normal makefile
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
endif
The check for KERNELRELEASE is used to separate the two parts
of the makefile. In the example, kbuild will only see the two
assignments, whereas "make" will see everything except these
two assignments. This is due to two passes made on the file:
the first pass is by the "make" instance run on the command
line; the second pass is by the kbuild system, which is
initiated by the parameterized "make" in the default target.
Separate Kbuild File and Makefile
---------------------------------
Kbuild will first look for a file named "Kbuild", and if it is not
found, it will then look for "Makefile". Utilizing a "Kbuild" file
allows us to split up the "Makefile" from example 1 into two files:
Example 2::
--> filename: Kbuild
obj-m := 8123.o
8123-y := 8123_if.o 8123_pci.o
--> filename: Makefile
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
The split in example 2 is questionable due to the simplicity of
each file; however, some external modules use makefiles
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
-------------------------
kbuild supports building multiple modules with a single build
file. For example, if you wanted to build two modules, foo.ko
and bar.ko, the kbuild lines would be::
obj-m := foo.o bar.o
foo-y := <foo_srcs>
bar-y := <bar_srcs>
It is that simple!
Header와 여러 subdirectory
259-346Kernel 내부 header 배치는 interface 범위에 따릅니다. Module 내부에서만 쓰는 header는 source와 같은 directory에 두고, 다른 directory의 kernel 코드도 사용하는 interface header는 `include/linux/`에 둡니다.
큰 subsystem은 `include/scsi`처럼 `include/` 아래에 자체 directory를 둘 수 있고, architecture-specific header는 `arch/$(SRCARCH)/include/`에 둡니다.
`include/linux/` 아래 header는 `#include <linux/module.h>`처럼 include합니다. Kbuild가 compiler search path를 자동으로 추가합니다.
External module은 kernel의 일반 style과 달리 source 옆 `include/` directory에 header를 두는 경우가 많습니다. 이 path는 `ccflags-y` 또는 `CFLAGS_<filename>.o`로 kbuild에 알려야 합니다. `8123_if.h`를 `include/`로 옮겼다면 `ccflags-y := -I $(src)/include`를 사용합니다.
여러 directory에 source가 퍼진 module도 build할 수 있습니다. 예제의 `complex.ko`는 `src/complex_main.o`와 `src/hal/hardwareif.o`를 `complex-y`에 나열하고, 두 header directory를 `ccflags-y`의 `-I` option으로 추가합니다.
Header의 공개 범위와 Kbuild 설정을 연결합니다.
Object path는 Kbuild file 위치를 기준으로 상대 지정합니다. 다만 source를 여러 directory에 흩어 두는 방식은 권장되지 않습니다.
Kbuild 실행 시 current directory는 항상 `-C`로 전달한 kernel tree root입니다. 따라서 external header path에는 absolute path가 필요하고, `$(src)`가 현재 실행 중인 Kbuild file directory의 absolute path를 제공합니다.
Include Files
=============
Within the kernel, header files are kept in standard locations
according to the following rule:
* If the header file only describes the internal interface of a
module, then the file is placed in the same directory as the
source files.
* If the header file describes an interface used by other parts
of the kernel that are located in different directories, then
the file is placed in include/linux/.
NOTE:
There are two notable exceptions to this rule: larger
subsystems have their own directory under include/, such as
include/scsi; and architecture specific headers are located
under arch/$(SRCARCH)/include/.
Kernel Includes
---------------
To include a header file located under include/linux/, simply
use::
#include <linux/module.h>
kbuild will add options to the compiler so the relevant directories
are searched.
Single Subdirectory
-------------------
External modules tend to place header files in a separate
include/ directory where their source is located, although this
is not the usual kernel style. To inform kbuild of the
directory, use either ccflags-y or CFLAGS_<filename>.o.
Using the example from section 3, if we moved 8123_if.h to a
subdirectory named include, the resulting kbuild file would
look like::
--> filename: Kbuild
obj-m := 8123.o
ccflags-y := -I $(src)/include
8123-y := 8123_if.o 8123_pci.o
Several Subdirectories
----------------------
kbuild can handle files that are spread over several directories.
Consider the following example::
.
|__ src
| |__ complex_main.c
| |__ hal
| |__ hardwareif.c
| |__ include
| |__ hardwareif.h
|__ include
|__ complex.h
To build the module complex.ko, we then need the following
kbuild file::
--> filename: Kbuild
obj-m := complex.o
complex-y := src/complex_main.o
complex-y += src/hal/hardwareif.o
ccflags-y := -I$(src)/include
ccflags-y += -I$(src)/src/hal/include
As you can see, kbuild knows how to handle object files located
in other directories. The trick is to specify the directory
relative to the kbuild file's location. That being said, this
is NOT recommended practice.
For the header files, kbuild must be explicitly told where to
look. When kbuild executes, the current directory is always the
root of the kernel tree (the argument to "-C") and therefore an
absolute path is needed. $(src) provides the absolute path by
pointing to the directory where the currently executing kbuild
file is located.
Module 설치 위치
347-387Kernel source에 포함된 module은 `/lib/modules/$(KERNELRELEASE)/kernel/`에 설치되고, external module은 기본적으로 `/lib/modules/$(KERNELRELEASE)/updates/`에 설치됩니다.
`INSTALL_MOD_PATH`는 전체 설치 path 앞에 prefix를 붙입니다. 예를 들어 `$ make INSTALL_MOD_PATH=/frodo modules_install`은 in-tree module을 `/frodo/lib/modules/$(KERNELRELEASE)/kernel/` 아래에 설치합니다. 이 값은 shell variable이나 make command line에서 설정할 수 있고 in-tree와 out-of-tree module 모두에 적용됩니다.
External module의 기본 subdirectory 이름 `updates`를 기능별 이름으로 바꾸려면 `INSTALL_MOD_DIR`을 사용합니다. `$ make INSTALL_MOD_DIR=gandalf -C $KDIR M=$PWD modules_install`은 `/lib/modules/$(KERNELRELEASE)/gandalf/`에 설치합니다.
설치 root와 external module subdirectory를 독립적으로 조정합니다.
Module Installation
===================
Modules which are included in the kernel are installed in the
directory:
/lib/modules/$(KERNELRELEASE)/kernel/
And external modules are installed in:
/lib/modules/$(KERNELRELEASE)/updates/
INSTALL_MOD_PATH
----------------
Above are the default directories but as always some level of
customization is possible. A prefix can be added to the
installation path using the variable INSTALL_MOD_PATH::
$ make INSTALL_MOD_PATH=/frodo modules_install
=> Install dir: /frodo/lib/modules/$(KERNELRELEASE)/kernel/
INSTALL_MOD_PATH may be set as an ordinary shell variable or,
as shown above, can be specified on the command line when
calling "make." This has effect when installing both in-tree
and out-of-tree modules.
INSTALL_MOD_DIR
---------------
External modules are by default installed to a directory under
/lib/modules/$(KERNELRELEASE)/updates/, but you may wish to
locate modules for a specific functionality in a separate
directory. For this purpose, use INSTALL_MOD_DIR to specify an
alternative name to "updates."::
$ make INSTALL_MOD_DIR=gandalf -C $KDIR \
M=$PWD modules_install
=> Install dir: /lib/modules/$(KERNELRELEASE)/gandalf/
Module versioning과 형식
388-445`CONFIG_MODVERSIONS`는 간단한 ABI 일관성 검사를 위한 module versioning을 활성화합니다. Exported symbol의 전체 prototype으로 CRC를 만들고, module load 시 kernel과 module의 CRC를 비교합니다. 값이 다르면 kernel은 module load를 거부합니다.
Kernel build가 생성하는 `Module.symvers`에는 vmlinux와 compile된 module의 모든 exported symbol과 해당 CRC가 기록됩니다. 한 행의 형식은 `<CRC> <Symbol> <Module> <Export Type> <Namespace>`이며 field는 tab으로 구분되고 namespace처럼 값이 비어 있을 수도 있습니다.
`CONFIG_MODVERSIONS`가 비활성화된 build에서는 CRC가 `0x00000000`입니다. `Module.symvers`는 exported symbol 전체 목록과 versioning이 활성화된 경우 각 CRC라는 두 정보를 제공합니다.
Exported symbol 한 행에 기록되는 정보입니다.
Exported symbol 정보는 `__ksymtab` 또는 `__ksymtab_gpl` section에 저장되고, symbol 이름과 namespace는 ELF string table과 비슷한 `__ksymtab_strings` 형식에 저장됩니다. `CONFIG_MODVERSIONS`가 켜지면 CRC는 `__kcrctab` 또는 `__kcrctab_gpl`에 추가됩니다.
기본인 `CONFIG_BASIC_MODVERSIONS` 방식에서는 import symbol의 이름과 CRC를 importing module의 `__versions` section에 저장합니다. 이 방식은 최대 64-byte symbol만 지원합니다.
`CONFIG_MODVERSIONS`와 `CONFIG_RUST`를 동시에 활성화하려면 `CONFIG_EXTENDED_MODVERSIONS`가 필요합니다. 이 방식은 null-terminated symbol 이름들을 `__version_ext_names`에 이어 붙이고, 대응 CRC를 `__version_ext_crcs`에 기록합니다.
Module Versioning
=================
Module versioning is enabled by the CONFIG_MODVERSIONS tag, and is used
as a simple ABI consistency check. A CRC value of the full prototype
for an exported symbol is created. When a module is loaded/used, the
CRC values contained in the kernel are compared with similar values in
the module; if they are not equal, the kernel refuses to load the
module.
Module.symvers contains a list of all exported symbols from a kernel
build.
Symbols From the Kernel (vmlinux + modules)
-------------------------------------------
During a kernel build, a file named Module.symvers will be
generated. Module.symvers contains all exported symbols from
the kernel and compiled modules. For each symbol, the
corresponding CRC value is also stored.
The syntax of the Module.symvers file is::
<CRC> <Symbol> <Module> <Export Type> <Namespace>
0xe1cc2a05 usb_stor_suspend drivers/usb/storage/usb-storage EXPORT_SYMBOL_GPL USB_STORAGE
The fields are separated by tabs and values may be empty (e.g.
if no namespace is defined for an exported symbol).
For a kernel build without CONFIG_MODVERSIONS enabled, the CRC
would read 0x00000000.
Module.symvers serves two purposes:
1) It lists all exported symbols from vmlinux and all modules.
2) It lists the CRC if CONFIG_MODVERSIONS is enabled.
Version Information Formats
---------------------------
Exported symbols have information stored in __ksymtab or __ksymtab_gpl
sections. Symbol names and namespaces are stored in __ksymtab_strings,
using a format similar to the string table used for ELF. If
CONFIG_MODVERSIONS is enabled, the CRCs corresponding to exported
symbols will be added to the __kcrctab or __kcrctab_gpl.
If CONFIG_BASIC_MODVERSIONS is enabled (default with
CONFIG_MODVERSIONS), imported symbols will have their symbol name and
CRC stored in the __versions section of the importing module. This
mode only supports symbols of length up to 64 bytes.
If CONFIG_EXTENDED_MODVERSIONS is enabled (required to enable both
CONFIG_MODVERSIONS and CONFIG_RUST at the same time), imported symbols
will have their symbol name recorded in the __version_ext_names
section as a series of concatenated, null-terminated strings. CRCs for
these symbols will be recorded in the __version_ext_crcs section.
External module 사이의 symbol
446-495External module build의 MODPOST 단계는 모든 외부 symbol이 정의되었는지 검사해야 하므로 kernel source tree의 `Module.symvers`를 읽습니다. MODPOST가 끝나면 해당 external module이 export하는 symbol을 담은 새 `Module.symvers`를 작성합니다.
Kernel과 external module의 symbol 정보를 합쳐 undefined symbol과 CRC를 확인합니다.
External module 하나가 다른 external module의 exported symbol을 사용할 때는 kbuild가 두 module의 symbol을 모두 알아야 undefined symbol warning을 피할 수 있습니다. 권장 방식은 공통 top-level Kbuild file을 사용하는 것입니다.
예를 들어 `foo.ko`가 `bar.ko`의 symbol을 사용하고 두 module이 `./foo/`, `./bar/`에 있다면 top-level file에 `obj-m := foo/ bar/`를 선언합니다. Top-level에서 `$ make -C $KDIR M=$PWD`를 실행하면 두 module을 한 build에서 처리하므로 서로의 symbol을 완전히 알 수 있습니다.
공통 top-level Kbuild를 만들기 어렵다면 build file의 `KBUILD_EXTRA_SYMBOLS`에 공백으로 구분한 추가 `Module.symvers` file 목록을 지정합니다. MODPOST가 초기 symbol table을 만들 때 이 file들을 읽습니다.
두 해결책 중 공통 top-level build가 권장됩니다.
Symbols and External Modules
----------------------------
When building an external module, the build system needs access
to the symbols from the kernel to check if all external symbols
are defined. This is done in the MODPOST step. modpost obtains
the symbols by reading Module.symvers from the kernel source
tree. During the MODPOST step, a new Module.symvers file will be
written containing all exported symbols from that external module.
Symbols From Another External Module
------------------------------------
Sometimes, an external module uses exported symbols from
another external module. Kbuild needs to have full knowledge of
all symbols to avoid spitting out warnings about undefined
symbols. Two solutions exist for this situation.
NOTE: The method with a top-level kbuild file is recommended
but may be impractical in certain situations.
Use a top-level kbuild file
If you have two modules, foo.ko and bar.ko, where
foo.ko needs symbols from bar.ko, you can use a
common top-level kbuild file so both modules are
compiled in the same build. Consider the following
directory layout::
./foo/ <= contains foo.ko
./bar/ <= contains bar.ko
The top-level kbuild file would then look like::
#./Kbuild (or ./Makefile):
obj-m := foo/ bar/
And executing::
$ make -C $KDIR M=$PWD
will then do the expected and compile both modules with
full knowledge of symbols from either module.
Use "make" variable KBUILD_EXTRA_SYMBOLS
If it is impractical to add a top-level kbuild file,
you can assign a space separated list
of files to KBUILD_EXTRA_SYMBOLS in your build file.
These files will be loaded by modpost during the
initialization of its symbol tables.
CONFIG option 활용
496-512Module은 특정 기능을 포함할지 결정하려고 `CONFIG_` option을 확인하는 경우가 많습니다. Kbuild에서는 `CONFIG_` variable을 직접 참조합니다.
Ext2 예제는 `obj-$(CONFIG_EXT2_FS) += ext2.o`로 filesystem module 또는 built-in object를 선택하고, 기본 object를 `ext2-y`에 나열합니다.
`ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o`는 XATTR option이 활성화된 경우에만 `xattr.o`를 composite `ext2.o`에 추가합니다. 이 패턴은 configuration 결과 `y`, `m`, 빈 값이 Kbuild goal에 직접 반영되는 전형적인 조건부 구성입니다.
Configuration 값이 module과 구성 object의 포함 여부를 결정합니다.
Tips & Tricks
=============
Testing for CONFIG_FOO_BAR
--------------------------
Modules often need to check for certain `CONFIG_` options to
decide if a specific feature is included in the module. In
kbuild this is done by referencing the `CONFIG_` variable
directly::
#fs/ext2/Makefile
obj-$(CONFIG_EXT2_FS) += ext2.o
ext2-y := balloc.o bitmap.o dir.o
ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o
요약·해설
modules.rst:1-512External module은 대상 kernel의 configuration·header·build artifact를 사용해야 하며 `M=`으로 module source 위치를 kbuild에 전달합니다. Linux 6.13부터 `-f`와 kernel Makefile 직접 include 방식도 사용할 수 있습니다.
Build file은 `obj-m`과 `<module>-y`로 module과 구성 object를 선언합니다. Wrapper Makefile은 편의 target을 제공하고, 큰 project에서는 kbuild 선언을 별도 `Kbuild` file로 분리하는 편이 명확합니다.
설치 path는 `INSTALL_MOD_PATH`와 `INSTALL_MOD_DIR`로 조정합니다. ABI versioning과 external module 간 symbol 의존성은 `Module.symvers`, MODPOST, 공통 top-level Kbuild 또는 `KBUILD_EXTRA_SYMBOLS`가 담당합니다.
Source 준비부터 설치와 symbol 연동까지의 핵심 단계입니다.