[PATCH] Speed up "make headers_*"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is just a heads up patch if anyone is interested.
I finally took the time needed to optimize the
make headers_* targets.

On my box it now takes less than 10 seconds to run
the full install + check cycle.
And it generates roughtly one screen full of output.

Compare that to ~31 seconds and output filling up
my scroll back buffer.

This fixes a long standing complaint from Linus that this is
too simple to warrant such long execution time - yet
there are room for improvements.

Note that this patchset removes support for ALTARCH - only remaining
user is sparc and patches are pending to remove ALTARCH usage form sparc too.

I will do a proper split-up of the patch later and add it
to kbuild-next.git.

Comments (especially to the perl scripts) are welcome.

	Sam

 b/Makefile                     |   41 ++++---
 b/scripts/Makefile.headersinst |  218 ++++++++++++-----------------------------
 b/scripts/headers_check.pl     |   48 +++++++++
 b/scripts/headers_install.pl   |   39 +++++++
 scripts/hdrcheck.sh            |   10 -
 5 files changed, 176 insertions(+), 180 deletions(-)

diff --git a/Makefile b/Makefile
index 8db70fe..8f8fd6f 100644
--- a/Makefile
+++ b/Makefile
@@ -996,36 +996,45 @@ depend dep:
 
 # ---------------------------------------------------------------------------
 # Kernel headers
-INSTALL_HDR_PATH=$(objtree)/usr
-export INSTALL_HDR_PATH
 
-HDRFILTER=generic i386 x86_64
-HDRARCHES=$(filter-out $(HDRFILTER),$(patsubst $(srctree)/include/asm-%/Kbuild,%,$(wildcard $(srctree)/include/asm-*/Kbuild)))
+#Default location for installed headers
+export INSTALL_HDR_PATH = $(objtree)/usr
 
-PHONY += headers_install_all
-headers_install_all: include/linux/version.h scripts_basic FORCE
+hdr-filter := generic um ppc
+hdr-archs  := $(filter-out $(hdr-filter),                           \
+                  $(patsubst $(srctree)/include/asm-%/Kbuild,%,     \
+                      $(wildcard $(srctree)/include/asm-*/Kbuild)))
+hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
+
+PHONY += __headers
+__headers: include/linux/version.h scripts_basic FORCE
 	$(Q)$(MAKE) $(build)=scripts scripts/unifdef
-	$(Q)for arch in $(HDRARCHES); do \
-	 $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch ;\
+
+PHONY += headers_install_all
+headers_install_all: __headers
+	$(Q)set -e; for arch in $(hdr-archs); do \
+	 $(MAKE) ARCH=$$arch SRCARCH=$$arch $(hdr-inst)=include \
+	         BIASMDIR=-bi-$$arch ;\
 	 done
 
 PHONY += headers_install
