Kbuild/Kconfig updates for 7.0

Kbuild changes
 ==============
 
 * Drop '*_probe' pattern from modpost section check allowlist, which hid
   legitimate warnings (Johan Hovold)
 
 * Disable -Wtype-limits altogether, instead of enabling at W=2 (Vincent
   Mailhol)
 
 * Improve UAPI testing to skip testing headers that require a libc when
   CONFIG_CC_CAN_LINK is not set, opening up testing of headers with no
   libc dependencies to more environments (Thomas Weißschuh)
 
 * Update gendwarfksyms documentation with required dependencies (Jihan
   LIN)
 
 * Reject invalid LLVM= values to avoid unintentionally falling back to
   system toolchain (Thomas Weißschuh)
 
 * Add a script to help run the kernel build process in a container for
   consistent environments and testing (Guillaume Tucker)
 
 * Simplify kallsyms by getting rid of the relative base (Ard Biesheuvel)
 
 * Performance and usability improvements to scripts/make_fit.py (Simon
   Glass)
 
 * Minor various clean ups and fixes
 
 Kconfig changes
 ===============
 
 * Move XPM icons to individual files, clearing up GTK deprecation
   warnings (Rostislav Krasny)
 
 * Support
 
     depends on FOO if BAR
 
   as syntactic sugar for
 
     depends on FOO || !BAR' (Nicolas Pitre, Graham Roff)
 
 * Refactor merge_config.sh to use awk over shell/sed/grep, dramatically
   speeding up processing large number of config fragments (Anders
   Roxell, Mikko Rapeli)
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQR74yXHMTGczQHYypIdayaRccAalgUCaYpgQwAKCRAdayaRccAa
 liOGAQCqMI42YMLqljFcPu3B/3f43xhDBCXAhquPBIMhbgt+aAEAmmo3uMLHKSRV
 XZDKkq13HMMV3Zlmrn5Xk/tzk+hkwwk=
 =WYl4
 -----END PGP SIGNATURE-----

Merge tag 'kbuild-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kbuild/linux

Pull Kbuild/Kconfig updates from Nathan Chancellor:
 "Kbuild:

   - Drop '*_probe' pattern from modpost section check allowlist, which
     hid legitimate warnings (Johan Hovold)

   - Disable -Wtype-limits altogether, instead of enabling at W=2
     (Vincent Mailhol)

   - Improve UAPI testing to skip testing headers that require a libc
     when CONFIG_CC_CAN_LINK is not set, opening up testing of headers
     with no libc dependencies to more environments (Thomas Weißschuh)

   - Update gendwarfksyms documentation with required dependencies
     (Jihan LIN)

   - Reject invalid LLVM= values to avoid unintentionally falling back
     to system toolchain (Thomas Weißschuh)

   - Add a script to help run the kernel build process in a container
     for consistent environments and testing (Guillaume Tucker)

   - Simplify kallsyms by getting rid of the relative base (Ard
     Biesheuvel)

   - Performance and usability improvements to scripts/make_fit.py
     (Simon Glass)

   - Minor various clean ups and fixes

  Kconfig:

   - Move XPM icons to individual files, clearing up GTK deprecation
     warnings (Rostislav Krasny)

   - Support

        depends on FOO if BAR

     as syntactic sugar for

        depends on FOO || !BAR

     (Nicolas Pitre, Graham Roff)

   - Refactor merge_config.sh to use awk over shell/sed/grep,
     dramatically speeding up processing large number of config
     fragments (Anders Roxell, Mikko Rapeli)"

* tag 'kbuild-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kbuild/linux: (39 commits)
  kbuild: remove dependency of run-command on config
  scripts/make_fit: Compress dtbs in parallel
  scripts/make_fit: Support a few more parallel compressors
  kbuild: Support a FIT_EXTRA_ARGS environment variable
  scripts/make_fit: Move dtb processing into a function
  scripts/make_fit: Support an initial ramdisk
  scripts/make_fit: Speed up operation
  rust: kconfig: Don't require RUST_IS_AVAILABLE for rustc-option
  MAINTAINERS: Add scripts/install.sh into Kbuild entry
  modpost: Amend ppc64 save/restfpr symnames for -Os build
  MIPS: tools: relocs: Ship a definition of R_MIPS_PC32
  streamline_config.pl: remove superfluous exclamation mark
  kbuild: dummy-tools: Add python3
  scripts: kconfig: merge_config.sh: warn on duplicate input files
  scripts: kconfig: merge_config.sh: use awk in checks too
  scripts: kconfig: merge_config.sh: refactor from shell/sed/grep to awk
  kallsyms: Get rid of kallsyms relative base
  mips: Add support for PC32 relocations in vmlinux
  Documentation: dev-tools: add container.rst page
  scripts: add tool to run containerized builds
  ...
This commit is contained in:
Linus Torvalds 2026-02-11 13:40:35 -08:00
commit 41f1a08645
63 changed files with 1516 additions and 627 deletions

View file

@ -73,8 +73,6 @@ rustc-llvm-version := $(shell,$(srctree)/scripts/rustc-llvm-version.sh $(RUSTC))
# $(rustc-option,<flag>)
# Return y if the Rust compiler supports <flag>, n otherwise
# Calls to this should be guarded so that they are not evaluated if
# CONFIG_RUST_IS_AVAILABLE is not set.
# If you are testing for unstable features, consider testing RUSTC_VERSION
# instead, as features may have different completeness while available.
rustc-option = $(success,trap "rm -rf .tmp_$$" EXIT; mkdir .tmp_$$; $(RUSTC) $(1) --crate-type=rlib /dev/null --out-dir=.tmp_$$ -o .tmp_$$/tmp.rlib)

View file

@ -410,7 +410,7 @@ FIT_COMPRESSION ?= gzip
quiet_cmd_fit = FIT $@
cmd_fit = $(MAKE_FIT) -o $@ --arch $(UIMAGE_ARCH) --os linux \
--name '$(UIMAGE_NAME)' \
--name '$(UIMAGE_NAME)' $(FIT_EXTRA_ARGS) \
$(if $(findstring 1,$(KBUILD_VERBOSE)),-v) \
$(if $(FIT_DECOMPOSE_DTBS),--decompose-dtbs) \
--compress $(FIT_COMPRESSION) -k $< @$(word 2,$^)

View file

@ -201,7 +201,6 @@ quiet_cmd_cpio = CPIO $@
cmd_cpio = $(CONFIG_SHELL) $(srctree)/usr/gen_initramfs.sh -o $@ $<
modules-$(KERNELRELEASE)-$(ARCH).cpio: .tmp_modules_cpio
$(Q)$(MAKE) $(build)=usr usr/gen_init_cpio
$(call cmd,cpio)
PHONY += modules-cpio-pkg

View file

