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

Pull Kbuild updates from Nicolas Schier:

  - Enable -fms-extensions, allowing anonymous use of tagged struct or
    union in struct/union (tag kbuild-ms-extensions-6.19). An exemplary
    conversion patch is added here, too (btrfs).

    [ Editor's note: the core of this actually came in early through a
      shared branch and a few other trees    - Linus ]

  - Introduce architecture-specific CC_CAN_LINK and flags for userprogs

  - Add new packaging target 'modules-cpio-pkg' for building a initramfs
    cpio w/ kmods

  - Handle included .c files in gen_compile_commands

  - Minor kbuild changes:
     - Use objtree for module signing key path, fixing oot kmod signing
     - Improve documentation of KBUILD_BUILD_TIMESTAMP
     - Reuse KBUILD_USERCFLAGS for UAPI, instead of defining twice
     - Rename scripts/Makefile.extrawarn to Makefile.warn
     - Drop obsolete types.h check from headers_check.pl
     - Remove outdated config leak ignore entries

* tag 'kbuild-6.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kbuild/linux:
  kbuild: add target to build a cpio containing modules
  initramfs: add gen_init_cpio to hostprogs unconditionally
  kbuild: allow architectures to override CC_CAN_LINK
  init: deduplicate cc-can-link.sh invocations
  kbuild: don't enable CC_CAN_LINK if the dummy program generates warnings
  scripts: headers_install.sh: Remove two outdated config leak ignore entries
  scripts/clang-tools: Handle included .c files in gen_compile_commands
  kbuild: uapi: Drop types.h check from headers_check.pl
  kbuild: Rename Makefile.extrawarn to Makefile.warn
  MAINTAINERS, .mailmap: Update mail address for Nicolas Schier
  kbuild: uapi: reuse KBUILD_USERCFLAGS
  kbuild: doc: improve KBUILD_BUILD_TIMESTAMP documentation
  kbuild: Use objtree for module signing key path
  btrfs: send: make use of -fms-extensions for defining struct fs_path
This commit is contained in:
Linus Torvalds
2025-12-03 14:42:21 -08:00
17 changed files with 207 additions and 115 deletions

View File

@@ -589,8 +589,8 @@ Nicolas Pitre <nico@fluxnic.net> <nicolas.pitre@linaro.org>
Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org>
Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.de>
Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.com>
Nicolas Schier <nicolas.schier@linux.dev> <n.schier@avm.de>
Nicolas Schier <nicolas.schier@linux.dev> <nicolas@fjasle.eu>
Nicolas Schier <nsc@kernel.org> <n.schier@avm.de>
Nicolas Schier <nsc@kernel.org> <nicolas@fjasle.eu>
Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Nikolay Aleksandrov <razor@blackwall.org> <naleksan@redhat.com>
Nikolay Aleksandrov <razor@blackwall.org> <nikolay@redhat.com>

View File

@@ -328,8 +328,14 @@ KBUILD_BUILD_TIMESTAMP
----------------------
Setting this to a date string overrides the timestamp used in the
UTS_VERSION definition (uname -v in the running kernel). The value has to
be a string that can be passed to date -d. The default value
is the output of the date command at one point during build.
be a string that can be passed to date -d. E.g.::
$ KBUILD_BUILD_TIMESTAMP="Mon Oct 13 00:00:00 UTC 2025" make
The default value is the output of the date command at one point during
build. If provided, this timestamp will also be used for mtime fields
within any initramfs archive. Initramfs mtimes are 32-bit, so dates before
the 1970 Unix epoch, or after 2106-02-07 06:28:15 UTC will fail.
KBUILD_BUILD_USER, KBUILD_BUILD_HOST
------------------------------------

View File

@@ -13498,7 +13498,7 @@ F: fs/autofs/
KERNEL BUILD + files below scripts/ (unless maintained elsewhere)
M: Nathan Chancellor <nathan@kernel.org>
M: Nicolas Schier <nicolas@fjasle.eu>
M: Nicolas Schier <nsc@kernel.org>
L: linux-kbuild@vger.kernel.org
S: Odd Fixes
Q: https://patchwork.kernel.org/project/linux-kbuild/list/

View File

