lmi
[Top][All Lists]
Advanced

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

[lmi] precompiled headers


From: Vaclav Slavik
Subject: [lmi] precompiled headers
Date: Sun, 28 Jun 2009 21:33:25 +0200

Hi,

I tried to add precompiled headers support to LMI, with mixed results.
That is, it works great for Visual C++ (cutting compilation time from 33
minutes to 4 minutes in my VM), but it doesn't improve gcc compilation
times (sometimes, it is a tiny bit faster, sometimes even a tiny bit
slower).

Unfortunately, the changes required are relatively large and keeping
them in our private repository with patches specific to VC++ would be
impractical. Would you consider including the changes summarized below
in the upstream?

What I did:

(1) I changed the PCH header inclusion into the following form, in all
files:

        #include LMI_PCH_HEADER
        #ifdef __BORLANDC__
        #   pragma hdrstop
        #endif // __BORLANDC__
        
(2) Modified the makefiles to define LMI_PCH_HEADER as <pchfile_wx.hpp>
for wx sources and <pchfile.hpp> for non-wx sources. 

(3) I used a script to obtain the list of most frequently included
headers and used its output to write pchfile*.hpp files.

There are some other changes such as always using -fPIC on Unix to allow
sharing of .gch files between static and dynamic libs, but they're minor
-- see full diff below.

Notice that LMI_PCH_HEADER must be defined even if precompiled headers
aren't used, so this impacts GCC build system too.

The reason why I used the rather unsual PCH preamble from (1) is best
explained in evolutionary steps: we need two PCH files, for wx and
non-wx sources, because loading in wx PCH would slow compilation of
non-wx sources down (in case of gcc, the net effect was significantly
worse than no PCH at all). That's easily achievable by #including
different PCH headers in different source files.

Unfortunately, there are files that are compiled twice, once as part of
wx target and once as part of non-wx one. gcc wouldn't mind, you can mix
and match several precompiled headers in one target. But what gcc
doesn't like is that wx and non-wx sources are compiled with different
-- and incompatible PCH-wise -- compiler flags and so we can use
pchfile.hpp.gch either for wx or non-wx sources, but not both.
Furthermore, VC++ requires that the same PCH header is used in all
sources in a target (project).

Still, we could deal with this in the few twice-compiled files, like
this:

        #if defined(__WXMSW__) || defined(__WXGTK__)
          #include <pchfile_wx.hpp>
        #else
          #include <pchfile.hpp>
   #endif

But once again, VC++ doesn't like it -- the PCH header inclusion must be
the very first preprocessor statement in the file, there can't be any
#if above it.

And that's also why LMI_PCH_HEADER must be always defined, VC++ couldn't
handle this either:

        #ifdef LMI_PCH_HEADER
          #include LMI_PCH_HEADER
          #ifdef __BORLANDC__
            #pragma hdrstop
          #endif // __BORLANDC__
        #endif


What do you think?

Below is an incomplete patch, with .cpp files changes excluded for
simplicity. As you can see, the makefiles part for gcc has some rough
edges and FIXMEs, that's because given the results, it didn't seem worth
spending any more time on.

Thanks,
Vaclav


=== modified file 'Makefile.am'
--- Makefile.am revid:address@hidden
+++ Makefile.am 2009-04-28 07:36:13 +0000
@@ -30,6 +30,9 @@
 
 AM_CPPFLAGS = -I$(srcdir)/tools/pete-2.1.1
 
+# FIXME: don't do it uncodnitionally, only on unix
+AM_CXXFLAGS = -fPIC -DLMI_COMPILER_USES_PCH
+
 # On windows use auto import feature
 if LMI_MSW
     AM_LDFLAGS=--enable-auto-import
@@ -38,6 +41,34 @@
 endif
 
 ##############################################################################
