(1) how to hide helper classes (2) KDE_NO_INLINE missing?

Simon Hausmann hausmann at kde.org
Sun Mar 14 11:34:53 GMT 2004


On Sunday 14 March 2004 02:59, Luciano Montanaro wrote:
> On Sunday 14 March 2004 00:54, Brad Hards wrote:
> > I haven't tried it yet, but anecdotal advice from Andrew Tridgell
> > indicates that Samba builds get a huge improvement. That is almost
> > certainly helped by the particular Samba header file system, where they
> > only ever include one header in each file (and it is always the same one
> > - it includes everything else that is required), so they get a lot of
> > assistance from pre-compiled headers.
> >
> > Maybe we can get better performance by making a standard <kde-includes.h>
> > that includes the 20 most common KDE headers and the 10 most common Qt
> > headers. Then work through the KDE files and rip out the duplicates.
> > Worth a try for someone with a lot of high performance hardware and a bit
> > of spare time.
>
> As you, I haven't tried it yet. However, an approach similar to yours could
> work, but I don't think the precompiled header should be #included for
> real.
>
> Reading the gcc manual, I see that the precompiled header could be included
> from the command line. Since Qt and KDE includes are guarded against
> multiple inclusion, a single include file could be used covering most of Qt
> and Kdelibs if the compiler supports it, otherwise everything would work as
> it does currently. No need to edit existing KDE files, just some more
> checks in the autotools scripts.

Right. That's pretty much what I did locally here, too. If anyone wants to 
give it a try, I attached the modifications I did to unsermake and 
acinclude.m4.in. It's modelled after qmake's implementation:

The idea is to have something like 'libkdecore_la_PCH = myheader.h'  in 
Makefile.am. That header file then gets precompiled and its inclusion is 
forced with '-include' to all of libkdecore_la_SOURCES.

myheader.h should have '#if defined(__cplusplus)' guards and include a 
selection of header files. The more files you add the more files you have to 
recompile when you touch one of them, so including all of them is not always 
a good idea, as it gives you the effect of --enable-final: You'll have to 
recompile all _SOURCES when you touch one of them. But even with only a 
selection of header files there is a speed-up, and it pays off for regular 
development if you mainly work on the .cpp files.

In addition at configure time you have to specify '--enable-pch' .

One thing it keep in mind is that the -include breaks preprocessor tricks, 
like the re-enabling of QTranslator in kapplication.cpp, so if you try it on 
libkdecore you need to remove the -DQT_NO_TRANSLATIONS in MakeVars. But apart 
from that I'm not aware of any problems.

So if anyone wants to try it: Please let me know if it works for you or if you 
find any problems.

Simon
-------------- next part --------------
Index: handlerbase.py
===================================================================
RCS file: /home/kde/kdenonbeta/unsermake/handlerbase.py,v
retrieving revision 1.1
diff -u -p -b -r1.1 handlerbase.py
--- handlerbase.py	7 Sep 2003 15:22:11 -0000	1.1
+++ handlerbase.py	14 Mar 2004 11:15:07 -0000
@@ -17,6 +17,9 @@ class HandlerBase:
 	def shuffle_binaries(self, amfile):
 		pass
 
+	def postprocess(self, amfile):
+		pass
+
 ext_dict = {}
 handlers = []
 