-headers_install: include/linux/version.h scripts_basic FORCE
-	@if [ ! -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
+headers_install: __headers
+	$(Q)if [ ! -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
 	  echo '*** Error: Headers not exportable for this architecture ($(SRCARCH))'; \
-	  exit 1 ; fi
-	$(Q)$(MAKE) $(build)=scripts scripts/unifdef
-	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include
+	  exit 1 ; \
+	fi
+	$(Q)$(MAKE) $(hdr-inst)=include ARCH=$(SRCARCH)
 
 PHONY += headers_check_all
 headers_check_all: headers_install_all
-	$(Q)for arch in $(HDRARCHES); do \
-	 $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
+	$(Q)set -e; for arch in $(hdr-archs); do \
+	 $(MAKE) ARCH=$$arch SRCARCH=$$arch $(hdr-inst)=include \
+	         BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
 	 done
 
 PHONY += headers_check
 headers_check: headers_install
-	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include HDRCHECK=1
+	$(Q)$(MAKE) $(hdr-inst)=include ARCH=$(SRCARCH) HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Modules
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index 53dae3e..80df6f3 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -7,188 +7,98 @@
 #
 # ==========================================================================
 
-UNIFDEF := scripts/unifdef -U__KERNEL__
-
-# 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))
 
-ifeq (,$(patsubst include/asm/%,,$(obj)/))
-# For producing the generated stuff in include/asm for biarch builds, include
-# both sets of Kbuild files; we'll generate anything which is mentioned in
-# _either_ arch, and recurse into subdirectories which are mentioned in either
-# arch. Since some directories may exist in one but not the other, we must
-# use $(wildcard...). 
-GENASM := 1
-archasm	   := $(subst include/asm,asm-$(ARCH),$(obj))
-altarchasm := $(subst include/asm,asm-$(ALTARCH),$(obj))
-KBUILDFILES := $(wildcard $(srctree)/include/$(archasm)/Kbuild $(srctree)/include/$(altarchasm)/Kbuild)
-else
-KBUILDFILES := $(srctree)/$(obj)/Kbuild
-endif
+kbuild-file := $(srctree)/$(obj)/Kbuild
+include $(kbuild-file)
 
-include $(KBUILDFILES)
+include scripts/Kbuild.include
 
-include scripts/Kbuild.include 
-
-# If this is include/asm-$(ARCH) and there's no $(ALTARCH), then
-# override $(_dst) so that we install to include/asm directly.
+# If this is include/asm-$(ARCH) then override $(_dst) so that
+# we install to include/asm directly.
 # Unless $(BIASMDIR) is set, in which case we're probably doing
 # a 'headers_install_all' build and we should keep the -$(ARCH)
 # in the directory name.
-ifeq ($(obj)$(ALTARCH),include/asm-$(ARCH)$(BIASMDIR))
+ifeq ($(obj),include/asm-$(ARCH)$(BIASMDIR))
      _dst := include/asm
 endif
 
-header-y	:= $(sort $(header-y))
-unifdef-y	:= $(sort $(unifdef-y))
-subdir-y	:= $(patsubst %/,%,$(filter %/, $(header-y)))
-header-y	:= $(filter-out %/, $(header-y))
-header-y	:= $(filter-out $(unifdef-y),$(header-y))
+install      := $(INSTALL_HDR_PATH)/$(_dst)
 
-# stamp files for header checks
-check-y		:= $(patsubst %,.check.%,$(header-y) $(unifdef-y) $(objhdr-y))
+header-y     := $(sort $(header-y) $(unifdef-y))
+subdirs      := $(patsubst %/,%,$(filter %/, $(header-y)))
+header-y     := $(filter-out %/, $(header-y))
 
-# Work out what needs to be removed
-oldheaders	:= $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$(wildcard $(INSTALL_HDR_PATH)/$(_dst)/*.h))
-unwanted	:= $(filter-out $(header-y) $(unifdef-y) $(objhdr-y),$(oldheaders))
+# files used to track state of install/check
+install-file := $(install)/.install
+check-file   := $(install)/.check
+check-dep    := $(install)/.check.d
 
-oldcheckstamps	:= $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$(wildcard $(INSTALL_HDR_PATH)/$(_dst)/.check.*.h))
-unwanted	+= $(filter-out $(check-y),$(oldcheckstamps))
+# all headers files for this dir
+all-files    := $(header-y) $(objhdr-y)
 
-# Prefix them all with full paths to $(INSTALL_HDR_PATH)
-header-y 	:= $(patsubst %,$(INSTALL_HDR_PATH)/$(_dst)/%,$(header-y))
-unifdef-y 	:= $(patsubst %,$(INSTALL_HDR_PATH)/$(_dst)/%,$(unifdef-y))
-objhdr-y 	:= $(patsubst %,$(INSTALL_HDR_PATH)/$(_dst)/%,$(objhdr-y))
-check-y 	:= $(patsubst %,$(INSTALL_HDR_PATH)/$(_dst)/%,$(check-y))
+# Work out what needs to be removed
+oldheaders   := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h))
+unwanted     := $(filter-out $(all-files),$(oldheaders))
 
+# Prefix all with full paths to $(INSTALL_HDR_PATH)
+header-y     := $(addprefix $(install)/, $(header-y))
+objhdr-y     := $(addprefix $(install)/, $(objhdr-y))
+unwanted     := $(addprefix $(install)/, $(unwanted))
 
-ifdef ALTARCH
-ifeq ($(obj),include/asm-$(ARCH))
-altarch-y	:= altarch-dir
-endif
-endif
+printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
 
-# Make the definitions visible for recursive make invocations
-export ALTARCH
-export ARCHDEF
-export ALTARCHDEF
-
-quiet_cmd_o_hdr_install   = INSTALL $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_o_hdr_install   = cp $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,$(objtree)/$(obj)/%,$@) \
-			    $(INSTALL_HDR_PATH)/$(_dst)
-
-quiet_cmd_headers_install = INSTALL $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_headers_install = $(HDRSED) $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,$(srctree)/$(obj)/%,$@)	\
-			    > $@
-
-quiet_cmd_unifdef	  = UNIFDEF $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_unifdef	  = $(UNIFDEF) $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,$(srctree)/$(obj)/%,$@) \
-				   | $(HDRSED) > $@ || :
-
-quiet_cmd_check		  = CHECK   $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/.check.%,$(_dst)/%,$@)
-      cmd_check		  = $(CONFIG_SHELL) $(srctree)/scripts/hdrcheck.sh \
-                              $(INSTALL_HDR_PATH)/include $(subst /.check.,/,$@) $@
-
-quiet_cmd_remove	  = REMOVE  $(_dst)/$@
-      cmd_remove	  = rm -f $(INSTALL_HDR_PATH)/$(_dst)/$@
-
-quiet_cmd_mkdir		  = MKDIR   $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_mkdir		  = mkdir -p $@
-
-quiet_cmd_gen		  = GEN     $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_gen		  = \
-FNAME=$(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$@);			\
-STUBDEF=__ASM_STUB_`echo $$FNAME | tr a-z.- A-Z__`;			\
-(echo "/* File autogenerated by 'make headers_install' */" ;		\
-echo "\#ifndef $$STUBDEF" ;						\
-echo "\#define $$STUBDEF" ;						\
-echo "\# if $(ARCHDEF)" ;						\
-if [ -r $(subst /$(_dst)/,/include/$(archasm)/,$@) ]; then		\
-	echo "\#  include <$(archasm)/$$FNAME>" ;			\
-else									\
-	echo "\#  error $(archasm)/$$FNAME does not exist in"		\
-			"the $(ARCH) architecture" ;			\
-fi ;									\
-echo "\# elif $(ALTARCHDEF)" ;						\
-if [ -r $(subst /$(_dst)/,/include/$(altarchasm)/,$@) ]; then		\
-	echo "\#  include <$(altarchasm)/$$FNAME>" ;			\
-else									\
-	echo "\#  error $(altarchasm)/$$FNAME does not exist in"	\
-			"the $(ALTARCH) architecture" ;			\
-fi ;									\
-echo "\# else" ;							\
-echo "\#  warning This machine appears to be"				\
-		 "neither $(ARCH) nor $(ALTARCH)." ;			\
-echo "\# endif" ;							\
-echo "\#endif /* $$STUBDEF */" ;					\
-) > $@
-
-.PHONY: __headersinst __headerscheck
+quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files)) files)
+      cmd_install = $(PERL) $(srctree)/scripts/headers_install.pl \
+                            $(obj) $(install) $(all-files)
 