+# Precompiled headers support
+##############################################################################
+
+# FIXME: make this conditional
+#if USE_PCH
+
+PCH_FILES = pchfile.hpp.gch pchfile_wx.hpp.gch
+
+CLEANFILES = $(PCH_FILES) .deps/
+# Adding a file to BUILT_SOURCES ensures that it is built before any source
+# files are compiled. That's exactly what is needed for PCH files.
+BUILT_SOURCES = $(PCH_FILES)
+
+pchfile.hpp.gch: $(srcdir)/pchfile.hpp
+       $(CXXCOMPILE) -x c++-header -c -o $@ -MD -MF $(DEPDIR)/address@hidden  
$<
+
+pchfile_wx.hpp.gch: $(srcdir)/pchfile_wx.hpp
+       $(CXXCOMPILE) $(WX_CXXFLAGS) -x c++-header -c -o $@ -MD -MF 
$(DEPDIR)/address@hidden $<
+
+# FIXME: generate deps!
+# FIXME: why don't other files depend on .gch files?
+
+include $(DEPDIR)/pchfile.hpp.gch.d
+include $(DEPDIR)/pchfile_wx.hpp.gch.d
+
+#endif
+
+##############################################################################
 # All Targets
 ##############################################################################
 
@@ -189,7 +220,7 @@
     wx_checks.cpp \
     wx_utility.cpp
 
-lmi_wx_CXXFLAGS = $(AM_CXXFLAGS) $(WX_CXXFLAGS) $(XMLWRAPP_CFLAGS) 
$(GTK_CFLAGS) $(LIBXSLT_CFLAGS) $(LIBXML_CFLAGS)
+lmi_wx_CXXFLAGS = $(AM_CXXFLAGS) $(WX_CXXFLAGS) $(XMLWRAPP_CFLAGS) 
$(GTK_CFLAGS) -DLMI_PCH_HEADER="<pchfile_wx.hpp>"
 # $(CGICC_INCLUDE_FLAGS)
 
 if LMI_MSW

=== modified file 'pchfile.hpp'
--- pchfile.hpp revid:address@hidden
+++ pchfile.hpp 2009-05-01 12:10:10 +0000
@@ -33,10 +33,95 @@
 #if defined LMI_COMPILER_USES_PCH && !defined LMI_IGNORE_PCH
 // This is merely a casual guess, not supported by any measurement of
 // its effect on performance. The optimal set of headers to precompile
-// probably varies by compiler. Including wx headers might impair
-// performance for non-wx targets.
-#   include <wx/wxprec.h>
+// probably varies by compiler.
+//
+// The current list of files to precompile includes most frequently used
+// standard and boost headers and a list of frequently included LMI headers,
+// both based on gcc's dependencies output.
+
+#   include "account_value.hpp"
+#   include "alert.hpp"
+#   include "any_entity.hpp"
+#   include "any_member.hpp"
+#   include "assert_lmi.hpp"
+#   include "authenticity.hpp"
+#   include "basic_values.hpp"
+#   include "calendar_date.hpp"
+#   include "ce_product_name.hpp"
+#   include "config.hpp"
+#   include "configurable_settings.hpp"
+#   include "data_directory.hpp"
+#   include "database.hpp"
+#   include "datum_base.hpp"
+#   include "datum_boolean.hpp"
+#   include "datum_string.hpp"
+#   include "dbindex.hpp"
+#   include "dbnames.hpp"
+#   include "death_benefits.hpp"
+#   include "facets.hpp"
+#   include "fenv_lmi.hpp"
+#   include "global_settings.hpp"
+#   include "handle_exceptions.hpp"
+#   include "illustrator.hpp"
+#   include "input.hpp"
+#   include "input_sequence.hpp"
+#   include "interest_rates.hpp"
+#   include "ledger.hpp"
+#   include "ledger_base.hpp"
+#   include "ledger_invariant.hpp"
+#   include "ledger_variant.hpp"
+#   include "main_common.hpp"
+#   include "max_stream_precision.hpp"
+#   include "mc_enum.hpp"
+#   include "mc_enum_type_enums.hpp"
+#   include "mc_enum_types.hpp"
+#   include "mc_enum_types.xpp"
+#   include "mc_enum_types_aux.hpp"
+#   include "miscellany.hpp"
+#   include "mvc_model.hpp"
+#   include "null_stream.hpp"
+#   include "numeric_io_cast.hpp"
+#   include "numeric_io_traits.hpp"
+#   include "obstruct_slicing.hpp"
+#   include "oecumenic_enumerations.hpp"
+#   include "outlay.hpp"
+#   include "path_utility.hpp"
+#   include "platform_dependent.hpp"
+#   include "round_to.hpp"
+#   include "rounding_rules.hpp"
+#   include "rtti_lmi.hpp"
+#   include "safely_dereference_as.hpp"
+#   include "so_attributes.hpp"
+#   include "stratified_charges.hpp"
+#   include "stream_cast.hpp"
+#   include "streamable.hpp"
+#   include "system_command.hpp"
+#   include "timer.hpp"
+#   include "tn_range.hpp"
+#   include "tn_range_type_trammels.hpp"
+#   include "tn_range_types.hpp"
+#   include "value_cast.hpp"
+#   include "yare_input.hpp"
+#   include "zero.hpp"
+
+#   include <cstddef>
+#   include <cstdlib>
+#   include <exception>
+#   include <istream>
+#   include <iterator>
+#   include <stdexcept>
+#   include <string>
+#   include <utility>
+#   include <vector>
+
+#   include <boost/config.hpp>
+#   include <boost/filesystem.hpp>
+#   include <boost/iterator.hpp>
+#   include <boost/preprocessor.hpp>
+#   include <boost/shared_ptr.hpp>
+#   include <boost/type_traits.hpp>
+#   include <boost/utility.hpp>
+
 #endif
 
 #endif // pchfile_hpp