Index: kdeinit.um
===================================================================
RCS file: /home/kde/kdenonbeta/unsermake/kdeinit.um,v
retrieving revision 1.11
diff -u -p -b -r1.11 kdeinit.um
--- kdeinit.um	7 Sep 2003 16:41:20 -0000	1.11
+++ kdeinit.um	14 Mar 2004 11:15:07 -0000
@@ -50,12 +50,16 @@ class KDEINIT_Handler(handlerbase.Handle
 				# reconstruct the objects and such from scratch)
 
 				kdeinitlib = copy.copy(bin)
-				kdeinitlib.type = program.PTYPE_LTLIBRARY
+				kdeinitlib.set_type(program.PTYPE_LTLIBRARY)
 				kdeinitlib.name = 'libkdeinit_' + bin.name
 				kdeinitlib.canon_name = 'libkdeinit_' + bin.canon_name
 				kdeinitlib.final_sources = {}
 				kdeinitlib.prefix = 'lib'
 
+				pchvar = bin.canon_name + "_PCH"
+				if amfile.is_defined(pchvar):
+					amfile.add_define(kdeinitlib.canon_name + '_PCH', amfile.value_list(bin.canon_name))
+
 				# now do the same thing for the <bin> definition
 
 				amfile.add_define(canon_name + '_LDFLAGS', '$(KDE_RPATH)')
@@ -63,7 +67,7 @@ class KDEINIT_Handler(handlerbase.Handle
 				amfile.add_define(canon_name + '_LDADD', kdeinitlib.name)
 
 				kdeinit = copy.copy(bin)
-				kdeinit.type = program.PTYPE_PROGRAM
+				kdeinit.set_type(program.PTYPE_PROGRAM)
 				kdeinit.final_sources = {}
 				kdeinit.prefix = 'bin'
 				kdeinit.name = name
Index: pch.um
===================================================================
RCS file: pch.um
diff -N pch.um
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ pch.um	14 Mar 2004 11:15:07 -0000
@@ -0,0 +1,66 @@
+# -*-python-*-
+# vim: ts=4 noet
+
+import handlerbase
+
+class PCHHandler(handlerbase.HandlerBase):
+	def __init__(self):
+		pass
+
+	def postprocess(self, amfile):
+		
+		for bin in amfile.binaries.values():
+
+			pchvarname = bin.canon_name + "_PCH"
+			header = amfile.value_list(pchvarname)
+
+			if not header:
+				continue
+
+			if len(header) > 1:
+				print "%s: there can be only one header file to precompile, skipping" % pchvarname
+				continue
+
+			header = header[0]
+			
+			pchdir = amfile.rulef.build + bin.canon_name + ".gch"
+
+#			print '%s: PCH = %s / pchdir %s' % (amfile.filename, header, pchdir)
+
+			# first create rules for precompiling the header
+			cxxlines = ["test -d %s || mkdir -p %s" % (pchdir, pchdir)]
+			clines = ["test -d %s || mkdir -p %s" % (pchdir, pchdir)]
+
+			splittedheader = string.split(header, ".")
+			base = splittedheader[0]
+			ext = "." + splittedheader[1]
+
+			pic = '';
+			#if bin.type == PTYPE_LTLIBRARY:
+			# can't use PTYPE_LTLIBRARY here :(
+			if bin.type == 3:
+				pic = '-fPIC -DPIC'
+
+			cxxtarget = pchdir + '/c++'
+			ctarget = pchdir + '/c'
+
+			cxxlines.extend(bin.compile_lines(amfile.rulef.source, base, ext, "-x c++-header " + pic, 1, 1, "_cxx", cxxtarget))
+			clines.extend(bin.compile_lines(amfile.rulef.source, base, ext, "-x c-header " + pic, 0, 1, "_c", ctarget))
+
+			amfile.rulef.insertTarget(cxxtarget, header, cxxlines)
+			amfile.rulef.insertTarget(ctarget, header, clines)
+
+			# now create target rules for forcing the inclusion of the pch with -include
+			amfile.rulef.add_define(amfile.canon_subdir + '_' + bin.canon_name + "_CPPFLAGS", "-include " + bin.canon_name, 'unsermake_enable_pch')
+
+			# the *_target_PCHDEP variable is what the actual objects depend on, to make sure the
+			# precompiled header gets created before the first inclusion
+			amfile.rulef.add_define(amfile.canon_subdir + "_" + bin.canon_name + "_PCHDEP", pchdir + "/c++" + ' ' + pchdir + '/c', 'unsermake_enable_pch')
+
+			amfile.rulef.dep_files.append('$(DEPDIR)/%s.U%s' % (base + "_cxx", bin.objext[1:]))
+			amfile.rulef.dep_files.append('$(DEPDIR)/%s.U%s' % (base + "_c", bin.objext[1:]))
+
+			bin.cleanfiles.extend([bin.canon_name + ".gch/c++", bin.canon_name + ".gch/c"])
+
+
+register_handler(PCHHandler())
Index: program.py
===================================================================
RCS file: /home/kde/kdenonbeta/unsermake/program.py,v
retrieving revision 1.9
diff -u -p -b -r1.9 program.py
--- program.py	8 Mar 2004 09:51:54 -0000	1.9
+++ program.py	14 Mar 2004 11:15:08 -0000
@@ -18,7 +18,6 @@ def program_type(suffix):
 				
 class Program:
 	def __init__(self, amfile, name, prefix, type):
-		self.type = type
 		self.name = name
 		self.prefix = prefix
 		self.canon_name = utilities.canon_name(name)
@@ -27,10 +26,18 @@ class Program:
 		self.objs = []
 		self.cleanfiles = []
 		self.final_sources = {}
+		self.set_type(type)
 		
 	def __repr__(self):
 		return self.name
 	
+	def set_type(self, type):
+		self.type = type
+		if self.type == PTYPE_LTLIBRARY:
+			self.objext = '.lo'
+		else:
+			self.objext = '.o'
+
 	def is_cpp(self, ext):
 		return ext in utilities.cppext
 
@@ -45,18 +52,18 @@ class Program:
 			print '\trules to generate it. This should most probably read as'
 			print '\tdependencies for the object file.'
 
-	def compile_lines(self, dir, base, ext):
+	def compile_lines(self, dir, base, ext, extraflags = "", forcecxx = 0, forcelibtoolOff = 0, depfilesuffix = '', deptargetoverride = ''):
 				
 		libtool=0
 		compile = ""
 						
-		if self.type == PTYPE_LTLIBRARY:
+		if self.type == PTYPE_LTLIBRARY and forcelibtoolOff == 0:
 			libtool=1
 			#compile = '$(LIBTOOL) --mode=compile '
 			#if self.is_cpp(ext):
 			#	compile = compile + '--tag=CXX '
 
-		if self.is_cpp(ext):
+		if self.is_cpp(ext) or forcecxx != 0:
 			compile += '$(CXX) '
 		else:
 			compile += '$(CC) '
@@ -65,8 +72,10 @@ class Program:
 		compile += self.add_prefixed_variable("INCLUDES", 1)
 #		compile += self.handle_variable("CPPFLAGS") # Handle the Includepaths in CPPFLAGS
 		compile += self.handle_variable("CPPFLAGS", 1)
+		if len(extraflags):
+			compile += extraflags + ' '
 
-		if self.is_cpp(ext):
+		if self.is_cpp(ext) or forcecxx:
 			compile += self.handle_variable("CXXFLAGS")
 		else:
 			compile += self.handle_variable("CFLAGS")
@@ -86,10 +95,14 @@ class Program:
 				      'status=$$?; if test "$$status" -ne 0 && test ! -d "' + rulef.build + '.libs"; then \\',
 				      'exit $$status; fi; fi'])
 