-ifdef HDRCHECK
-__headerscheck: $(subdir-y) $(check-y)
-	@true
+quiet_cmd_remove = REMOVE  $(patsubst $(INSTALL_HDR_PATH)/%,%,$(unwanted))
+      cmd_remove = rm -f $(unwanted)
+
+quiet_cmd_check = CHECK   $(printdir) ($(words $(all-files)) files)
+      cmd_check = $(PERL) $(srctree)/scripts/headers_check.pl \
+                  $(INSTALL_HDR_PATH)/include                 \
+                  $(addprefix $(install)/, $(all-files))
 
-$(check-y) : $(INSTALL_HDR_PATH)/$(_dst)/.check.%.h : $(INSTALL_HDR_PATH)/$(_dst)/%.h 
-	$(call cmd,check)
+PHONY += __headersinst __headerscheck
 
-# Other dependencies for $(check-y)
-include /dev/null $(wildcard $(check-y))
+ifdef HDRCHECK
+__headerscheck: $(subdirs) $(check-file)
+	@:
 
-# ... but leave $(check-y) as .PHONY for now until those deps are actually correct.
-.PHONY: $(check-y)
+targets += $(check-file)
+$(check-file): $(addprefix $(srctree)/$(obj)/,$(all-files)) FORCE
+	$(call if_changed,check)
+	$(Q)touch $@
 
 else
 # Rules for installing headers
-__headersinst: $(subdir-y) $(header-y) $(unifdef-y) $(altarch-y) $(objhdr-y)
-	@true
-
-$(objhdr-y) $(subdir-y) $(header-y) $(unifdef-y): | $(INSTALL_HDR_PATH)/$(_dst) $(unwanted)
-
-$(INSTALL_HDR_PATH)/$(_dst):
-	$(call cmd,mkdir)
+__headersinst: $(subdirs) $(install-file)
+	@:
 