-

=== added file 'pchfile_wx.hpp'
--- pchfile_wx.hpp      1970-01-01 00:00:00 +0000
+++ pchfile_wx.hpp      2009-04-27 13:41:57 +0000
@@ -0,0 +1,45 @@
+// Precompiled header file.
+//
+// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+// Always include this header first in every '.cpp' file that uses wxWidgets,
+// before anything else except comments and whitespace. Never include it in
+// any header file.
+
+#ifndef pchfile_wx_hpp
+#define pchfile_wx_hpp
+
+#include "pchfile.hpp"
+
+#if defined LMI_COMPILER_USES_PCH && !defined LMI_IGNORE_PCH
+#   include <wx/wx.h>
+
+#   include "wx_new.hpp"
+#   include "wx_utility.hpp"
+#   include "wx_workarounds.hpp"
+
+#   include "product_editor.hpp"
+#   include "view_ex.hpp"
+#endif
+
+#endif // pchfile_wx_hpp
+

=== modified file 'workhorse.make'
--- workhorse.make      revid:address@hidden
+++ workhorse.make      2009-05-01 11:46:29 +0000
@@ -266,6 +266,7 @@
 # so there's no point in calling them.
 
 all_include_directories := \
+  . \
   $(src_dir) \
   $(src_dir)/tools/pete-2.1.1 \
   $(overriding_include_directories) \
@@ -411,6 +412,7 @@
   -Wnon-template-friend \
   -Woverloaded-virtual \
   -Wpmf-conversions \
+  -Winvalid-pch \
   -Wsynth \
 
 # Too many warnings on correct code, e.g. exact comparison to zero:
@@ -544,11 +546,23 @@
   gcc_version_specific_warnings := -Wno-uninitialized
 endif
 
+pch_header := "<pchfile.hpp>"
+$(wx_dependent_objects): pch_header := "<pchfile_wx.hpp>"
+
+
+all:
+
+pch: pchfile.hpp.gch pchfile_wx.hpp.gch
+
+%.hpp.gch: %.hpp
+       $(CXX) -x c++-header -c $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< -o$@
+
 CFLAGS = \
   $(debug_flag) $(optimization_flag) $(gprof_flag) \
 
 CXXFLAGS = \
   $(debug_flag) $(optimization_flag) $(gprof_flag) \
+  -DLMI_PCH_HEADER=$(pch_header) \
 
 # Explicitly disable the infelicitous auto-import default. See:
 #   http://article.gmane.org/gmane.comp.gnu.mingw.user/19758
@@ -571,6 +585,7 @@
   $(libstdcxx_warning_macros) \
   $(wx_predefinitions) \
   -DBOOST_STRICT_CONFIG \
+  -DLMI_COMPILER_USES_PCH \
 
 REQUIRED_CFLAGS = \
   $(C_WARNINGS) \






reply via email to

[Prev in Thread] Current Thread [Next in Thread]