-		lines.extend(["@depfile='%s$(DEPDIR)/%s.U%s' tmpdepfile='%s$(DEPDIR)/%s.TU%s' targetfile='$%s%s%s';\\"
-					  % (rulef.build, base, self.objext[1:],
-						 rulef.build, base, self.objext[1:],
-						 rulef.build, base, self.objext),
+		target = rulef.build + base + self.objext
+		if deptargetoverride:
+			target = deptargetoverride
+
+		lines.extend(["@depfile='%s$(DEPDIR)/%s.U%s' tmpdepfile='%s$(DEPDIR)/%s.TU%s' targetfile='$%s';\\"
+					  % (rulef.build, base + depfilesuffix, self.objext[1:],
+						 rulef.build, base + depfilesuffix, self.objext[1:],
+						 target),
 					  "set %s-c %s -o %s -Wp,-MD,$$tmpdepfile; \\" % (compile, file, output),
 					  "$(V_COMPILE)"])
 
@@ -114,8 +127,13 @@ class Program:
 			
 		lines = self.compile_lines(dir, base, ext)
 		
+		dep = dir + base + ext
+		pchdep = self.amfile.canon_subdir + "_" + self.canon_name + '_PCHDEP'
+		if self.amfile.rulef.is_defined(pchdep):
+			dep += ' $(' + pchdep + ')'
+
 		rulef.insertTarget(rulef.build + base + self.objext,
-						   dir + base + ext,
+						   dep,
 						   lines)
 
 		rulef.dep_files.append('$(DEPDIR)/%s.U%s' % (base, self.objext[1:]))
@@ -186,7 +204,8 @@ class Program:
 			return ""
 			
 	def handle_variable(self, var, replace_srcdir=0): # Now handles the Paths
-		added = self.add_prefixed_variable("AM_%s" % var, replace_srcdir)
+		added = self.add_prefixed_variable("%s_%s" % (self.canon_name, var), replace_srcdir)
+		added += self.add_prefixed_variable("AM_%s" % var, replace_srcdir)
 		if self.amfile.is_defined(var):
 			added += self.add_prefixed_variable(var, replace_srcdir)
 		else:
@@ -453,10 +472,6 @@ class Program:
 	def handle_sources(self, sources):
 		self.sources = sources
 		self.objects = []
-		if self.type == PTYPE_LTLIBRARY:
-			self.objext = '.lo'
-		else:
-			self.objext = '.o'
 
 		self.use_c_linker = 1
 		for source in self.sources:
Index: unsermake
===================================================================
RCS file: /home/kde/kdenonbeta/unsermake/unsermake,v
retrieving revision 1.233
diff -u -p -b -r1.233 unsermake
--- unsermake	8 Mar 2004 09:51:55 -0000	1.233
+++ unsermake	14 Mar 2004 11:15:08 -0000
@@ -708,6 +708,9 @@ class AMFile(MakeFile):
 		for handler in handlerbase.handlers:
 			handler.shuffle_binaries(self)
 			
+		for handler in handlerbase.handlers:
+			handler.postprocess(self)
+			
 		for prog in self.binaries.values():
 			prog.handle_sources( self.definition_rec( prog.canon_name + '_SOURCES' ) )
 			prog.add_targets()
-------------- next part --------------
Index: acinclude.m4.in
===================================================================
RCS file: /home/kde/kde-common/admin/acinclude.m4.in,v
retrieving revision 2.445
diff -u -p -b -r2.445 acinclude.m4.in
--- acinclude.m4.in	26 Feb 2004 21:13:57 -0000	2.445
+++ acinclude.m4.in	14 Mar 2004 11:17:55 -0000
@@ -2975,25 +2975,49 @@ AC_DEFUN([AC_CHECK_COMPILERS],
     CXXFLAGS="-Wcast-qual -Wshadow -Wcast-align $CXXFLAGS"
   fi
     
+  AC_ARG_ENABLE(pch,
+     AC_HELP_STRING([--enable-pch],
+                    [enables precompiled header support (currently only KCC or gcc >=3.4+unsermake) [default=no]]),
+    [ kde_use_pch=$enableval ],[ kde_use_pch=no ])
+ 
+
   if test "$GXX" = "yes"; then
     KDE_CHECK_COMPILER_FLAG(fno-exceptions,[CXXFLAGS="$CXXFLAGS -fno-exceptions"])
     KDE_CHECK_COMPILER_FLAG(fno-check-new, [CXXFLAGS="$CXXFLAGS -fno-check-new"])
     KDE_CHECK_COMPILER_FLAG(fno-common, [CXXFLAGS="$CXXFLAGS -fno-common"])
     KDE_CHECK_COMPILER_FLAG(fexceptions, [USE_EXCEPTIONS="-fexceptions"], USE_EXCEPTIONS=	)
+
+    if test "$kde_use_pch" = "yes"; then
+        AC_MSG_CHECKING(wether gcc supports precompiling c header files)
+        echo >conftest.h
+        if $CC -x c-header conftest.h >/dev/null 2>/dev/null; then
+            kde_gcc_supports_pch=yes
+            AC_MSG_RESULT(yes)
+        else
+            kde_gcc_supports_pch=no
+            AC_MSG_RESULT(no)
   fi
+        if test "$kde_gcc_supports_pch"; then
+            AC_MSG_CHECKING(wether gcc supports precompiling c++ header files)
+            if $CXX -x c++-header conftest.h >/dev/null 2>/dev/null; then
+                kde_gcc_supports_pch=yes
+                AC_MSG_RESULT(yes)
+            else
+                kde_gcc_supports_pch=no
+                AC_MSG_RESULT(no)
+            fi
+        fi
+        rm -f conftest.h conftest.h.gch
+    fi
+    AM_CONDITIONAL(unsermake_enable_pch, test "$kde_use_pch" = "yes" && test "$kde_gcc_supports_pch" = "yes")
+  fi
+
   if test "$CXX" = "KCC"; then
     dnl unfortunately we currently cannot disable exception support in KCC
     dnl because doing so is binary incompatible and Qt by default links with exceptions :-(
     dnl KDE_CHECK_COMPILER_FLAG(-no_exceptions,[CXXFLAGS="$CXXFLAGS --no_exceptions"])
     dnl KDE_CHECK_COMPILER_FLAG(-exceptions, [USE_EXCEPTIONS="--exceptions"], USE_EXCEPTIONS=	)
 
-    AC_ARG_ENABLE(pch,
-	AC_HELP_STRING([--enable-pch],
-		       [enables precompiled header support (currently only KCC) [default=no]]),
-    [
-      kde_use_pch=$enableval
-    ],[kde_use_pch=no])
- 
     if test "$kde_use_pch" = "yes"; then
       dnl TODO: support --pch-dir!
       KDE_CHECK_COMPILER_FLAG(-pch,[CXXFLAGS="$CXXFLAGS --pch"])


More information about the kde-core-devel mailing list