-.PHONY: $(unwanted)
-$(unwanted):
-	$(call cmd,remove)
+targets += $(install-file)
+$(install-file): $(addprefix $(srctree)/$(obj)/,$(all-files)) FORCE
+	$(if $(unwanted),$(call cmd,remove),)
+	$(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@)))
+	$(call if_changed,install)
+	$(Q)touch $@
 
-ifdef GENASM
-$(objhdr-y) $(header-y) $(unifdef-y): $(KBUILDFILES)
-	$(call cmd,gen)
+endif
 
-else
-$(objhdr-y) :		$(INSTALL_HDR_PATH)/$(_dst)/%.h: $(objtree)/$(obj)/%.h $(KBUILDFILES)
-	$(call cmd,o_hdr_install)
+# Recursion
+hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
+.PHONY: $(subdirs)
+$(subdirs):
+	$(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@
 
-$(header-y) :		$(INSTALL_HDR_PATH)/$(_dst)/%.h: $(srctree)/$(obj)/%.h $(KBUILDFILES)
-	$(call cmd,headers_install)
+targets := $(wildcard $(sort $(targets)))
+cmd_files := $(wildcard \
+             $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
 
-$(unifdef-y) :		$(INSTALL_HDR_PATH)/$(_dst)/%.h: $(srctree)/$(obj)/%.h $(KBUILDFILES)
-	$(call cmd,unifdef)
-endif
+ifneq ($(cmd_files),)
+	include $(cmd_files)
 endif
 
-hdrinst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
-
-.PHONY: altarch-dir
-# All the files in the normal arch dir must be created first, since we test
-# for their existence.
-altarch-dir: $(subdir-y) $(header-y) $(unifdef-y) $(objhdr-y)
-	$(Q)$(MAKE) $(hdrinst)=include/asm-$(ALTARCH) dst=include/asm-$(ALTARCH)
-	$(Q)$(MAKE) $(hdrinst)=include/asm dst=include/asm$(BIASMDIR)
-
-# Recursion
-.PHONY: $(subdir-y)
-$(subdir-y):
-	$(Q)$(MAKE) $(hdrinst)=$(obj)/$@ dst=$(_dst)/$@ rel=../$(rel)
+.PHONY: $(PHONY)
+PHONY += FORCE
+FORCE: ;
diff --git a/scripts/hdrcheck.sh b/scripts/hdrcheck.sh
deleted file mode 100755
index 3159858..0000000
--- a/scripts/hdrcheck.sh
+++ /dev/null
@@ -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
diff --git a/scripts/headers_check.pl b/scripts/headers_check.pl
new file mode 100644
index 0000000..dfb2ec7
--- /dev/null
+++ b/scripts/headers_check.pl
@@ -0,0 +1,48 @@
+#!/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
+# 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
+
+my ($dir, @files) = @ARGV;
+
+my $ret = 0;
+my $lineno = 0;
+my $filename;
+
+foreach $file (@files) {
+	$filename = $file;
+	open(FILE, "< $filename") or die "$filename: $!\n";
+	$lineno = 0;
+	while ($line = <FILE>) {
+		$lineno++;
+		&check_include();
+	}
+	close(FILE);
+}
+exit($ret);
+
+my $includere = qr/^\s*#\s*include\s+<(.*)>/;
+sub check_include()
+{
+	if ($line =~ m/^\s*#\s*include\s+<(.*)>/) {
+		my $inc = $1;
+		if ($inc =~ m/^asm/ || $inc =~ m/^linux/) {
+			if (!(stat($dir . "/" . $inc))) {
+				printf STDERR "$filename:$lineno: included file '$inc' is not exported\n";
+				$ret = 1;
+			}
+		}
+	}
+}
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl
new file mode 100644
index 0000000..8aa66af
--- /dev/null
+++ b/scripts/headers_install.pl
@@ -0,0 +1,39 @@
+#!/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 opendir installdir [files...]
+# opendir: 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__
+
+my ($opendir, $installdir, @files) = @ARGV;
+
+my $ret = 0;
+
+foreach $file (@files) {
+	open(INFILE, "< $opendir/$file") or die "$openddir/$file: $!\n";
+	open(OUTFILE, "> $installdir/$file.tmp") or
+		die "$installdir/$file.tmp: $!\n";
+	while ($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 $line;
+	}
+	close(OUTFILE);
+	close(INFILE);
+	system "scripts/unifdef -U__KERNEL__ $installdir/$file.tmp > $installdir/$file"
+}
+
+exit($ret);
+
--
To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux&nblp;USB Development]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite Secrets]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux