I can use the following command to create a Linux kernel .config file based on a specified architecture default for a custom ARM-based board:
ARCH=arm make defconfig KBUILD_DEFCONFIG=var_som_mx6_android_defconfig
I thought that this command more or less copies ./arch/arm/configs/var_som_mx6_android_defconfig to ./.config. However the resulting .config file isn't exactly a copy:
$ diff --unified arch/arm/configs/var_som_mx6_android_defconfig .config
--- arch/arm/configs/var_som_mx6_android_defconfig 2017-01-20 12:10:51.891515984 -0800
+++ .config 2017-01-26 15:31:29.000000000 -0800
## -407,6 +407,7 ##
CONFIG_ARM_ERRATA_751472=y
CONFIG_ARM_ERRATA_794072=y
CONFIG_ARM_ERRATA_761320=y
+CONFIG_ARM_ERRATA_845369=y
# CONFIG_ARM_ERRATA_753970 is not set
CONFIG_ARM_ERRATA_754322=y
# CONFIG_ARM_ERRATA_754327 is not set
## -2683,7 +2684,6 ##
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=y
# CONFIG_CUSE is not set
-CONFIG_AUFS_FS=y
#
# Caches
## -2759,6 +2759,21 ##
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+CONFIG_AUFS_FS=y
+CONFIG_AUFS_BRANCH_MAX_127=y
+# CONFIG_AUFS_BRANCH_MAX_511 is not set
+# CONFIG_AUFS_BRANCH_MAX_1023 is not set
+# CONFIG_AUFS_BRANCH_MAX_32767 is not set
+CONFIG_AUFS_SBILIST=y
+# CONFIG_AUFS_HNOTIFY is not set
+# CONFIG_AUFS_RDU is not set
+# CONFIG_AUFS_PROC_MAP is not set
+# CONFIG_AUFS_SP_IATTR is not set
+# CONFIG_AUFS_SHWH is not set
+# CONFIG_AUFS_BR_RAMFS is not set
+# CONFIG_AUFS_BR_FUSE is not set
+CONFIG_AUFS_BDEV_LOOP=y
+# CONFIG_AUFS_DEBUG is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
I don't understand where the extra lines are coming from, and I have always found the internal workings of the kernel configuration, makefiles, and build scripts to be difficult to understand. Can anyone explain where those lines in the .config might be coming from?
Motivation
The .config file is not simply copied from your defconfig file. The motivation for storing defconfig in such a format is next: in defconfig we can specify only options with non-default values (i.e. options we changed for our board). This way we can keep it small and clear. Every new kernel version brings a bunch of new options, and this way we don't need to update our defconfig file each time the kernel releases. Also, it should be mentioned that kernel build system keeps very specific order of options in defconfig file, so it's better to avoid modifying it by hand. Instead you should use make savedefconfig rule.
Simplified explanation
When .config file is being generated, kernel build system goes through all Kconfig files (from all subdirs), checking all options in those Kconfig files:
if option is mentioned in defconfig, build system puts that option into .config with value chosen in defconfig
if option isn't mentioned in defconfig, build system puts that option into .config using its default value, specified in corresponding Kconfig
Check scripts/kconfig/Makefile and scripts/kconfig/conf.c files to see how it's actually done.
More precise and detailed explanation
From "Kbuild: the Linux Kernel Build System" by Javier Martinez:
Defining Configuration Symbols: Kconfig Files
Configuration symbols are defined in files known as Kconfig files. Each Kconfig file can describe an arbitrary number of symbols and can also include (source) other Kconfig files. Compilation targets that construct configuration menus of kernel compile options, such as make menuconfig, read these files to build the tree-like structure. Every directory in the kernel has one Kconfig that includes the Kconfig files of its subdirectories. On top of the kernel source code directory, there is a Kconfig file that is the root of the options tree. The menuconfig (scripts/kconfig/mconf), gconfig (scripts/kconfig/gconf) and other compile targets invoke programs that start at this root Kconfig and recursively read the Kconfig files located in each subdirectory to build their menus. Which subdirectory to visit also is defined in each Kconfig file and also depends on the config symbol values chosen by the user.
Storing Symbol Values: .config File
All config symbol values are saved in a special file called .config. Every time you want to change a kernel compile configuration, you execute a make target, such as menuconfig or xconfig. These read the Kconfig files to create the menus and update the config symbols' values using the values defined in the .config file. Additionally, these tools update the .config file with the new options you chose and also can generate one if it didn't exist before.
Because the .config file is plain text, you also can change it without needing any specialized tool. It is very convenient for saving and restoring previous kernel compilation configurations as well.
Useful commands
You can use simpler syntax for make defconfig, like:
$ make ARCH=arm your_board_defconfig
See the full list of available defconfigs with:
$ make ARCH=arm help | grep defconfig
If you need to do reverse action (i.e. create a neat small defconfig from extensive .config), you can use savedefconfig rule:
$ make ARCH=arm savedefconfig
Also, as 0andriy mentioned, you can use diffconfig script to see changes from one .config to another one:
$ scripts/diffconfig .config_old .config_new
It also generates include/generated/autoconf.h.
This header file is included by C source files. On the other hand, .config is for the Makefile system.
The build system generates two files, and keeps them consistent.
Related
i'm working on a project requiring cmake. i'd like to add some custom rules to my makefile, but can't quite get my head around how to do it.
both c source files and header files are in the same directory. also in this same directory are a number of .def files, which are the sources for some of the header files #included in the source during compilation.
if i were to do this in a makefile, i'd use a simple rule like
.SUFFIXES: .def
.def.h:
$(PREPROC) $< > $#
how can i do this with cmake ??
i've tried various permutations of the following, both with and without cmake working directory specifications :
add_custom_command(
OUTPUT vvr_const.h
PRE_BUILD
COMMAND preproc vvr_const.def > vvr_const.h
DEPENDS vvr_const.def
)
add_custom_target(vvr_const.h DEPENDS vvr_const.def)
but the header file isn't generated by the time the c source file is compiled, so the compile fails. i've also tried a variation where i replace the last line above with
set_property(SOURCE main.c APPEND PROPERTY OBJECT_DEPENDS vvr_const.h)
in this case, the header file is correctly generated in advance, but make can't find it, and complains that there's no rule to make the target .h.
ideally this would be a general rule, like the make rule above, but i'm not opposed to making a separate rule for each of the .def files if that's what it takes.
cheers.
There are 2 problems with the add_custom_command approach you present:
You did not specify a working directory; by default the command is run in the build directory, not in the source directory.
You rely on shell functionality here (the redirect to a file). Even though this probably still works. You should go with an approach that does not rely on the shell.
To solve issues 1 and 2 I recommend creating a seperate cmake script file receiving the absolute paths to input and output files and using those in the custom command. This allows you to use execute_process to specify the file to write without relying on the platform.
preprocess_def.cmake
# preprocess def file
# parameters INPUT_FILE and OUTPUT_FILE denote the file to use as source
# and the file to write the results to respectively
# use preproc tool to get data to write to the output file
execute_process(COMMAND preproc "${INPUT_FILE}"
RESULT_VARIABLE _EXIT_CODE
OUTPUT_FILE "${OUTPUT_FILE}")
if (_EXIT_CODE)
message(FATAL_ERROR "An error occured when preprocessing the file ${INPUT_FILE}")
endif()
CMakeLists.txt
set(_INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.def")
set(_OUTPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.h")
# not necessary to use build event here, if we mark the output file as generated
add_custom_command(OUTPUT "${_OUTPUT_FILE}"
COMMAND "${CMAKE_BUILD_TOOL}" -D "OUPUT_FILE=${_OUTPUT_FILE}" -D "INPUT_FILE=${_INPUT_FILE}" -P "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_def.cmake"
DEPENDS "${_INPUT_FILE}")
add_executable(my_target vvr_const.h ...)
set_source_files_properties(vvr_const.h PROPERTIES GENERATED 1)
Documentation from cmake:
PRE_BUILD
On Visual Studio Generators, run before any other rules are executed within the target. On other generators, run just before PRE_LINK commands.
So possibly your command is just running too late.
U-boot being a bootloader targeted at different architecture and SoC's, there are several source files, and only some of them makes it to the final executable for a particular board. For example, in the arch/ directory, there is one directory per architecture. If the build is for an ARM architecture SoC, only some of the files in arch/arm/ will be compiled into the executable.
Which of the source files get compiled into the executable depends on the configuration of the build. This configuration is controlled by a file present in configs/ directory. In case of BeagleBone Black, this file is configs/am335x_boneblack_defconfig. This file defines several variables, which are used in Makefiles.
A part of the configs/am335x_defconfig is shown below:
CONFIG_ARM=y
CONFIG_ARCH_OMAP2PLUS=y
CONFIG_TI_COMMON_CMD_OPTIONS=y
CONFIG_AM33XX=y
CONFIG_DISTRO_DEFAULTS=y
The variables defined in these files are later referenced in other Makefiles. For example, the CONFIG_AM33XX variable defined above is referenced in /arch/arm/mach-omap2/am33xx/Makefile as shown below:
obj-$(CONFIG_AM33XX) += clock_am33xx.o
obj-$(CONFIG_TI814X) += clock_ti814x.o
obj-$(CONFIG_AM43XX) += clock_am43xx.o
ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX),)
obj-y += clock.o
endif
I guess while executing the command
$make am335x_boneblack_defconfig
the value of the variable CONFIG_AM33XX gets replaced in some transient copy of the Makefile, so that the content of the above makefile gets replaced by
obj-y += clock_am33xx.o
Figuring out which source files are included in the final executable just by searching for the config variables in all the Makefiles is a tedious task.
I need a way to create a list of source files which gets compiled for a particular config file automatically. Is there a way to do it?
Just do a clean build and search for all object files:
make mrproper
make foo_defconfig
make -j6
find . -name '*.o'
You probably want to exclude directories tools/ and scripts/.
KBUILD_DEFCONFIG_KMACHINE ?= defconfig_file does not work as I expected.
First lesson I learned: defconfig != .config
Bare-Kernel-Build (without yocto): A new defconfig file below arch/arm/config/xy_defconfig created by make savedefconfig is not equal to the .config file. I assume the linux kernel expand some symbols and create the final .config.
Yocto-Build: Here comes the issue: Yocto can not correctly handle the defconfig file below arch/arm/config/xy_defconfig. When building the linux-kernel with yocto.. the kernel is half size and not bootable. This results, because yocto does not expand the missing symbols in .config, which a make defconfig would do.
How do you handle the issue?
Update:
Figured out an additional make xy_defconfig do the trick and creates the correct .config file. It is a ugly hack, any better ideas are very welcome.
Added this to my custom linux-xy.bb file.
KBUILD_DEFCONFIG ?= xy_defconfig
do_makedefconfig() {
oe_runmake -C ${B} ARCH=${ARCH} $KBUILD_DEFCONFIG
}
addtask do_makedefconfig after do_configme before do_compile
First copy your defconfig to sources/meta-mylayer/recipes-kernel/linux
and write a .bbappend file for linux recipe
linux-ti_%.bbappend
FILESEXTRAPATHS_prepend : "${THISDIR}:"
SRC_URI += "file://your-defconfig"
2. open sources/meta-mylayer/conf/machine/your-machine.conf add below line,
search the macro if already present or nor using grep -inr "INTREE_DEFCONFIG"
INTREE_DEFCONFIG_pn-linux-ti = "am335x_phytec_defconfig"
if the macro already present in the same file replace defconfig name.
kernel-yocto approach
The KBUILD_DEFCONFIG variable is handled by kernel-yocto class, so you need to inherit it. It is usually done indirectly through include file linux-yocto.inc, so you should have this line you linux recipe:
require recipes-kernel/linux/linux-yocto.inc
Please note that KBUILD_DEFCONFIG_KMACHINE consists of two parts. The first one is variable name (KBUILD_DEFCONFIG) and the second one is kernel machine override (KMACHINE). So you need to change the override to fit your machine. That's why the KMACHINE part is written in italics in the documentation [1]. There is an example for RPi from the documentation:
KBUILD_DEFCONFIG_raspberrypi2 = "bcm2709_defconfig"
The KMACHINE is set in linux-yocto.inc to the MACHINE variable by default.
handle in-tree defconfig by hand
We are using in-tree defconfig without the kernel-yocto class. linux.inc from meta-oe layer is used. I don't know if this is a best practice. Here is our linux recipe (it is reduced to a bare minimum):
require recipes-kernel/linux/linux.inc
PV = "your_version"
SRC_URI = "your_sources"
do_configure_prepend() {
bbnote "Copying defconfig"
cp ${S}/arch/${ARCH}/configs/YOUR_defconfig ${WORKDIR}/defconfig
}
[1] https://www.yoctoproject.org/docs/2.4/mega-manual/mega-manual.html#var-KBUILD_DEFCONFIG
I understand there is an option to add compile-time macros/definitions to the Kconfig file that can be used in the code.
(For example, some definition of a constant, like a #define).
The Kconfig values are passed as Makefile defines. Also, all selected Kconfig values are put in a header file and passed to the assembler and 'C' code. So, you do not do this directly in the Kconfig file, but can do it in the Makefile or source.
Kconfig
config MY_DEFINE
bool "Select to get some DEFINE"
default y
help
This is a config define that is sent to both make
and defined in a config.h header.
Makefile
ifeq ($(CONFIG_MY_DEFINE),y)
KBUILD_CFLAGS += -DTHE_REAL_DEAL=1 # THE_REAL_DEAL now '1' in C files.
endif
Source
#ifdef CONFIG_MY_DEFINE
#define THE_REAL_DEAL 1
#endif
So, the Kconfig section defines the user interface information. The .config is makefile syntax, which is output by menuconfig, etc. This is sourced when you type make. Ie, all the stuff selected by menuconfig or another tool is available in Makefiles. The Kconfig variable has a CONFIG_ prefix added.
You can choose either the Makefile or the Source sections to get your define. If you want to select a range, then you can pass the value of CONFIG_MY_DEFINE to the compiler. Ie, including almost any kernel header will include config.h and the 'C' value CONFIG_MY_DEFINE will be set to whatever the user selected in the range.
See the kbuild wiki for more, which mainly references the kernel's kbuild documentation.
Say I have a header file which is included by many source files, maybe with a very deep hierarchy. It is very boring to list this common header file in the prerequisites of each source object, and not sure whether there is an elegant solution. Thanks!
You can generate such dependencies with gcc -M. From TFM:
-M Instead of outputting the result of preprocessing, output a rule suitable for make describing the dependencies of the main source file. The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from -include or -imacros command line options.
Also see Generating Prerequisites Automatically.