@ -16,7 +16,7 @@ KBUILD_CFLAGS += -Werror=return-type
KBUILD_CFLAGS += -Werror=strict-prototypes
KBUILD_CFLAGS += -Wno-format-security
KBUILD_CFLAGS += -Wno-trigraphs
KBUILD_CFLAGS += $(call cc-option, -Wno-frame-address)
KBUILD_CFLAGS += -Wno-frame-address
KBUILD_CFLAGS += $(call cc-option, -Wno-address-of-packed-member)
KBUILD_CFLAGS += -Wmissing-declarations
KBUILD_CFLAGS += -Wmissing-prototypes
@ -55,6 +55,9 @@ else
KBUILD_CFLAGS += -Wno-main
endif
# Too noisy on range checks and in macros handling both signed and unsigned.
KBUILD_CFLAGS += -Wno-type-limits
# These result in bogus false positives
KBUILD_CFLAGS += $(call cc-option, -Wno-dangling-pointer)
@ -72,7 +75,7 @@ KBUILD_CFLAGS += -Wno-pointer-sign
# In order to make sure new function cast mismatches are not introduced
# in the kernel (to avoid tripping CFI checking), the kernel should be
# globally built with -Wcast-function-type.
KBUILD_CFLAGS += $(call cc-option, -Wcast-function-type)
KBUILD_CFLAGS += -Wcast-function-type
# Currently, disable -Wstringop-overflow for GCC 11, globally.
KBUILD_CFLAGS-$(CONFIG_CC_NO_STRINGOP_OVERFLOW) += $(call cc-option, -Wno-stringop-overflow)
@ -99,7 +102,7 @@ KBUILD_CFLAGS += $(KBUILD_CFLAGS-y) $(CONFIG_CC_IMPLICIT_FALLTHROUGH)
KBUILD_CFLAGS += -Werror=date-time
# enforce correct pointer usage
KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types)
KBUILD_CFLAGS += -Werror=incompatible-pointer-types
# Require designated initializers for all marked structures
KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init)
@ -116,7 +119,7 @@ ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
KBUILD_CFLAGS += -Wmissing-format-attribute
KBUILD_CFLAGS += -Wmissing-include-dirs
KBUILD_CFLAGS += $(call cc-option, -Wunused-const-variable)
KBUILD_CFLAGS += -Wunused-const-variable
KBUILD_CPPFLAGS += -Wundef
KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1
@ -125,12 +128,12 @@ else
# Some diagnostics enabled by default are noisy.
# Suppress them by using -Wno... except for W=1.
KBUILD_CFLAGS += $(call cc-option, -Wno-unused-but-set-variable)
KBUILD_CFLAGS += $(call cc-option, -Wno-unused-const-variable)
KBUILD_CFLAGS += -Wno-unused-but-set-variable
KBUILD_CFLAGS += -Wno-unused-const-variable
KBUILD_CFLAGS += $(call cc-option, -Wno-packed-not-aligned)
KBUILD_CFLAGS += $(call cc-option, -Wno-format-overflow)
ifdef CONFIG_CC_IS_GCC
KBUILD_CFLAGS += $(call cc-option, -Wno-format-truncation)
KBUILD_CFLAGS += -Wno-format-truncation
endif
KBUILD_CFLAGS += $(call cc-option, -Wno-stringop-truncation)
@ -145,14 +148,11 @@ KBUILD_CFLAGS += -Wno-format
# problematic.
KBUILD_CFLAGS += -Wformat-extra-args -Wformat-invalid-specifier
KBUILD_CFLAGS += -Wformat-zero-length -Wnonnull
# Requires clang-12+.
ifeq ($(call clang-min-version, 120000),y)
KBUILD_CFLAGS += -Wformat-insufficient-args
endif
endif
KBUILD_CFLAGS += $(call cc-option, -Wno-pointer-to-enum-cast)
KBUILD_CFLAGS += -Wno-pointer-to-enum-cast
KBUILD_CFLAGS += -Wno-tautological-constant-out-of-range-compare
KBUILD_CFLAGS += $(call cc-option, -Wno-unaligned-access)
KBUILD_CFLAGS += -Wno-unaligned-access
KBUILD_CFLAGS += -Wno-enum-compare-conditional
endif
@ -166,7 +166,7 @@ ifneq ($(findstring 2, $(KBUILD_EXTRA_WARN)),)
KBUILD_CFLAGS += -Wdisabled-optimization
KBUILD_CFLAGS += -Wshadow
KBUILD_CFLAGS += $(call cc-option, -Wlogical-op)
KBUILD_CFLAGS += $(call cc-option, -Wunused-macros)
KBUILD_CFLAGS += -Wunused-macros
KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN2
@ -174,7 +174,6 @@ else
# The following turn off the warnings enabled by -Wextra
KBUILD_CFLAGS += -Wno-missing-field-initializers
KBUILD_CFLAGS += -Wno-type-limits
KBUILD_CFLAGS += -Wno-shift-negative-value
ifdef CONFIG_CC_IS_CLANG

199
scripts/container Executable file
View file

@ -0,0 +1,199 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2025 Guillaume Tucker
"""Containerized builds"""
import abc
import argparse
import logging
import os
import pathlib
import shutil
import subprocess
import sys
import uuid
class ContainerRuntime(abc.ABC):
"""Base class for a container runtime implementation"""
name = None # Property defined in each implementation class
def __init__(self, args, logger):
self._uid = args.uid or os.getuid()
self._gid = args.gid or args.uid or os.getgid()
self._env_file = args.env_file
self._shell = args.shell
self._logger = logger
@classmethod
def is_present(cls):
"""Determine whether the runtime is present on the system"""
return shutil.which(cls.name) is not None
@abc.abstractmethod
def _do_run(self, image, cmd, container_name):
"""Runtime-specific handler to run a command in a container"""
@abc.abstractmethod
def _do_abort(self, container_name):
"""Runtime-specific handler to abort a running container"""
def run(self, image, cmd):
"""Run a command in a runtime container"""
container_name = str(uuid.uuid4())
self._logger.debug("container: %s", container_name)
try:
return self._do_run(image, cmd, container_name)
except KeyboardInterrupt:
self._logger.error("user aborted")
self._do_abort(container_name)
return 1
class CommonRuntime(ContainerRuntime):
"""Common logic for Docker and Podman"""
def _do_run(self, image, cmd, container_name):
cmdline = [self.name, 'run']
cmdline += self._get_opts(container_name)
cmdline.append(image)
cmdline += cmd
self._logger.debug('command: %s', ' '.join(cmdline))
return subprocess.call(cmdline)
def _get_opts(self, container_name):
opts = [
'--name', container_name,
'--rm',
'--volume', f'{pathlib.Path.cwd()}:/src',
'--workdir', '/src',
]
if self._env_file:
opts += ['--env-file', self._env_file]
if self._shell:
opts += ['--interactive', '--tty']
return opts
def _do_abort(self, container_name):
subprocess.call([self.name, 'kill', container_name])
class DockerRuntime(CommonRuntime):
"""Run a command in a Docker container"""
name = 'docker'
def _get_opts(self, container_name):
return super()._get_opts(container_name) + [
'--user', f'{self._uid}:{self._gid}'
]
class PodmanRuntime(CommonRuntime):
"""Run a command in a Podman container"""
name = 'podman'
def _get_opts(self, container_name):
return super()._get_opts(container_name) + [
'--userns', f'keep-id:uid={self._uid},gid={self._gid}',
]
class Runtimes:
"""List of all supported runtimes"""
runtimes = [PodmanRuntime, DockerRuntime]
@classmethod
def get_names(cls):
"""Get a list of all the runtime names"""
return list(runtime.name for runtime in cls.runtimes)
@classmethod
def get(cls, name):
"""Get a single runtime class matching the given name"""
for runtime in cls.runtimes:
if runtime.name == name:
if not runtime.is_present():
raise ValueError(f"runtime not found: {name}")
return runtime
raise ValueError(f"unknown runtime: {name}")
@classmethod
def find(cls):
"""Find the first runtime present on the system"""
for runtime in cls.runtimes:
if runtime.is_present():
return runtime
raise ValueError("no runtime found")
def _get_logger(verbose):
"""Set up a logger with the appropriate level"""
logger = logging.getLogger('container')
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(
fmt='[container {levelname}] {message}', style='{'
))
logger.addHandler(handler)
logger.setLevel(logging.DEBUG if verbose is True else logging.INFO)
return logger
def main(args):
"""Main entry point for the container tool"""
logger = _get_logger(args.verbose)
try:
cls = Runtimes.get(args.runtime) if args.runtime else Runtimes.find()
except ValueError as ex:
logger.error(ex)
return 1
logger.debug("runtime: %s", cls.name)
logger.debug("image: %s", args.image)
return cls(args, logger).run(args.image, args.cmd)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
'container',
description="See the documentation for more details: "
"https://docs.kernel.org/dev-tools/container.html"
)
parser.add_argument(
'-e', '--env-file',
help="Path to an environment file to load in the container."
)
parser.add_argument(
'-g', '--gid',
help="Group ID to use inside the container."
)
parser.add_argument(
'-i', '--image', required=True,
help="Container image name."
)
parser.add_argument(
'-r', '--runtime', choices=Runtimes.get_names(),
help="Container runtime name. If not specified, the first one found "
"on the system will be used i.e. Podman if present, otherwise Docker."
)
parser.add_argument(
'-s', '--shell', action='store_true',
help="Run the container in an interactive shell."
)
parser.add_argument(
'-u', '--uid',
help="User ID to use inside the container. If the -g option is not "
"specified, the user ID will also be set as the group ID."
)
parser.add_argument(
'-v', '--verbose', action='store_true',
help="Enable verbose output."
)
parser.add_argument(
'cmd', nargs='+',
help="Command to run in the container"
)
sys.exit(main(parser.parse_args(sys.argv[1:])))

