Definition of target in Linux kernel's Makefile - makefile

I'm about to build linux kernel. Before moving to the build step, I have to configure the linux kernel with the command as below
make menuconfig
I can not find any definition of menuconfig in ./Makefile. I also grep-ed in the repo to look for the definition of the target and found nothing. So how does make runs some targets relating to Configuring the kernel like menuconfig, oldconfig, etc.

The kernel build system makes heavy use of GNU Make features. In the top-level Makefile, the rule for the menuconfig target is this one:
%config: outputmakefile scripts_basic FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $#
That runs a sub-make for the target in "scripts/kconfig/Makefile". In "scripts/kconfig/Makefile", the rule for the menuconfig target is slightly obscured:
define config_rule
PHONY += $(1)
$(1): $(obj)/$($(1)-prog)
$(Q)$$< $(silent) $(Kconfig)
PHONY += build_$(1)
build_$(1): $(obj)/$($(1)-prog)
endef
$(foreach c, config menuconfig nconfig gconfig xconfig, $(eval $(call config_rule,$(c))))

Related

How to add multiple Headers files path in a Makefile?

I am trying to compile uleds.c driver and this driver includes multiple files existing under this path :
/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/src/kernel/include/linux
I want now to modify my Makefile and add this path so I can compile correctly uleds.c
This is my Makefile :
#CC=arm-poky-linux-gnueabi-gcc -march=armv7-a -marm -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a5 --sysroot=/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi
#CC="gcc"
obj-m += uleds.o
KERNEL_SOURCE := /opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/lib/modules/4.14.73-linux4sam-6.0-dirty
default:
${CC} ${KERNEL_SOURCE} uleds.c
clean:
${CC} $(INC) ${KERNEL_SOURCE} clean
Any suggestions for that ? Thank you
This appears to be an attempt at a kbuild file,.
You should not be manually compiling the file yourself using your default rule. Instead, you should be running the kernel's makefile, and have it compile the driver based on obj-m and friends.
Your makefile would look like so:
ifneq ($(KERNELRELEASE),)
ccflags-y += -I some/other/dir
obj-m += uleds.o
else
# default to build against running kernel if KDIR not
# specified:
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
endif
If you call make from the driver's directory, it will in turn call make from your kernel directory, which will know everything about the kernel and will be able to properly build your module.
Notice that by default, the built-in kernel's clean target will remove all generated *.[oas] files, so no need for a special clean target. Also, by default, the kernel's makefile will include its own include directories, so you likely don't need to do anything special for that. In case you do need to include from somewhere else, you can add a -I directive to the ccflags-y as shown in the example.
See Linux Kernel Makefiles and Building External Modules for details.
Simplest is:
${CC} -I/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/src/kernel/include/linux uleds.c
Try reading the following to get familiar with other GCC (compiler) options: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options

Re-evaluating GNU make makefile variable