@@ -1084,7 +1084,7 @@ KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srcroot)/=)
endif
# include additional Makefiles when needed
include-y := scripts/Makefile.extrawarn
include-y := scripts/Makefile.warn
include-$(CONFIG_DEBUG_INFO) += scripts/Makefile.debug
include-$(CONFIG_DEBUG_INFO_BTF)+= scripts/Makefile.btf
include-$(CONFIG_KASAN) += scripts/Makefile.kasan
@@ -1137,8 +1137,17 @@ ifneq ($(CONFIG_ARCH_VMLINUX_NEEDS_RELOCS),)
LDFLAGS_vmlinux += --emit-relocs --discard-none
endif
# Align the bit size of userspace programs with the kernel
USERFLAGS_FROM_KERNEL := -m32 -m64 --target=%
# Align the architecture of userspace programs with the kernel
USERFLAGS_FROM_KERNEL := --target=%
ifdef CONFIG_ARCH_USERFLAGS
KBUILD_USERCFLAGS += $(CONFIG_ARCH_USERFLAGS)
KBUILD_USERLDFLAGS += $(CONFIG_ARCH_USERFLAGS)
else
# If not overridden also inherit the bit size
USERFLAGS_FROM_KERNEL += -m32 -m64
endif
KBUILD_USERCFLAGS += $(filter $(USERFLAGS_FROM_KERNEL), $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
KBUILD_USERLDFLAGS += $(filter $(USERFLAGS_FROM_KERNEL), $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))

View File

@@ -6,7 +6,7 @@
CFLAGS-$(CONFIG_DRM_USE_DYNAMIC_DEBUG) += -DDYNAMIC_DEBUG_MODULE
# Unconditionally enable W=1 warnings locally
# --- begin copy-paste W=1 warnings from scripts/Makefile.extrawarn
# --- begin copy-paste W=1 warnings from scripts/Makefile.warn
subdir-ccflags-y += -Wextra -Wunused -Wno-unused-parameter
subdir-ccflags-y += $(call cc-option, -Wrestrict)
subdir-ccflags-y += -Wmissing-format-attribute

View File

@@ -47,28 +47,30 @@
* It allows fast adding of path elements on the right side (normal path) and
* fast adding to the left side (reversed path). A reversed path can also be
* unreversed if needed.
*
* The definition of struct fs_path relies on -fms-extensions to allow
* including a tagged struct as an anonymous member.
*/
struct fs_path {
union {
struct {
char *start;
char *end;
struct __fs_path {
char *start;
char *end;
char *buf;
unsigned short buf_len:15;
unsigned short reversed:1;
char inline_buf[];
};
/*
* Average path length does not exceed 200 bytes, we'll have
* better packing in the slab and higher chance to satisfy
* an allocation later during send.
*/
char pad[256];
};
char *buf;
unsigned short buf_len:15;
unsigned short reversed:1;
};
static_assert(sizeof(struct __fs_path) < 256);
struct fs_path {
struct __fs_path;
/*
* Average path length does not exceed 200 bytes, we'll have
* better packing in the slab and higher chance to satisfy
* an allocation later during send.
*/
char inline_buf[256 - sizeof(struct __fs_path)];
};
#define FS_PATH_INLINE_SIZE \
(sizeof(struct fs_path) - offsetof(struct fs_path, inline_buf))
sizeof_field(struct fs_path, inline_buf)
/* reused for each extent */
@@ -305,7 +307,6 @@ struct send_ctx {
struct btrfs_lru_cache dir_created_cache;
struct btrfs_lru_cache dir_utimes_cache;
/* Must be last as it ends in a flexible-array member. */
struct fs_path cur_inode_path;
};

View File

@@ -82,10 +82,14 @@ config RUSTC_LLVM_VERSION
int
default $(rustc-llvm-version)
config ARCH_HAS_CC_CAN_LINK
bool
config CC_CAN_LINK
bool
default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag)) if 64BIT
default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m32-flag))
default ARCH_CC_CAN_LINK if ARCH_HAS_CC_CAN_LINK
default $(cc_can_link_user,$(m64-flag)) if 64BIT
default $(cc_can_link_user,$(m32-flag))
# Fixed in GCC 14, 13.3, 12.4 and 11.5
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921

View File

