kbuild: optimize headers_* targets

Move the core functionality of headers_install
and headers_check to two small perl scripts.
The makefile is adapted to use the perl scrip and
changed to operate on all files in a directory.
So if one file is changed then all files in the
directory is processed.

perl were chosen for the helper scripts because this
is pure text processing which perl is good at and
especially the headers_check.pl script are expected to
see changes / new checks implmented.

The speed is ~300% faster on this box.
And the output generated to the screen is now down to
two lines per directory (one for install, one for check)
so it is easier to scroll back after a kernel build.

The perl scripts has been brought to sanity by patient
feedback from: Vegard Nossum <vegard.nossum@gmail.com>

Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
This commit is contained in:
Sam Ravnborg 2008-06-15 21:41:09 +02:00
parent 88181ec30f
commit 7712401ae9
4 changed files with 162 additions and 93 deletions

View file

@ -1,26 +1,14 @@
# ========================================================================== # ==========================================================================
# Installing headers # Installing headers
# #
# header-y files will be installed verbatim # header-y - list files to be installed. They are preprocessed
# unifdef-y are the files where unifdef will be run before installing files # to remove __KERNEL__ section of the file
# objhdr-y are generated files that will be installed verbatim # unifdef-y - Same as header-y. Obsolete
# objhdr-y - Same as header-y but for generated files
# #
# ========================================================================== # ==========================================================================
UNIFDEF := scripts/unifdef -U__KERNEL__ # called may set destination dir (when installing to asm/)
# Eliminate the contents of (and inclusions of) compiler.h
HDRSED := sed -e "s/ inline / __inline__ /g" \
-e "s/[[:space:]]__user[[:space:]]\{1,\}/ /g" \
-e "s/(__user[[:space:]]\{1,\}/ (/g" \
-e "s/[[:space:]]__force[[:space:]]\{1,\}/ /g" \
-e "s/(__force[[:space:]]\{1,\}/ (/g" \
-e "s/[[:space:]]__iomem[[:space:]]\{1,\}/ /g" \
-e "s/(__iomem[[:space:]]\{1,\}/ (/g" \
-e "s/[[:space:]]__attribute_const__[[:space:]]\{1,\}/\ /g" \
-e "s/[[:space:]]__attribute_const__$$//" \
-e "/^\#include <linux\/compiler.h>/d"
_dst := $(if $(dst),$(dst),$(obj)) _dst := $(if $(dst),$(dst),$(obj))
kbuild-file := $(srctree)/$(obj)/Kbuild kbuild-file := $(srctree)/$(obj)/Kbuild
@ -28,89 +16,82 @@ include $(kbuild-file)
include scripts/Kbuild.include include scripts/Kbuild.include
install := $(INSTALL_HDR_PATH)/$(_dst) install := $(INSTALL_HDR_PATH)/$(_dst)
header-y := $(sort $(header-y) $(unifdef-y)) header-y := $(sort $(header-y) $(unifdef-y))
subdir-y := $(patsubst %/,%,$(filter %/, $(header-y))) subdirs := $(patsubst %/,%,$(filter %/, $(header-y)))
header-y := $(filter-out %/, $(header-y)) header-y := $(filter-out %/, $(header-y))
# stamp files for header checks # files used to track state of install/check
check-y := $(patsubst %,.check.%,$(header-y) $(objhdr-y)) install-file := $(install)/.install
check-file := $(install)/.check
# all headers files for this dir
all-files := $(header-y) $(objhdr-y)
input-files := $(addprefix $(srctree)/$(obj)/,$(header-y)) \
$(addprefix $(objtree)/$(obj)/,$(objhdr-y))
output-files := $(addprefix $(install)/, $(all-files))
# Work out what needs to be removed # Work out what needs to be removed
oldheaders := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h)) oldheaders := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h))
unwanted := $(filter-out $(header-y) $(objhdr-y),$(oldheaders)) unwanted := $(filter-out $(all-files),$(oldheaders))
oldcheckstamps := $(patsubst $(install)/%,%,$(wildcard $(install)/.check.*.h)) # Prefix unwanted with full paths to $(INSTALL_HDR_PATH)
unwanted += $(filter-out $(check-y),$(oldcheckstamps)) unwanted-file := $(addprefix $(install)/, $(unwanted))
# Prefix them all with full paths to $(INSTALL_HDR_PATH) printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
header-y := $(patsubst %,$(install)/%,$(header-y))
objhdr-y := $(patsubst %,$(install)/%,$(objhdr-y))
check-y := $(patsubst %,$(install)/%,$(check-y))
quiet_cmd_o_hdr_install = INSTALL $(patsubst $(INSTALL_HDR_PATH)/%,%,$@) quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
cmd_o_hdr_install = cp $(patsubst $(install)/%,$(objtree)/$(obj)/%,$@) \ file$(if $(word 2, $(all-files)),s))
$(install) cmd_install = $(PERL) $< $(srctree)/$(obj) $(install) $(header-y); \
$(PERL) $< $(objtree)/$(obj) $(install) $(objhdr-y); \
touch $@
quiet_cmd_unifdef = UNIFDEF $(patsubst $(INSTALL_HDR_PATH)/%,%,$@) quiet_cmd_remove = REMOVE $(unwanted)
cmd_unifdef = $(UNIFDEF) $(patsubst $(install)/%,$(srctree)/$(obj)/%,$@)\ cmd_remove = rm -f $(unwanted-file)
| $(HDRSED) > $@ || :
quiet_cmd_check = CHECK $(patsubst $(install)/.check.%,$(_dst)/%,$@) quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files)
cmd_check = $(CONFIG_SHELL) $(srctree)/scripts/hdrcheck.sh \ cmd_check = $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH) \
$(INSTALL_HDR_PATH)/include $(subst /.check.,/,$@) $@ $(addprefix $(install)/, $(all-files)); \
touch $@
quiet_cmd_remove = REMOVE $(_dst)/$@ PHONY += __headersinst __headerscheck
cmd_remove = rm -f $(install)/$@
quiet_cmd_mkdir = MKDIR $(patsubst $(INSTALL_HDR_PATH)/%,%,$@) ifndef HDRCHECK
cmd_mkdir = mkdir -p $@ # Rules for installing headers
__headersinst: $(subdirs) $(install-file)
@:
.PHONY: __headersinst __headerscheck targets += $(install-file)
$(install-file): scripts/headers_install.pl $(input-files) FORCE
ifdef HDRCHECK $(if $(unwanted),$(call cmd,remove),)
__headerscheck: $(subdir-y) $(check-y) $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@)))
@true $(call if_changed,install)
$(check-y) : $(install)/.check.%.h : $(install)/%.h
$(call cmd,check)
# Other dependencies for $(check-y)
include /dev/null $(wildcard $(check-y))
# but leave $(check-y) as .PHONY for now until those
# deps are actually correct.
.PHONY: $(check-y)
else else
# Rules for installing headers __headerscheck: $(subdirs) $(check-file)
__headersinst: $(subdir-y) $(header-y) $(objhdr-y) @:
@true
$(objhdr-y) $(subdir-y) $(header-y): | $(install) $(unwanted) targets += $(check-file)
$(check-file): scripts/headers_check.pl $(output-files) FORCE
$(install): $(call if_changed,check)
$(call cmd,mkdir)
# Rules for removing unwanted header files
.PHONY: $(unwanted)
$(unwanted):
$(call cmd,remove)
# Install generated files
$(objhdr-y): $(install)/%.h: $(objtree)/$(obj)/%.h $(kbuild-file)
$(call cmd,o_hdr_install)
# Unifdef header files and install them
$(header-y): $(install)/%.h: $(srctree)/$(obj)/%.h $(kbuild-file)
$(call cmd,unifdef)
endif endif
hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
# Recursion # Recursion
.PHONY: $(subdir-y) hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
$(subdir-y): .PHONY: $(subdirs)
$(subdirs):
$(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@ $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@
targets := $(wildcard $(sort $(targets)))
cmd_files := $(wildcard \
$(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
ifneq ($(cmd_files),)
include $(cmd_files)
endif
.PHONY: $(PHONY)
PHONY += FORCE
FORCE: ;

View file

@ -1,10 +0,0 @@
#!/bin/sh
for FILE in `grep '^[ \t]*#[ \t]*include[ \t]*<' $2 | cut -f2 -d\< | cut -f1 -d\> | egrep ^linux\|^asm` ; do
if [ ! -r $1/$FILE ]; then
echo $2 requires $FILE, which does not exist in exported headers
exit 1
fi
done
# FIXME: List dependencies into $3
touch $3

56
scripts/headers_check.pl Normal file
View file

@ -0,0 +1,56 @@
#!/usr/bin/perl
#
# headers_check.pl execute a number of trivial consistency checks
#
# Usage: headers_check.pl dir [files...]
# dir: dir to look for included files
# arch: architecture
# files: list of files to check
#
# The script reads the supplied files line by line and:
#
# 1) for each include statement it checks if the
# included file actually exists.
# Only include files located in asm* and linux* are checked.
# The rest are assumed to be system include files.
#
# 2) TODO: check for leaked CONFIG_ symbols
use strict;
use warnings;
my ($dir, $arch, @files) = @ARGV;
my $ret = 0;
my $line;
my $lineno = 0;
my $filename;
foreach my $file (@files) {
$filename = $file;
open(my $fh, '<', "$filename") or die "$filename: $!\n";
$lineno = 0;
while ($line = <$fh>) {
$lineno++;
check_include();
}
close $fh;
}
exit $ret;
sub check_include
{
if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) {
my $inc = $1;
my $found;
$found = stat($dir . "/" . $inc);
if (!$found) {
$inc =~ s#asm/#asm-$arch/#;
$found = stat($dir . "/" . $inc);
}
if (!$found) {
printf STDERR "$filename:$lineno: included file '$inc' is not exported\n";
$ret = 1;
}
}
}

View file

@ -0,0 +1,42 @@
#!/usr/bin/perl
#
# headers_install prepare the listed header files for use in
# user space and copy the files to their destination.
#
# Usage: headers_install.pl odir installdir [files...]
# odir: dir to open files
# install: dir to install the files
# files: list of files to check
#
# Step in preparation for users space:
# 1) Drop all use of compiler.h definitions
# 2) Drop include of compiler.h
# 3) Drop all sections defined out by __KERNEL__ (using unifdef)
use strict;
use warnings;
my ($readdir, $installdir, @files) = @ARGV;
my $unifdef = "scripts/unifdef -U__KERNEL__";
foreach my $file (@files) {
my $tmpfile = "$installdir/$file.tmp";
open(my $infile, '<', "$readdir/$file")
or die "$readdir/$file: $!\n";
open(my $outfile, '>', "$tmpfile") or die "$tmpfile: $!\n";
while (my $line = <$infile>) {
$line =~ s/([\s(])__user\s/$1/g;
$line =~ s/([\s(])__force\s/$1/g;
$line =~ s/([\s(])__iomem\s/$1/g;
$line =~ s/\s__attribute_const__\s/ /g;
$line =~ s/\s__attribute_const__$//g;
$line =~ s/^#include <linux\/compiler.h>//;
printf $outfile "%s", $line;
}
close $outfile;
close $infile;
system $unifdef . " $tmpfile > $installdir/$file";
unlink $tmpfile;
}
exit 0;