4
scripts/dummy-tools/python3 Executable file
View file

@ -0,0 +1,4 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
true

View file

@ -46,7 +46,6 @@ struct addr_range {
};
static unsigned long long _text;
static unsigned long long relative_base;
static struct addr_range text_ranges[] = {
{ "_stext", "_etext" },
{ "_sinittext", "_einittext" },
@ -57,6 +56,7 @@ static struct addr_range text_ranges[] = {
static struct sym_entry **table;
static unsigned int table_size, table_cnt;
static int all_symbols;
static int pc_relative;
static int token_profit[0x10000];
@ -280,7 +280,7 @@ static void read_map(const char *in)
static void output_label(const char *label)
{
printf(".globl %s\n", label);
printf("\tALGN\n");
printf("\t.balign 4\n");
printf("%s:\n", label);
}
@ -343,15 +343,6 @@ static void write_src(void)
unsigned int *markers, markers_cnt;
char buf[KSYM_NAME_LEN];
printf("#include <asm/bitsperlong.h>\n");
printf("#if BITS_PER_LONG == 64\n");
printf("#define PTR .quad\n");
printf("#define ALGN .balign 8\n");
printf("#else\n");
printf("#define PTR .long\n");
printf("#define ALGN .balign 4\n");
printf("#endif\n");
printf("\t.section .rodata, \"a\"\n");
output_label("kallsyms_num_syms");
@ -434,34 +425,24 @@ static void write_src(void)
output_label("kallsyms_offsets");
for (i = 0; i < table_cnt; i++) {
/*
* Use the offset relative to the lowest value
* encountered of all relative symbols, and emit
* non-relocatable fixed offsets that will be fixed
* up at runtime.
*/
if (pc_relative) {
long long offset = table[i]->addr - _text;
long long offset;
offset = table[i]->addr - relative_base;
if (offset < 0 || offset > UINT_MAX) {
fprintf(stderr, "kallsyms failure: "
"relative symbol value %#llx out of range\n",
table[i]->addr);
exit(EXIT_FAILURE);
if (offset < INT_MIN || offset > INT_MAX) {
fprintf(stderr, "kallsyms failure: "
"relative symbol value %#llx out of range\n",
table[i]->addr);
exit(EXIT_FAILURE);
}
printf("\t.long\t_text - . + (%d)\t/* %s */\n",
(int)offset, table[i]->sym);
} else {
printf("\t.long\t%#x\t/* %s */\n",
(unsigned int)table[i]->addr, table[i]->sym);
}
printf("\t.long\t%#x\t/* %s */\n", (int)offset, table[i]->sym);
}
printf("\n");
output_label("kallsyms_relative_base");
/* Provide proper symbols relocatability by their '_text' relativeness. */
if (_text <= relative_base)
printf("\tPTR\t_text + %#llx\n", relative_base - _text);
else
printf("\tPTR\t_text - %#llx\n", _text - relative_base);
printf("\n");
sort_symbols_by_name();
output_label("kallsyms_seqs_of_names");
for (i = 0; i < table_cnt; i++)
@ -701,22 +682,12 @@ static void sort_symbols(void)
qsort(table, table_cnt, sizeof(table[0]), compare_symbols);
}
/* find the minimum non-absolute symbol address */
static void record_relative_base(void)
{
/*
* The table is sorted by address.
* Take the first symbol value.
*/
if (table_cnt)
relative_base = table[0]->addr;
}
int main(int argc, char **argv)
{
while (1) {
static const struct option long_options[] = {
{"all-symbols", no_argument, &all_symbols, 1},
{"pc-relative", no_argument, &pc_relative, 1},
{},
};
@ -734,7 +705,6 @@ int main(int argc, char **argv)
read_map(argv[optind]);
shrink_table();
sort_symbols();
record_relative_base();
optimize_token_table();
write_src();

View file

@ -201,7 +201,7 @@ $(addprefix $(obj)/, mconf.o $(lxdialog)): | $(obj)/mconf-cflags
# qconf: Used for the xconfig target based on Qt
hostprogs += qconf
qconf-cxxobjs := qconf.o qconf-moc.o
qconf-objs := images.o $(common-objs)
qconf-objs := $(common-objs)
HOSTLDLIBS_qconf = $(call read-file, $(obj)/qconf-libs)
HOSTCXXFLAGS_qconf.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags)
@ -219,7 +219,7 @@ targets += qconf-moc.cc
# gconf: Used for the gconfig target based on GTK+
hostprogs += gconf
gconf-objs := gconf.o images.o $(common-objs)
gconf-objs := gconf.o $(common-objs)
HOSTLDLIBS_gconf = $(call read-file, $(obj)/gconf-libs)
HOSTCFLAGS_gconf.o = $(call read-file, $(obj)/gconf-cflags)

View file

@ -5,7 +5,6 @@
#include <stdlib.h>
#include "lkc.h"
#include "images.h"
#include <gtk/gtk.h>
@ -951,12 +950,24 @@ static void fixup_rootmenu(struct menu *menu)
}
/* Main Window Initialization */
static void replace_button_icon(GtkWidget *widget, const char * const xpm[])
static void replace_button_icon(GtkWidget *widget, const char *filename)
{
GdkPixbuf *pixbuf;
GtkWidget *image;
GError *err = NULL;
char *env = getenv(SRCTREE);
gchar *path = g_strconcat(env ? env : g_get_current_dir(), "/scripts/kconfig/icons/", filename, NULL);
pixbuf = gdk_pixbuf_new_from_file(path, &err);
g_free(path);
if (err) {
g_warning("Failed to load icon %s: %s", filename, err->message);
g_error_free(err);
return;
}
pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)xpm);
image = gtk_image_new_from_pixbuf(pixbuf);
g_object_unref(pixbuf);
@ -1078,17 +1089,17 @@ static void init_main_window(const gchar *glade_file)
single_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button4"));
g_signal_connect(single_btn, "clicked",
G_CALLBACK(on_single_clicked), NULL);
replace_button_icon(single_btn, xpm_single_view);
replace_button_icon(single_btn, "single_view.xpm");
split_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button5"));
g_signal_connect(split_btn, "clicked",
G_CALLBACK(on_split_clicked), NULL);
replace_button_icon(split_btn, xpm_split_view);
replace_button_icon(split_btn, "split_view.xpm");
full_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button6"));
g_signal_connect(full_btn, "clicked",
G_CALLBACK(on_full_clicked), NULL);
replace_button_icon(full_btn, xpm_tree_view);
replace_button_icon(full_btn, "tree_view.xpm");
widget = GTK_WIDGET(gtk_builder_get_object(builder, "button7"));
g_signal_connect(widget, "clicked",
@ -1269,7 +1280,17 @@ static void init_right_tree(void)
g_signal_connect(G_OBJECT(renderer), "edited",
G_CALLBACK(renderer_edited), tree2_w);
pix_menu = gdk_pixbuf_new_from_xpm_data((const char **)xpm_menu);
char *env = getenv(SRCTREE);
gchar *path = g_strconcat(env ? env : g_get_current_dir(), "/scripts/kconfig/icons/menu.xpm", NULL);
GError *err = NULL;
pix_menu = gdk_pixbuf_new_from_file(path, &err);
g_free(path);
if (err) {
g_warning("Failed to load menu icon: %s", err->message);
g_error_free(err);
}
for (i = 0; i < COL_VALUE; i++) {
column = gtk_tree_view_get_column(view, i);

View file

@ -0,0 +1,29 @@
/* XPM */
static char * back_xpm[] = {
"22 22 3 1",
". c None",
"# c #000083",
"a c #838183",
"......................",
"......................",
"......................",
"......................",
"......................",
"...........######a....",
"..#......##########...",
"..##...####......##a..",
"..###.###.........##..",
"..######..........##..",
"..#####...........##..",
"..######..........##..",
"..#######.........##..",
"..########.......##a..",
"...............a###...",
"...............###....",
"......................",
"......................",
"......................",
"......................",
"......................",
"......................"
};

View file

@ -0,0 +1,18 @@
/* XPM */
static char * choice_no_xpm[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .... ",
" .. .. ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" .. .. ",
" .... ",
" "
};

View file

@ -0,0 +1,18 @@
/* XPM */
static char * choice_yes_xpm[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .... ",
" .. .. ",
" . . ",
" . .. . ",
" . .... . ",
" . .... . ",
" . .. . ",
" . . ",
" .. .. ",
" .... ",
" "
};

View file

@ -0,0 +1,31 @@
/* XPM */
static char * load_xpm[] = {
"22 22 5 1",
". c None",
"# c #000000",
"c c #838100",
"a c #ffff00",
"b c #ffffff",
"......................",
"......................",
"......................",
"............####....#.",
"...........#....##.##.",
"..................###.",
".................####.",
".####...........#####.",
"#abab##########.......",
"#babababababab#.......",
"#ababababababa#.......",
"#babababababab#.......",
"#ababab###############",
"#babab##cccccccccccc##",
"#abab##cccccccccccc##.",
"#bab##cccccccccccc##..",
"#ab##cccccccccccc##...",
"#b##cccccccccccc##....",
"###cccccccccccc##.....",
"##cccccccccccc##......",
"###############.......",
"......................"
};

View file

@ -0,0 +1,18 @@
/* XPM */
static char * menu_xpm[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . .. . ",
" . .... . ",
" . ...... . ",
" . ...... . ",
" . .... . ",
" . .. . ",
" . . ",
" .......... ",
" "
};

View file

@ -0,0 +1,18 @@
/* XPM */
static char * menuback_xpm[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . .. . ",
" . .... . ",
" . ...... . ",
" . ...... . ",
" . .... . ",
" . .. . ",
" . . ",
" .......... ",
" "
};

View file

@ -0,0 +1,31 @@
/* XPM */
static char * save_xpm[] = {
"22 22 5 1",
". c None",
"# c #000000",
"a c #838100",
"b c #c5c2c5",
"c c #cdb6d5",
"......................",
".####################.",
".#aa#bbbbbbbbbbbb#bb#.",
".#aa#bbbbbbbbbbbb#bb#.",
".#aa#bbbbbbbbbcbb####.",
".#aa#bbbccbbbbbbb#aa#.",
".#aa#bbbccbbbbbbb#aa#.",
".#aa#bbbbbbbbbbbb#aa#.",
".#aa#bbbbbbbbbbbb#aa#.",
".#aa#bbbbbbbbbbbb#aa#.",
".#aa#bbbbbbbbbbbb#aa#.",
".#aaa############aaa#.",
".#aaaaaaaaaaaaaaaaaa#.",
".#aaaaaaaaaaaaaaaaaa#.",
".#aaa#############aa#.",
".#aaa#########bbb#aa#.",
".#aaa#########bbb#aa#.",
".#aaa#########bbb#aa#.",
".#aaa#########bbb#aa#.",
".#aaa#########bbb#aa#.",
"..##################..",
"......................"
};

View file

@ -0,0 +1,28 @@
/* XPM */
static char * single_view_xpm[] = {
"22 22 2 1",
". c None",
"# c #000000",
"......................",
"......................",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"......................",
"......................"
};

View file

@ -0,0 +1,28 @@
/* XPM */
static char * split_view_xpm[] = {
"22 22 2 1",
". c None",
"# c #000000",
"......................",
"......................",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......................",
"......................"
};

View file

@ -0,0 +1,18 @@
/* XPM */
static char * symbol_mod_xpm[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . . ",
" . .. . ",
" . .... . ",
" . .... . ",
" . .. . ",
" . . ",
" . . ",
" .......... ",
" "
};

View file

@ -0,0 +1,18 @@
/* XPM */
static char * symbol_no_xpm[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" .......... ",
" "
};

View file

@ -0,0 +1,18 @@
/* XPM */
static char * symbol_yes_xpm[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . . ",
" . . . ",
" . .. . ",
" . . .. . ",
" . .... . ",
" . .. . ",
" . . ",
" .......... ",
" "
};

View file

@ -0,0 +1,28 @@
/* XPM */
static char * tree_view_xpm[] = {
"22 22 2 1",
". c None",
"# c #000000",
"......................",
"......................",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......########........",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......########........",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......########........",
"......................",
"......................"
};

View file

@ -1,328 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
*/
#include "images.h"
const char * const xpm_load[] = {
"22 22 5 1",
". c None",
"# c #000000",
"c c #838100",
"a c #ffff00",
"b c #ffffff",
"......................",
"......................",
"......................",
"............####....#.",
"...........#....##.##.",
"..................###.",
".................####.",
".####...........#####.",
"#abab##########.......",
"#babababababab#.......",
"#ababababababa#.......",
"#babababababab#.......",
"#ababab###############",
"#babab##cccccccccccc##",
"#abab##cccccccccccc##.",
"#bab##cccccccccccc##..",
"#ab##cccccccccccc##...",
"#b##cccccccccccc##....",
"###cccccccccccc##.....",
"##cccccccccccc##......",
"###############.......",
"......................"};
const char * const xpm_save[] = {
"22 22 5 1",
". c None",
"# c #000000",
"a c #838100",
"b c #c5c2c5",
"c c #cdb6d5",
"......................",
".####################.",
".#aa#bbbbbbbbbbbb#bb#.",
".#aa#bbbbbbbbbbbb#bb#.",
".#aa#bbbbbbbbbcbb####.",
".#aa#bbbccbbbbbbb#aa#.",
".#aa#bbbccbbbbbbb#aa#.",
".#aa#bbbbbbbbbbbb#aa#.",
".#aa#bbbbbbbbbbbb#aa#.",
".#aa#bbbbbbbbbbbb#aa#.",
".#aa#bbbbbbbbbbbb#aa#.",
".#aaa############aaa#.",
".#aaaaaaaaaaaaaaaaaa#.",
".#aaaaaaaaaaaaaaaaaa#.",
".#aaa#############aa#.",
".#aaa#########bbb#aa#.",
".#aaa#########bbb#aa#.",
".#aaa#########bbb#aa#.",
".#aaa#########bbb#aa#.",
".#aaa#########bbb#aa#.",
"..##################..",
"......................"};
const char * const xpm_back[] = {
"22 22 3 1",
". c None",
"# c #000083",
"a c #838183",
"......................",
"......................",
"......................",
"......................",
"......................",
"...........######a....",
"..#......##########...",
"..##...####......##a..",
"..###.###.........##..",
"..######..........##..",
"..#####...........##..",
"..######..........##..",
"..#######.........##..",
"..########.......##a..",
"...............a###...",
"...............###....",
"......................",
"......................",
"......................",
"......................",
"......................",
"......................"};
const char * const xpm_tree_view[] = {
"22 22 2 1",
". c None",
"# c #000000",
"......................",
"......................",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......########........",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......########........",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......#...............",
"......########........",
"......................",
"......................"};
const char * const xpm_single_view[] = {
"22 22 2 1",
". c None",
"# c #000000",
"......................",
"......................",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"..........#...........",
"......................",
"......................"};
const char * const xpm_split_view[] = {
"22 22 2 1",
". c None",
"# c #000000",
"......................",
"......................",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......#......#........",
"......................",
"......................"};
const char * const xpm_symbol_no[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" .......... ",
" "};
const char * const xpm_symbol_mod[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . . ",
" . .. . ",
" . .... . ",
" . .... . ",
" . .. . ",
" . . ",
" . . ",
" .......... ",
" "};
const char * const xpm_symbol_yes[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . . ",
" . . . ",
" . .. . ",
" . . .. . ",
" . .... . ",
" . .. . ",
" . . ",
" .......... ",
" "};
const char * const xpm_choice_no[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .... ",
" .. .. ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" . . ",
" .. .. ",
" .... ",
" "};
const char * const xpm_choice_yes[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .... ",
" .. .. ",
" . . ",
" . .. . ",
" . .... . ",
" . .... . ",
" . .. . ",
" . . ",
" .. .. ",
" .... ",
" "};
const char * const xpm_menu[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . .. . ",
" . .... . ",
" . ...... . ",
" . ...... . ",
" . .... . ",
" . .. . ",
" . . ",
" .......... ",
" "};
const char * const xpm_menu_inv[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" .......... ",
" .. ...... ",
" .. .... ",
" .. .. ",
" .. .. ",
" .. .... ",
" .. ...... ",
" .......... ",
" .......... ",
" "};
const char * const xpm_menuback[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" .......... ",
" . . ",
" . .. . ",
" . .... . ",
" . ...... . ",
" . ...... . ",
" . .... . ",
" . .. . ",
" . . ",
" .......... ",
" "};
const char * const xpm_void[] = {
"12 12 2 1",
" c white",
". c black",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};

View file

@ -1,33 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
*/
#ifndef IMAGES_H
#define IMAGES_H
#ifdef __cplusplus
extern "C" {
#endif
extern const char * const xpm_load[];
extern const char * const xpm_save[];
extern const char * const xpm_back[];
extern const char * const xpm_tree_view[];
extern const char * const xpm_single_view[];
extern const char * const xpm_split_view[];
extern const char * const xpm_symbol_no[];
extern const char * const xpm_symbol_mod[];
extern const char * const xpm_symbol_yes[];
extern const char * const xpm_choice_no[];
extern const char * const xpm_choice_yes[];
extern const char * const xpm_menu[];
extern const char * const xpm_menu_inv[];
extern const char * const xpm_menuback[];
extern const char * const xpm_void[];
#ifdef __cplusplus
}
#endif
#endif /* IMAGES_H */

View file

@ -82,7 +82,7 @@ void menu_warn(const struct menu *menu, const char *fmt, ...);
struct menu *menu_add_menu(void);
void menu_end_menu(void);
void menu_add_entry(struct symbol *sym, enum menu_type type);
void menu_add_dep(struct expr *dep);
void menu_add_dep(struct expr *dep, struct expr *cond);
void menu_add_visibility(struct expr *dep);
struct property *menu_add_prompt(enum prop_type type, const char *prompt,
struct expr *dep);

View file

@ -127,8 +127,18 @@ static struct expr *rewrite_m(struct expr *e)
return e;
}
void menu_add_dep(struct expr *dep)
void menu_add_dep(struct expr *dep, struct expr *cond)
{
if (cond) {
/*
* We have "depends on X if Y" and we want:
* Y != n --> X
* Y == n --> y
* That simplifies to: (X || (Y == n))
*/
dep = expr_alloc_or(dep,
expr_trans_compare(cond, E_EQUAL, &symbol_no));
}
current_entry->dep = expr_alloc_and(current_entry->dep, dep);
}

View file

@ -16,8 +16,8 @@
set -e
clean_up() {
rm -f $TMP_FILE
rm -f $MERGE_FILE
rm -f "$TMP_FILE"
rm -f "$TMP_FILE.new"
}
usage() {
@ -43,6 +43,10 @@ STRICT=false
CONFIG_PREFIX=${CONFIG_-CONFIG_}
WARNOVERRIDE=echo
if [ -z "$AWK" ]; then
AWK=awk
fi
while true; do
case $1 in
"-n")
@ -117,11 +121,8 @@ if [ ! -r "$INITFILE" ]; then
fi
MERGE_LIST=$*
SED_CONFIG_EXP1="s/^\(${CONFIG_PREFIX}[a-zA-Z0-9_]*\)=.*/\1/p"
SED_CONFIG_EXP2="s/^# \(${CONFIG_PREFIX}[a-zA-Z0-9_]*\) is not set$/\1/p"
TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
MERGE_FILE=$(mktemp ./.merge_tmp.config.XXXXXXXXXX)
echo "Using $INITFILE as base"
@ -129,6 +130,8 @@ trap clean_up EXIT
cat $INITFILE > $TMP_FILE
PROCESSED_FILES=""
# Merge files, printing warnings on overridden values
for ORIG_MERGE_FILE in $MERGE_LIST ; do
echo "Merging $ORIG_MERGE_FILE"
@ -136,42 +139,138 @@ for ORIG_MERGE_FILE in $MERGE_LIST ; do
echo "The merge file '$ORIG_MERGE_FILE' does not exist. Exit." >&2
exit 1
fi
cat $ORIG_MERGE_FILE > $MERGE_FILE
CFG_LIST=$(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $MERGE_FILE)
for CFG in $CFG_LIST ; do
grep -q -w $CFG $TMP_FILE || continue
PREV_VAL=$(grep -w $CFG $TMP_FILE)
NEW_VAL=$(grep -w $CFG $MERGE_FILE)
BUILTIN_FLAG=false
if [ "$BUILTIN" = "true" ] && [ "${NEW_VAL#CONFIG_*=}" = "m" ] && [ "${PREV_VAL#CONFIG_*=}" = "y" ]; then
${WARNOVERRIDE} Previous value: $PREV_VAL
${WARNOVERRIDE} New value: $NEW_VAL
${WARNOVERRIDE} -y passed, will not demote y to m
${WARNOVERRIDE}
BUILTIN_FLAG=true
elif [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
${WARNOVERRIDE} Value of $CFG is redefined by fragment $ORIG_MERGE_FILE:
${WARNOVERRIDE} Previous value: $PREV_VAL
${WARNOVERRIDE} New value: $NEW_VAL
${WARNOVERRIDE}
if [ "$STRICT" = "true" ]; then
STRICT_MODE_VIOLATED=true
fi
elif [ "$WARNREDUN" = "true" ]; then
${WARNOVERRIDE} Value of $CFG is redundant by fragment $ORIG_MERGE_FILE:
fi
if [ "$BUILTIN_FLAG" = "false" ]; then
sed -i "/$CFG[ =]/d" $TMP_FILE
else
sed -i "/$CFG[ =]/d" $MERGE_FILE
fi
done
# In case the previous file lacks a new line at the end
echo >> $TMP_FILE
cat $MERGE_FILE >> $TMP_FILE
# Check for duplicate input files
case " $PROCESSED_FILES " in
*" $ORIG_MERGE_FILE "*)
${WARNOVERRIDE} "WARNING: Input file provided multiple times: $ORIG_MERGE_FILE"
;;
esac
# Use awk for single-pass processing instead of per-symbol grep/sed
if ! "$AWK" -v prefix="$CONFIG_PREFIX" \
-v warnoverride="$WARNOVERRIDE" \
-v strict="$STRICT" \
-v builtin="$BUILTIN" \
-v warnredun="$WARNREDUN" '
BEGIN {
strict_violated = 0
cfg_regex = "^" prefix "[a-zA-Z0-9_]+"
notset_regex = "^# " prefix "[a-zA-Z0-9_]+ is not set$"
}
# Extract config name from a line, returns "" if not a config line
function get_cfg(line) {
if (match(line, cfg_regex)) {
return substr(line, RSTART, RLENGTH)
} else if (match(line, notset_regex)) {
# Extract CONFIG_FOO from "# CONFIG_FOO is not set"
sub(/^# /, "", line)
sub(/ is not set$/, "", line)
return line
}
return ""
}
function warn_builtin(cfg, prev, new) {
if (warnoverride == "true") return
print cfg ": -y passed, will not demote y to m"
print "Previous value: " prev
print "New value: " new
print ""
}
function warn_redefined(cfg, prev, new) {
if (warnoverride == "true") return
print "Value of " cfg " is redefined by fragment " mergefile ":"
print "Previous value: " prev
print "New value: " new
print ""
}
function warn_redundant(cfg) {
if (warnredun != "true" || warnoverride == "true") return
print "Value of " cfg " is redundant by fragment " mergefile ":"
}
# First pass: read merge file, store all lines and index
FILENAME == ARGV[1] {
mergefile = FILENAME
merge_lines[FNR] = $0
merge_total = FNR
cfg = get_cfg($0)
if (cfg != "") {
merge_cfg[cfg] = $0
merge_cfg_line[cfg] = FNR
}
next
}
# Second pass: process base file (TMP_FILE)
FILENAME == ARGV[2] {
cfg = get_cfg($0)
# Not a config or not in merge file - keep it
if (cfg == "" || !(cfg in merge_cfg)) {
print $0 >> ARGV[3]
next
}
prev_val = $0
new_val = merge_cfg[cfg]
# BUILTIN: do not demote y to m
if (builtin == "true" && new_val ~ /=m$/ && prev_val ~ /=y$/) {
warn_builtin(cfg, prev_val, new_val)
print $0 >> ARGV[3]
skip_merge[merge_cfg_line[cfg]] = 1
next
}
# Values equal - redundant
if (prev_val == new_val) {
warn_redundant(cfg)
next
}
# "=n" is the same as "is not set"
if (prev_val ~ /=n$/ && new_val ~ / is not set$/) {
print $0 >> ARGV[3]
next
}
# Values differ - redefined
warn_redefined(cfg, prev_val, new_val)
if (strict == "true") {
strict_violated = 1
}
}
# output file, skip all lines
FILENAME == ARGV[3] {
nextfile
}
END {
# Newline in case base file lacks trailing newline
print "" >> ARGV[3]
# Append merge file, skipping lines marked for builtin preservation
for (i = 1; i <= merge_total; i++) {
if (!(i in skip_merge)) {
print merge_lines[i] >> ARGV[3]
}
}
if (strict_violated) {
exit 1
}
}' \
"$ORIG_MERGE_FILE" "$TMP_FILE" "$TMP_FILE.new"; then
# awk exited non-zero, strict mode was violated
STRICT_MODE_VIOLATED=true
fi
mv "$TMP_FILE.new" "$TMP_FILE"
PROCESSED_FILES="$PROCESSED_FILES $ORIG_MERGE_FILE"
done
if [ "$STRICT_MODE_VIOLATED" = "true" ]; then
echo "The fragment redefined a value and strict mode had been passed."
exit 1
@ -198,16 +297,91 @@ fi
# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set
make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET
# Check all specified config values took effect (might have missed-dependency issues)
if ! "$AWK" -v prefix="$CONFIG_PREFIX" \
-v warnoverride="$WARNOVERRIDE" \
-v strict="$STRICT" \
-v warnredun="$WARNREDUN" '
BEGIN {
strict_violated = 0
cfg_regex = "^" prefix "[a-zA-Z0-9_]+"
notset_regex = "^# " prefix "[a-zA-Z0-9_]+ is not set$"
}
# Check all specified config values took (might have missed-dependency issues)
for CFG in $(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $TMP_FILE); do
# Extract config name from a line, returns "" if not a config line
function get_cfg(line) {
if (match(line, cfg_regex)) {
return substr(line, RSTART, RLENGTH)
} else if (match(line, notset_regex)) {
# Extract CONFIG_FOO from "# CONFIG_FOO is not set"
sub(/^# /, "", line)
sub(/ is not set$/, "", line)
return line
}
return ""
}
REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG" || true)
if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
echo "Value requested for $CFG not in final .config"
echo "Requested value: $REQUESTED_VAL"
echo "Actual value: $ACTUAL_VAL"
echo ""
fi
done
function warn_mismatch(cfg, merged, final) {
if (warnredun == "true") return
if (final == "" && !(merged ~ / is not set$/ || merged ~ /=n$/)) {
print "WARNING: Value requested for " cfg " not in final .config"
print "Requested value: " merged
print "Actual value: " final
} else if (final == "" && merged ~ / is not set$/) {
# not set, pass
} else if (merged == "" && final != "") {
print "WARNING: " cfg " not in merged config but added in final .config:"
print "Requested value: " merged
print "Actual value: " final
} else {
print "WARNING: " cfg " differs:"
print "Requested value: " merged
print "Actual value: " final
}
}
# First pass: read effective config file, store all lines
FILENAME == ARGV[1] {
cfg = get_cfg($0)
if (cfg != "") {
config_cfg[cfg] = $0
}
next
}
# Second pass: process merged config and compare against effective config
{
cfg = get_cfg($0)
if (cfg == "") next
# strip trailing comment
sub(/[[:space:]]+#.*/, "", $0)
merged_val = $0
final_val = config_cfg[cfg]
if (merged_val == final_val) next
if (merged_val ~ /=n$/ && final_val ~ / is not set$/) next
if (merged_val ~ /=n$/ && final_val == "") next
warn_mismatch(cfg, merged_val, final_val)
if (strict == "true") {
strict_violated = 1
}
}
END {
if (strict_violated) {
exit 1
}
}' \
"$KCONFIG_CONFIG" "$TMP_FILE"; then
# awk exited non-zero, strict mode was violated
STRICT_MODE_VIOLATED=true
fi
if [ "$STRICT" == "true" ] && [ "$STRICT_MODE_VIOLATED" == "true" ]; then
echo "Requested and effective config differ"
exit 1
fi

View file

@ -323,7 +323,7 @@ if_entry: T_IF expr T_EOL
{
printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno);
menu_add_entry(NULL, M_IF);
menu_add_dep($2);
menu_add_dep($2, NULL);
$$ = menu_add_menu();
};
@ -422,9 +422,9 @@ help: help_start T_HELPTEXT
/* depends option */
depends: T_DEPENDS T_ON expr T_EOL
depends: T_DEPENDS T_ON expr if_expr T_EOL
{
menu_add_dep($3);
menu_add_dep($3, $4);
printd(DEBUG_PARSE, "%s:%d:depends on\n", cur_filename, cur_lineno);
};

View file

@ -26,8 +26,6 @@
#include "lkc.h"
#include "qconf.h"
#include "images.h"
static QApplication *configApp;
static ConfigSettings *configSettings;
@ -1283,13 +1281,14 @@ ConfigMainWindow::ConfigMainWindow(void)
move(x.toInt(), y.toInt());
// set up icons
ConfigItem::symbolYesIcon = QIcon(QPixmap(xpm_symbol_yes));
ConfigItem::symbolModIcon = QIcon(QPixmap(xpm_symbol_mod));
ConfigItem::symbolNoIcon = QIcon(QPixmap(xpm_symbol_no));
ConfigItem::choiceYesIcon = QIcon(QPixmap(xpm_choice_yes));
ConfigItem::choiceNoIcon = QIcon(QPixmap(xpm_choice_no));
ConfigItem::menuIcon = QIcon(QPixmap(xpm_menu));
ConfigItem::menubackIcon = QIcon(QPixmap(xpm_menuback));
QString iconsDir = QString(getenv(SRCTREE) ? getenv(SRCTREE) : QDir::currentPath()) + "/scripts/kconfig/icons/";
ConfigItem::symbolYesIcon = QIcon(QPixmap(iconsDir + "symbol_yes.xpm"));
ConfigItem::symbolModIcon = QIcon(QPixmap(iconsDir + "symbol_mod.xpm"));
ConfigItem::symbolNoIcon = QIcon(QPixmap(iconsDir + "symbol_no.xpm"));
ConfigItem::choiceYesIcon = QIcon(QPixmap(iconsDir + "choice_yes.xpm"));
ConfigItem::choiceNoIcon = QIcon(QPixmap(iconsDir + "choice_no.xpm"));
ConfigItem::menuIcon = QIcon(QPixmap(iconsDir + "menu.xpm"));
ConfigItem::menubackIcon = QIcon(QPixmap(iconsDir + "menuback.xpm"));
QWidget *widget = new QWidget(this);
setCentralWidget(widget);
@ -1312,7 +1311,7 @@ ConfigMainWindow::ConfigMainWindow(void)
configList->setFocus();
backAction = new QAction(QPixmap(xpm_back), "Back", this);
backAction = new QAction(QPixmap(iconsDir + "back.xpm"), "Back", this);
backAction->setShortcut(QKeySequence::Back);
connect(backAction, &QAction::triggered,
this, &ConfigMainWindow::goBack);
@ -1322,12 +1321,12 @@ ConfigMainWindow::ConfigMainWindow(void)
connect(quitAction, &QAction::triggered,
this, &ConfigMainWindow::close);
QAction *loadAction = new QAction(QPixmap(xpm_load), "&Open", this);
QAction *loadAction = new QAction(QPixmap(iconsDir + "load.xpm"), "&Open", this);
loadAction->setShortcut(QKeySequence::Open);
connect(loadAction, &QAction::triggered,
this, &ConfigMainWindow::loadConfig);
saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
saveAction = new QAction(QPixmap(iconsDir + "save.xpm"), "&Save", this);
saveAction->setShortcut(QKeySequence::Save);
connect(saveAction, &QAction::triggered,
this, &ConfigMainWindow::saveConfig);
@ -1344,15 +1343,15 @@ ConfigMainWindow::ConfigMainWindow(void)
searchAction->setShortcut(QKeySequence::Find);
connect(searchAction, &QAction::triggered,
this, &ConfigMainWindow::searchConfig);
singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
singleViewAction = new QAction(QPixmap(iconsDir + "single_view.xpm"), "Single View", this);
singleViewAction->setCheckable(true);
connect(singleViewAction, &QAction::triggered,
this, &ConfigMainWindow::showSingleView);
splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
splitViewAction = new QAction(QPixmap(iconsDir + "split_view.xpm"), "Split View", this);
splitViewAction->setCheckable(true);
connect(splitViewAction, &QAction::triggered,
this, &ConfigMainWindow::showSplitView);
fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
fullViewAction = new QAction(QPixmap(iconsDir + "tree_view.xpm"), "Full View", this);
fullViewAction->setCheckable(true);
connect(fullViewAction, &QAction::triggered,
this, &ConfigMainWindow::showFullView);

View file

@ -415,7 +415,7 @@ foreach my $module (keys(%modules)) {
}
} else {
# Most likely, someone has a custom (binary?) module loaded.
print STDERR "$module config not found!!\n";
print STDERR "$module config not found!\n";
}
}

View file

@ -0,0 +1,32 @@
# SPDX-License-Identifier: GPL-2.0
# Test Kconfig file for conditional dependencies.
# Enable module support for tristate testing
config MODULES
bool "Enable loadable module support"
modules
default y
config FOO
bool "FOO symbol"
config BAR
bool "BAR symbol"
config TEST_BASIC
bool "Test basic conditional dependency"
depends on FOO if BAR
default y
config TEST_COMPLEX
bool "Test complex conditional dependency"
depends on (FOO && BAR) if (FOO || BAR)
default y
config BAZ
tristate "BAZ symbol"
config TEST_OPTIONAL
tristate "Test simple optional dependency"
depends on BAZ if BAZ
default y

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0
"""
Correctly handle conditional dependencies.
"""
def test(conf):
assert conf.oldconfig('test_config1') == 0
assert conf.config_matches('expected_config1')
assert conf.oldconfig('test_config2') == 0
assert conf.config_matches('expected_config2')
assert conf.oldconfig('test_config3') == 0
assert conf.config_matches('expected_config3')

View file

@ -0,0 +1,11 @@
#
# Automatically generated file; DO NOT EDIT.
# Main menu
#
CONFIG_MODULES=y
CONFIG_FOO=y
CONFIG_BAR=y
CONFIG_TEST_BASIC=y
CONFIG_TEST_COMPLEX=y
CONFIG_BAZ=m
CONFIG_TEST_OPTIONAL=m

View file

@ -0,0 +1,9 @@
#
# Automatically generated file; DO NOT EDIT.
# Main menu
#
CONFIG_MODULES=y
# CONFIG_FOO is not set
CONFIG_BAR=y
CONFIG_BAZ=y
CONFIG_TEST_OPTIONAL=y

View file

@ -0,0 +1,11 @@
#
# Automatically generated file; DO NOT EDIT.
# Main menu
#
CONFIG_MODULES=y
# CONFIG_FOO is not set
# CONFIG_BAR is not set
CONFIG_TEST_BASIC=y
CONFIG_TEST_COMPLEX=y
# CONFIG_BAZ is not set
CONFIG_TEST_OPTIONAL=y

View file

@ -0,0 +1,6 @@
# Basic check that everything can be configured if selected.
CONFIG_FOO=y
CONFIG_BAR=y
CONFIG_BAZ=m
# Ensure that TEST_OPTIONAL=y with BAZ=m is converted to TEST_OPTIONAL=m
CONFIG_TEST_OPTIONAL=y

View file

@ -0,0 +1,7 @@
# If FOO is not selected, then TEST_BASIC should fail the conditional
# dependency since BAR is set.
# TEST_COMPLEX will fail dependency as it depends on both FOO and BAR
# if either of those is selected.
CONFIG_FOO=n
CONFIG_BAR=y
CONFIG_BAZ=y

View file

@ -0,0 +1,6 @@
# If FOO is not selected, but BAR is also not selected, then TEST_BASIC
# should pass since the dependency on FOO is conditional on BAR.
# TEST_COMPLEX should be also set since neither FOO nor BAR are selected
# so it has no dependencies.
CONFIG_FOO=n
CONFIG_BAR=n

View file

@ -115,6 +115,10 @@ kallsyms()
kallsymopt="${kallsymopt} --all-symbols"
fi
if is_enabled CONFIG_64BIT || is_enabled CONFIG_RELOCATABLE; then
kallsymopt="${kallsymopt} --pc-relative"
fi
info KSYMS "${2}.S"
scripts/kallsyms ${kallsymopt} "${1}" > "${2}.S"

View file

@ -10,10 +10,14 @@
Usage:
make_fit.py -A arm64 -n 'Linux-6.6' -O linux
-o arch/arm64/boot/image.fit -k /tmp/kern/arch/arm64/boot/image.itk
@arch/arm64/boot/dts/dtbs-list -E -c gzip
-r /boot/initrd.img-6.14.0-27-generic @arch/arm64/boot/dts/dtbs-list
-E -c gzip
Creates a FIT containing the supplied kernel and a set of devicetree files,
either specified individually or listed in a file (with an '@' prefix).
Creates a FIT containing the supplied kernel, an optional ramdisk, and a set of
devicetree files, either specified individually or listed in a file (with an
'@' prefix).
Use -r to specify an existing ramdisk/initrd file.
Use -E to generate an external FIT (where the data is placed after the
FIT data structure). This allows parsing of the data without loading
@ -29,12 +33,11 @@ looks at the .cmd files produced by the kernel build.
The resulting FIT can be booted by bootloaders which support FIT, such
as U-Boot, Linuxboot, Tianocore, etc.
Note that this tool does not yet support adding a ramdisk / initrd.
"""
import argparse
import collections
import multiprocessing
import os
import subprocess
import sys
@ -48,11 +51,12 @@ import libfdt
CompTool = collections.namedtuple('CompTool', 'ext,tools')
COMP_TOOLS = {
'bzip2': CompTool('.bz2', 'bzip2'),
'bzip2': CompTool('.bz2', 'pbzip2,bzip2'),
'gzip': CompTool('.gz', 'pigz,gzip'),
'lz4': CompTool('.lz4', 'lz4'),
'lzma': CompTool('.lzma', 'lzma'),
'lzma': CompTool('.lzma', 'plzip,lzma'),
'lzo': CompTool('.lzo', 'lzop'),
'xz': CompTool('.xz', 'xz'),
'zstd': CompTool('.zstd', 'zstd'),
}
@ -81,6 +85,8 @@ def parse_args():
help='Specifies the operating system')
parser.add_argument('-k', '--kernel', type=str, required=True,
help='Specifies the (uncompressed) kernel input file (.itk)')
parser.add_argument('-r', '--ramdisk', type=str,
help='Specifies the ramdisk/initrd input file')
parser.add_argument('-v', '--verbose', action='store_true',
help='Enable verbose output')
parser.add_argument('dtbs', type=str, nargs='*',
@ -98,7 +104,7 @@ def setup_fit(fsw, name):
fsw (libfdt.FdtSw): Object to use for writing
name (str): Name of kernel image
"""
fsw.INC_SIZE = 65536
fsw.INC_SIZE = 16 << 20
fsw.finish_reservemap()
fsw.begin_node('')
fsw.property_string('description', f'{name} with devicetree set')
@ -133,7 +139,28 @@ def write_kernel(fsw, data, args):
fsw.property_u32('entry', 0)
def finish_fit(fsw, entries):
def write_ramdisk(fsw, data, args):
"""Write out the ramdisk image
Writes a ramdisk node along with the required properties
Args:
fsw (libfdt.FdtSw): Object to use for writing
data (bytes): Data to write (possibly compressed)
args (Namespace): Contains necessary strings:
arch: FIT architecture, e.g. 'arm64'
fit_os: Operating Systems, e.g. 'linux'
"""
with fsw.add_node('ramdisk'):
fsw.property_string('description', 'Ramdisk')
fsw.property_string('type', 'ramdisk')
fsw.property_string('arch', args.arch)
fsw.property_string('compression', 'none')
fsw.property_string('os', args.os)
fsw.property('data', data)
def finish_fit(fsw, entries, has_ramdisk=False):
"""Finish the FIT ready for use
Writes the /configurations node and subnodes
@ -143,6 +170,7 @@ def finish_fit(fsw, entries):
entries (list of tuple): List of configurations:
str: Description of model
str: Compatible stringlist
has_ramdisk (bool): True if a ramdisk is included in the FIT
"""
fsw.end_node()
seq = 0
@ -154,6 +182,8 @@ def finish_fit(fsw, entries):
fsw.property_string('description', model)
fsw.property('fdt', bytes(''.join(f'fdt-{x}\x00' for x in files), "ascii"))
fsw.property_string('kernel', 'kernel')
if has_ramdisk:
fsw.property_string('ramdisk', 'ramdisk')
fsw.end_node()
@ -179,7 +209,12 @@ def compress_data(inf, compress):
done = False
for tool in comp.tools.split(','):
try:
subprocess.call([tool, '-c'], stdin=inf, stdout=outf)
# Add parallel flags for tools that support them
cmd = [tool]
if tool in ('zstd', 'xz'):
cmd.extend(['-T0']) # Use all available cores
cmd.append('-c')
subprocess.call(cmd, stdin=inf, stdout=outf)
done = True
break
except FileNotFoundError:
@ -191,15 +226,31 @@ def compress_data(inf, compress):
return comp_data
def output_dtb(fsw, seq, fname, arch, compress):
def compress_dtb(fname, compress):
"""Compress a single DTB file
Args:
fname (str): Filename containing the DTB
compress (str): Compression algorithm, e.g. 'gzip'
Returns:
tuple: (str: fname, bytes: compressed_data)
"""
with open(fname, 'rb') as inf:
compressed = compress_data(inf, compress)
return fname, compressed
def output_dtb(fsw, seq, fname, arch, compress, data=None):
"""Write out a single devicetree to the FIT
Args:
fsw (libfdt.FdtSw): Object to use for writing
seq (int): Sequence number (1 for first)
fname (str): Filename containing the DTB
arch: FIT architecture, e.g. 'arm64'
arch (str): FIT architecture, e.g. 'arm64'
compress (str): Compressed algorithm, e.g. 'gzip'
data (bytes): Pre-compressed data (optional)
"""
with fsw.add_node(f'fdt-{seq}'):
fsw.property_string('description', os.path.basename(fname))
@ -207,9 +258,10 @@ def output_dtb(fsw, seq, fname, arch, compress):
fsw.property_string('arch', arch)
fsw.property_string('compression', compress)
with open(fname, 'rb') as inf:
compressed = compress_data(inf, compress)
fsw.property('data', compressed)
if data is None:
with open(fname, 'rb') as inf:
data = compress_data(inf, compress)
fsw.property('data', data)
def process_dtb(fname, args):
@ -249,6 +301,73 @@ def process_dtb(fname, args):
return (model, compat, files)
def _process_dtbs(args, fsw, entries, fdts):
"""Process all DTB files and add them to the FIT
Args:
args: Program arguments
fsw: FIT writer object
entries: List to append entries to
fdts: Dictionary of processed DTBs
Returns:
tuple:
Number of files processed
Total size of files processed
"""
seq = 0
size = 0
# First figure out the unique DTB files that need compression
todo = []
file_info = [] # List of (fname, model, compat, files) tuples
for fname in args.dtbs:
# Ignore non-DTB (*.dtb) files
if os.path.splitext(fname)[1] != '.dtb':
continue
try:
(model, compat, files) = process_dtb(fname, args)
except Exception as e:
sys.stderr.write(f'Error processing {fname}:\n')
raise e
file_info.append((fname, model, compat, files))
for fn in files:
if fn not in fdts and fn not in todo:
todo.append(fn)
# Compress all DTBs in parallel
cache = {}
if todo and args.compress != 'none':
if args.verbose:
print(f'Compressing {len(todo)} DTBs...')
with multiprocessing.Pool() as pool:
compress_args = [(fn, args.compress) for fn in todo]
# unpacks each tuple, calls compress_dtb(fn, compress) in parallel
results = pool.starmap(compress_dtb, compress_args)
cache = dict(results)
# Now write all DTBs to the FIT using pre-compressed data
for fname, model, compat, files in file_info:
for fn in files:
if fn not in fdts:
seq += 1
size += os.path.getsize(fn)
output_dtb(fsw, seq, fn, args.arch, args.compress,
cache.get(fn))
fdts[fn] = seq
files_seq = [fdts[fn] for fn in files]
entries.append([model, compat, files_seq])
return seq, size
def build_fit(args):
"""Build the FIT from the provided files and arguments
@ -261,7 +380,6 @@ def build_fit(args):
int: Number of configurations generated
size: Total uncompressed size of data
"""
seq = 0
size = 0
fsw = libfdt.FdtSw()
setup_fit(fsw, args.name)
@ -274,32 +392,23 @@ def build_fit(args):
size += os.path.getsize(args.kernel)
write_kernel(fsw, comp_data, args)
for fname in args.dtbs:
# Ignore non-DTB (*.dtb) files
if os.path.splitext(fname)[1] != '.dtb':
continue
# Handle the ramdisk if provided. Compression is not supported as it is
# already compressed.
if args.ramdisk:
with open(args.ramdisk, 'rb') as inf:
data = inf.read()
size += len(data)
write_ramdisk(fsw, data, args)
try:
(model, compat, files) = process_dtb(fname, args)
except Exception as e:
sys.stderr.write(f"Error processing {fname}:\n")
raise e
count, fdt_size = _process_dtbs(args, fsw, entries, fdts)
size += fdt_size
for fn in files:
if fn not in fdts:
seq += 1
size += os.path.getsize(fn)
output_dtb(fsw, seq, fn, args.arch, args.compress)
fdts[fn] = seq
files_seq = [fdts[fn] for fn in files]
entries.append([model, compat, files_seq])
finish_fit(fsw, entries)
finish_fit(fsw, entries, bool(args.ramdisk))
# Include the kernel itself in the returned file count
return fsw.as_fdt().as_bytearray(), seq + 1, size
fdt = fsw.as_fdt()
fdt.pack()
return fdt.as_bytearray(), count + 1 + bool(args.ramdisk), size
def run_make_fit():

View file

@ -602,6 +602,10 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
/* Special register function linked on all modules during final link of .ko */
if (strstarts(symname, "_restgpr0_") ||
strstarts(symname, "_savegpr0_") ||
strstarts(symname, "_restgpr1_") ||
strstarts(symname, "_savegpr1_") ||
strstarts(symname, "_restfpr_") ||
strstarts(symname, "_savefpr_") ||
strstarts(symname, "_restvr_") ||
strstarts(symname, "_savevr_") ||
strcmp(symname, ".TOC.") == 0)
@ -958,7 +962,7 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
/* symbols in data sections that may refer to any init/exit sections */
if (match(fromsec, PATTERNS(DATA_SECTIONS)) &&
match(tosec, PATTERNS(ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS)) &&
match(fromsym, PATTERNS("*_ops", "*_probe", "*_console")))
match(fromsym, PATTERNS("*_ops", "*_console")))
return 0;
/* Check for pattern 3 */