@@ -65,6 +65,9 @@ cc-option-bit = $(if-success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null,$
m32-flag := $(cc-option-bit,-m32)
m64-flag := $(cc-option-bit,-m64)
# Test whether the compiler can link userspace applications
cc_can_link_user = $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(1))
rustc-version := $(shell,$(srctree)/scripts/rustc-version.sh $(RUSTC))
rustc-llvm-version := $(shell,$(srctree)/scripts/rustc-llvm-version.sh $(RUSTC))

View File

@@ -100,7 +100,7 @@ endif
# Don't stop modules_install even if we can't sign external modules.
#
ifeq ($(filter pkcs11:%, $(CONFIG_MODULE_SIG_KEY)),)
sig-key := $(if $(wildcard $(CONFIG_MODULE_SIG_KEY)),,$(srctree)/)$(CONFIG_MODULE_SIG_KEY)
sig-key := $(if $(wildcard $(CONFIG_MODULE_SIG_KEY)),,$(objtree)/)$(CONFIG_MODULE_SIG_KEY)
else
sig-key := $(CONFIG_MODULE_SIG_KEY)
endif

View File

@@ -189,6 +189,25 @@ tar-pkg: linux-$(KERNELRELEASE)-$(ARCH).tar
tar%-pkg: linux-$(KERNELRELEASE)-$(ARCH).tar.% FORCE
@:
# modules-cpio-pkg - generate an initramfs with the modules
# ---------------------------------------------------------------------------
.tmp_modules_cpio: FORCE
$(Q)$(MAKE) -f $(srctree)/Makefile
$(Q)rm -rf $@
$(Q)$(MAKE) -f $(srctree)/Makefile INSTALL_MOD_PATH=$@ modules_install
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
modules-cpio-pkg: modules-$(KERNELRELEASE)-$(ARCH).cpio
@:
# perf-tar*-src-pkg - generate a source tarball with perf source
# ---------------------------------------------------------------------------
@@ -245,6 +264,7 @@ help:
@echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball'
@echo ' tarxz-pkg - Build the kernel as a xz compressed tarball'
@echo ' tarzst-pkg - Build the kernel as a zstd compressed tarball'
@echo ' modules-cpio-pkg - Build the kernel modules as cpio archive'
@echo ' perf-tar-src-pkg - Build the perf source tarball with no compression'
@echo ' perf-targz-src-pkg - Build the perf source tarball with gzip compression'
@echo ' perf-tarbz2-src-pkg - Build the perf source tarball with bz2 compression'

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
cat << "END" | $@ -x c - -o /dev/null >/dev/null 2>&1
cat << "END" | $@ -Werror -Wl,--fatal-warnings -x c - -o /dev/null >/dev/null 2>&1
#include <stdio.h>
int main(void)
{

View File

@@ -21,6 +21,12 @@ _DEFAULT_LOG_LEVEL = 'WARNING'
_FILENAME_PATTERN = r'^\..*\.cmd$'
_LINE_PATTERN = r'^(saved)?cmd_[^ ]*\.o := (?P<command_prefix>.* )(?P<file_path>[^ ]*\.[cS]) *(;|$)'
_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
# Pre-compiled regexes for better performance
_INCLUDE_PATTERN = re.compile(r'^\s*#\s*include\s*[<"]([^>"]*)[>"]')
_C_INCLUDE_PATTERN = re.compile(r'^\s*#\s*include\s*"([^"]*\.c)"\s*$')
_FILENAME_MATCHER = re.compile(_FILENAME_PATTERN)
# The tools/ directory adopts a different build system, and produces .cmd
# files in a different format. Do not support it.
_EXCLUDE_DIRS = ['.git', 'Documentation', 'include', 'tools']
@@ -82,7 +88,6 @@ def cmdfiles_in_dir(directory):
The path to a .cmd file.
"""
filename_matcher = re.compile(_FILENAME_PATTERN)
exclude_dirs = [ os.path.join(directory, d) for d in _EXCLUDE_DIRS ]
for dirpath, dirnames, filenames in os.walk(directory, topdown=True):
@@ -92,7 +97,7 @@ def cmdfiles_in_dir(directory):
continue
for filename in filenames:
if filename_matcher.match(filename):
if _FILENAME_MATCHER.match(filename):
yield os.path.join(dirpath, filename)
@@ -149,8 +154,87 @@ def cmdfiles_for_modorder(modorder):
yield to_cmdfile(mod_line.rstrip())
def extract_includes_from_file(source_file, root_directory):
"""Extract #include statements from a C file.
Args:
source_file: Path to the source .c file to analyze
root_directory: Root directory for resolving relative paths
Returns:
List of header files that should be included (without quotes/brackets)
"""
includes = []
if not os.path.exists(source_file):
return includes
try:
with open(source_file, 'r') as f:
for line in f:
line = line.strip()
# Look for #include statements.
# Match both #include "header.h" and #include <header.h>.
match = _INCLUDE_PATTERN.match(line)
if match:
header = match.group(1)
# Skip including other .c files to avoid circular includes.
if not header.endswith('.c'):
# For relative includes (quoted), resolve path relative to source file.
if '"' in line:
src_dir = os.path.dirname(source_file)
header_path = os.path.join(src_dir, header)
if os.path.exists(header_path):
rel_header = os.path.relpath(header_path, root_directory)
includes.append(rel_header)
else:
includes.append(header)
else:
# System include like <linux/sched.h>.
includes.append(header)
except IOError:
pass
return includes
def find_included_c_files(source_file, root_directory):
"""Find .c files that are included by the given source file.
Args:
source_file: Path to the source .c file
root_directory: Root directory for resolving relative paths
Yields:
Full paths to included .c files
"""
if not os.path.exists(source_file):
return
try:
with open(source_file, 'r') as f:
for line in f:
line = line.strip()
# Look for #include "*.c" patterns.
match = _C_INCLUDE_PATTERN.match(line)
if match:
included_file = match.group(1)
# Handle relative paths.
if not os.path.isabs(included_file):
src_dir = os.path.dirname(source_file)
included_file = os.path.join(src_dir, included_file)
# Normalize the path.
included_file = os.path.normpath(included_file)
# Check if the file exists.
if os.path.exists(included_file):
yield included_file
except IOError:
pass
def process_line(root_directory, command_prefix, file_path):
"""Extracts information from a .cmd line and creates an entry from it.
"""Extracts information from a .cmd line and creates entries from it.
Args:
root_directory: The directory that was searched for .cmd files. Usually
@@ -160,7 +244,8 @@ def process_line(root_directory, command_prefix, file_path):
Usually relative to root_directory, but sometimes absolute.
Returns:
An entry to append to compile_commands.
A list of entries to append to compile_commands (may include multiple
entries if the source file includes other .c files).
Raises:
ValueError: Could not find the extracted file based on file_path and
@@ -176,11 +261,47 @@ def process_line(root_directory, command_prefix, file_path):
abs_path = os.path.realpath(os.path.join(root_directory, file_path))
if not os.path.exists(abs_path):
raise ValueError('File %s not found' % abs_path)
return {
entries = []
# Create entry for the main source file.
main_entry = {
'directory': root_directory,
'file': abs_path,
'command': prefix + file_path,
}
entries.append(main_entry)
# Find and create entries for included .c files.
for included_c_file in find_included_c_files(abs_path, root_directory):
# For included .c files, create a compilation command that:
# 1. Uses the same compilation flags as the parent file
# 2. But compiles the included file directly (not the parent)
# 3. Includes necessary headers from the parent file for proper macro resolution
# Convert absolute path to relative for the command.
rel_path = os.path.relpath(included_c_file, root_directory)
# Extract includes from the parent file to provide proper compilation context.
extra_includes = ''
try:
parent_includes = extract_includes_from_file(abs_path, root_directory)
if parent_includes:
extra_includes = ' ' + ' '.join('-include ' + inc for inc in parent_includes)
except IOError:
pass
included_entry = {
'directory': root_directory,
'file': included_c_file,
# Use the same compilation prefix but target the included file directly.
# Add extra headers for proper macro resolution.
'command': prefix + extra_includes + ' ' + rel_path,
}
entries.append(included_entry)
logging.debug('Added entry for included file: %s', included_c_file)
return entries
def main():
@@ -213,9 +334,9 @@ def main():
result = line_matcher.match(f.readline())
if result:
try:
entry = process_line(directory, result.group('command_prefix'),
entries = process_line(directory, result.group('command_prefix'),
result.group('file_path'))
compile_commands.append(entry)
compile_commands.extend(entries)
except ValueError as err:
logging.info('Could not add line from %s: %s',
cmdfile, err)

View File

@@ -70,8 +70,6 @@ configs=$(sed -e '
#
# The format is <file-name>:<CONFIG-option> in each line.
config_leak_ignores="
arch/arc/include/uapi/asm/page.h:CONFIG_ARC_PAGE_SIZE_16K
arch/arc/include/uapi/asm/page.h:CONFIG_ARC_PAGE_SIZE_4K
arch/arc/include/uapi/asm/swab.h:CONFIG_ARC_HAS_SWAPE
arch/arm/include/uapi/asm/ptrace.h:CONFIG_CPU_ENDIAN_BE8
arch/nios2/include/uapi/asm/swab.h:CONFIG_NIOS2_CI_SWAB_NO

View File

@@ -16,6 +16,8 @@ obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o
$(obj)/initramfs_data.o: $(obj)/initramfs_inc_data
hostprogs := gen_init_cpio
ramfs-input := $(CONFIG_INITRAMFS_SOURCE)
cpio-data :=
@@ -48,8 +50,6 @@ ifeq ($(cpio-data),)
cpio-data := $(obj)/initramfs_data.cpio
hostprogs := gen_init_cpio
# .initramfs_data.cpio.d is used to identify all files included
# in initramfs and to detect if any files are added/removed.
# Removed files are identified by directory timestamp being updated

View File

@@ -6,16 +6,9 @@
#
# -std=c90 (equivalent to -ansi) catches the violation of those.
# We cannot go as far as adding -Wpedantic since it emits too many warnings.
UAPI_CFLAGS := -std=c90 -Wall -Werror=implicit-function-declaration
UAPI_CFLAGS := -std=c90 -Werror=implicit-function-declaration
# In theory, we do not care -m32 or -m64 for header compile tests.
# It is here just because CONFIG_CC_CAN_LINK is tested with -m32 or -m64.
UAPI_CFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
# USERCFLAGS might contain sysroot location for CC.
UAPI_CFLAGS += $(USERCFLAGS)
override c_flags = $(UAPI_CFLAGS) -Wp,-MMD,$(depfile) -I $(obj) -I $(srctree)/usr/dummy-include
override c_flags = $(KBUILD_USERCFLAGS) $(UAPI_CFLAGS) -Wp,-MMD,$(depfile) -I $(obj) -I $(srctree)/usr/dummy-include
# The following are excluded for now because they fail to build.
#

View File

@@ -39,7 +39,6 @@ foreach my $file (@files) {
$lineno++;
&check_include();
&check_asm_types();
&check_sizetypes();
&check_declarations();
# Dropped for now. Too much noise &check_config();
}
@@ -103,65 +102,3 @@ sub check_asm_types
$ret = 1;
}
}
my $linux_types;
my %import_stack = ();
sub check_include_typesh
{
my $path = $_[0];
my $import_path;
my $fh;
my @file_paths = ($path, $dir . "/" . $path, dirname($filename) . "/" . $path);
for my $possible ( @file_paths ) {
if (not $import_stack{$possible} and open($fh, '<', $possible)) {
$import_path = $possible;
$import_stack{$import_path} = 1;
last;
}
}
if (eof $fh) {
return;
}
my $line;
while ($line = <$fh>) {
if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
$linux_types = 1;
last;
}
if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
check_include_typesh($included);
}
}
close $fh;
delete $import_stack{$import_path};
}
sub check_sizetypes
{
if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
return;
}
if ($lineno == 1) {
$linux_types = 0;
} elsif ($linux_types >= 1) {
return;
}
if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
$linux_types = 1;
return;
}
if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
check_include_typesh($included);
}
# strip single-line comments, as types may be referenced within them
$line =~ s@/\*.*?\*/@@;
if ($line =~ m/__[us](8|16|32|64)\b/) {
printf STDERR "$filename:$lineno: " .
"found __[us]{8,16,32,64} type " .
"without #include <linux/types.h>\n";
$linux_types = 2;
$ret = 1;
}
}