I have inherited a large branched project? that requires a volatile set of .a archives $(LIB_FILES) to be included into link target, located in some directories $(LIB_DIRS). I can write an expression like this:
LIBDEP = $(foreach ldir, $(LIB_DIRS), \
$(filter $(addprefix %/, $(LIB_FILES)), $(wildcard $(ldir)/* )))
The problem is that they might not exist at moment of make's invocation and would be built by invoking $(MAKE) inside of another target's rule, which is a prerequisite to the link step.
The problem is actual list of files that should be created varies on external factors determined at their build steps, that I can't hard-code it properly, without turning makefile into a spaghetti mess and said variable is not re-evaluated at the moment of link command invocation.
I have suspicion that $(eval ) function can be used somehow, but manual is not very forthcoming as well as I didn't found examples of its use in this way.
Toolchain: GCC and binutils, make 3.81
Another solution is to create an explicit dependency of your make script on the output of the step which currently creates the variable $(LIB_FILES). This is what the manual is dealing with in the chapter How makefiles are remade and it aims at the technique which make is best at, namely deriving dependencies from the existence and timestamp of files (instead of variables). The following hopefully depicts your situation with the process of deducing a new set of libraries simulated by the two variables $(LIBS_THIS_TIME) and $(LIB_CONFIG_SET).
LIBS_THIS_TIME = foo.a:baz.a:bar.a
LIB_CONFIG_SET = $(subst :,_,$(LIBS_THIS_TIME))
include libdeps.d
linkstep:
#echo I am linking $^ now
touch $#
libdeps.d: $(LIB_CONFIG_SET)
-rm libdeps.d
$(foreach lib,$(subst :, ,$(LIBS_THIS_TIME)),echo linkstep: $(lib) >> libdeps.d;)
$(LIB_CONFIG_SET):
touch $#
If make finds that libdeps.d is not up to date to your current library configuration it is remade before make executes any other rule, although it is not the first target in the makefile. This way, if your build process creates a new or different set of libraries, libdeps.d would be remade first and only then make would carry on with the other targets in your top makefile, now with the correct dependecy information.
It sometimes happens that you need to invoke make several times in succession. One possibility to do this is to use conditionals:
ifeq ($(STEP),)
all:
<do-first-step>
$(MAKE) STEP=2 $#
else ifeq ($(STEP),2)
all:
<do-second-step>
$(MAKE) STEP=3 $#
else ifeq ($(STEP),3)
all:
<do-third-step>
endif
In each step you can generate new files and have them existing for the next step.

Need help in understanding Makefile for Kernel Module

I am a newbie in Kernel Development. I was trying to understand the following makefile for Hello World! program. But I am not able to figure it out completely.
obj-m += hello.o
all:
sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
I am not able to understand what is meant by 'obj-m += hello.o' . I know m here means module and thats it.
Also why are we not defining the dependencies of hello.o
And lastly I am not able to figure out completely the compiling rules defined under all: and clean:
Any help would be highly appreciated.!!
obj-m is a Makefile variable. It actually consists of 2 parts: 'obj' means that the referred target is a kernel object, while 'm' part means that the object is to be build like a module.
The variable is considered by kernel build rules. As kernel modules follow a certain convention, running your Makefile will result in creation of module hello.ko from source file hello.c (if everything works properly).
The 'obj' variable may take different suffixes as well. For example 'obj-y' will try to link the referred object into the main kernel image, instead of creating a module. The suffix may also refer to a kernel .config file variable, like this:
obj-$(CONFIG_HOTPLUG) += hotplug.o
In this case, if CONFIG_HOTPLUG is set to 'y' the hoplug object will be compiled into the main kernel; if set to 'm' then a separate hotplug.ko loadable module will be created. If not set to anything (resulting in 'obj-'), hotplug will be omitted outright.

How to handle different targets for same directories in parallel making

The question is about parallel making w/ GNU makefile.
Given a folder structure as below, the goal is to deliver a makefile that it supports make release/debug/clean in parallel.
project folder structure:
foo
+-foo1
+-foo2
+-foo3
The makefile may be sth like:
SUBDIR = foo1 foo2 foo3
.PHONY $(SUBDIR) release debug clean
release: $(SUBDIR)
$(SUBDIR):
$(MAKE) -C $# release
debug: $(SUBDIR)
#below is incorrect. $(SUBDIR) is overriden.
$(SUBDIR):
$(MAKE) -C $# debug
..
Sub directory list are set as phony targets for parallel making. but it lost the information of original target (release, debug, clean etc).
One method is to suffix the names for the directories and recover it in commands, but it is weird. another method might be to use variables, but not sure how to work it out.
The questions is:
How to write the rules for directories, that supports parallel making w/ different targets (release/debug/clean)?
Any hints are greatly appreciated.
Setting variables on the command line certainly works. You can also use MAKECMDGOALS (see the GNU make manual):
$(SUBDIR):
$(MAKE) -C $# $(MAKECMDGOALS)

making all rules depend on the Makefile itself

When I change a Makefile, its rules may have changed, so they should be reevaluated, but make doesn't seem to think so.
Is there any way to say, in a Makefile, that all of its targets, no matter which, depend on the Makefile itself?
(Regardless of its name.)
I'm using GNU make.
This looks like one more simple, useful, logical thing that Make should be able to do, but isn't.
Here is a workaround. If the clean rule is set up correctly, Make can execute it whenever the makefile has been altered, using an empty dummy file as a marker.
-include dummy
dummy: Makefile
#touch $#
#$(MAKE) -s clean
This will work for most targets, that is targets that are actual files and that are removed by clean, and any targets that depend on them. Side-effect targets and some PHONY targets will slip through the net.
Since GNU make version 4.3 it is now possible with the use of those two special variable:
.EXTRA_PREREQS
To add new prerequisite to every target
MAKEFILE_LIST
To get the path of the make file
To have every target depend on the current make file:
Put near the top of the file (before any include since it would affect the MAKEFILE_LIST) the following line:
.EXTRA_PREREQS:= $(abspath $(lastword $(MAKEFILE_LIST)))
To have every target depend on the current make file and also the make files which were included
Put the following line at the end of your file:
.EXTRA_PREREQS+=$(foreach mk, ${MAKEFILE_LIST},$(abspath ${mk}))
The only answer I know to this is to add makefile explicitly to the dependencies. For example,
%.o: %.c makefile
$(CC) $(CFLAGS) -c $<

Resources