Build system
The following document briefly describes the steps and methodologies used for the new and improved Makefile system.
The Problem
The problem with the old Makefile system is that it was very difficult to
maintain and it lacked any sense of formal structure, thus developing for LTP
and including new targets was more difficult than it should have been
(maintenance). Furthermore, proper option-based cross-compilation was
impossible due to the fact that the Makefiles didn’t support a prefixing
system, and the appropriate implicit / static rules hadn’t been configured to
compile into multiple object directories for out-of-tree build support (ease of
use / functionality). Finally, there wasn’t a means to setup dependencies
between components, such that if a component required libltp.a
in order to
compile, it would go off and compile libltp.a
first (ease of use).
These items needed to be fixed to reduce maintenance nightmares for the development community contributing to LTP, and the project maintainers.
Design
The system was designed such that including a single GNU Makefile compatible set in each new directory component is all that’s essentially required to build the system.
Say you had a directory like the following (with .c
files in them which
directly tie into applications, e.g. baz.c -> baz):
.../foo/
|--> Makefile
|
--> bar/
|
--> Makefile
|
--> baz.c
# SPDX-License-Identifier: GPL-2.0-or-later
top_srcdir ?= ..
include $(top_srcdir)/include/mk/env_pre.mk
include $(top_srcdir)/include/mk/generic_trunk_target.mk
# SPDX-License-Identifier: GPL-2.0-or-later
top_srcdir ?= ../..
include $(top_srcdir)/include/mk/env_pre.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
Kernel Modules
Some of the tests need to build kernel modules, happily LTP has infrastructure for this.
ifneq ($(KERNELRELEASE),)
obj-m := module01.o
else
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
REQ_VERSION_MAJOR := 2
REQ_VERSION_PATCH := 6
MAKE_TARGETS := test01 test02 module01.ko
include $(top_srcdir)/include/mk/module.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
endif
This is a Makefile example that allows you to build kernel modules inside LTP.
The prerequisites for the build are detected by the configure
script.
The REQ_VERSION_MAJOR
and REQ_VERSION_PATCH
describe minimal kernel
version for which the build system tries to build the module.
The build system is also forward compatible with changes in Linux kernel internal API so that, if module fails to build, the failure is ignored both on build and installation. If the userspace counterpart of the test fails to load the module because the file does not exists, the test is skipped.
Note the ifneq($(KERNELRELEASE),)
. The reason it exists, it is that the
Makefile is executed twice: once by LTP build system and once by kernel kbuild,
see https://docs.kernel.org/kbuild/modules.html in the Linux kernel documentation for details
on external module build.
Make Rules and Make Variables
When using make rules, avoid writing ad hoc rules like:
[prog]: [dependencies]
cc -I../../include $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) \
-o [prog] [dependencies]
This makes cross-compilation and determinism difficult, if not impossible.
Besides, implicit rules are your friends and as long as you use MAKEOPTS=;
in the top-level caller (or do $(subst r,$(MAKEOPTS)
) to remove -r
),
the compile will complete successfully, assuming all other prerequisites have
been fulfilled (libraries, headers, etc).
Variable |
Explanation |
---|---|
$(AR) |
The library archiver |
$(CC) |
The system C compiler |
$(CCP) |
The system C preprocessor |
$(CFLAGS) |
C compiler flags |
$(CPPFLAGS) |
Preprocessor flags, e.g. |
$(DEBUG_CFLAGS) |
Debug flags to pass to |
$(KVM_LD) |
Special linker for wrapping KVM payload binaries into linkable object
files. Defaults to |
$(LD) |
The system linker (typically |
$(LDFLAGS) |
What to pass in to the linker, including |
$(LDLIBS) |
Libraries to pass to the linker (e.g. |
$(LTPLDLIBS) |
LTP internal libraries i.e. these in libs/ directory |
$(OPT_CFLAGS) |
Optimization flags to pass into the C compiler, Examples of more recent bugs: tree-optimization/17510 and tree-optimization/39100. Various bugs have occurred in the past due to buggy logic in the tree-optimization portion of the gcc compiler, from 3.3.x to 4.4. |
$(RANLIB) |
What to run after archiving a library |
$(WCFLAGS) |
Warning flags to pass to |
Make System Variables
A series of variables are used within the make system that direct what actions need to be taken. Rather than listing the variables here, please refer to the comments contained in include/mk/env_pre.mk.
Guidelines and Recommendations
Of course, GNU Make manual is the key to understand the Make system, but following manuals are probably the most important:
Warning
Rebuild from scratch before committing anything in the build system.