build: Enabling ability to use precompiled headers and some other build fixes

Change-Id: If2b216e5674fc762338929026733f3dcb801bb1b
Refs: #1588
diff --git a/.waf-tools/pch.py b/.waf-tools/pch.py
new file mode 100644
index 0000000..c0e3039
--- /dev/null
+++ b/.waf-tools/pch.py
@@ -0,0 +1,75 @@
+#! /usr/bin/env python
+# encoding: utf-8
+
+from waflib import Logs, Utils, Task, TaskGen, Build
+from waflib.Tools import c_preproc, cxx
+
+def options(opt):
+    opt.add_option('--with-pch', action='store_true', default=False, dest='with_pch',
+                   help='''Try to use precompiled header to speed up compilation '''
+                        '''(only gcc and clang)''')
+
+def configure(conf):
+    conf.env['WITH_PCH'] = conf.options.with_pch
+
+class gchx(Task.Task):
+    run_str = '${CXX} -x c++-header ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ' + \
+              '${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ' + \
+              '${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT}'
+    scan    = c_preproc.scan
+    color   = 'BLUE'
+
+
+PCH_COMPILER_OPTIONS = {
+    'clang++': ['-include', '.pch', ''],
+    'g++': ['-include', '.gch', ''],
+}
+
+@TaskGen.extension('.cpp')
+def cxx_hook(self, node):
+    if (self.env.WITH_PCH and
+        self.env['COMPILER_CXX'] in PCH_COMPILER_OPTIONS.keys() and
+        getattr(self, 'pch', None)):
+
+        (flag, pch_ext, include_ext) = PCH_COMPILER_OPTIONS[self.env['COMPILER_CXX']]
+
+        if not getattr(self, 'pch_task', None):
+            if isinstance(self.pch, str):
+                self.pch = self.path.find_node(self.pch)
+
+            output = self.pch.change_ext('.hpp%s' % pch_ext)
+
+            try:
+                # == Will reuse the existing task ==
+                # This could cause problem if different compiler flags were used for
+                # previous compilation of the precompiled header
+                existingTask = self.bld.get_tgen_by_name(output.abspath())
+                self.pch_task = existingTask
+            except:
+                self.pch_task = self.create_task('gchx', self.pch, output)
+                self.pch_task.name = output.abspath()
+
+                self.bld.task_gen_cache_names = {}
+                self.bld.add_to_group(self.pch_task, group=getattr(self, 'group', None))
+
+        task = self.create_compiled_task('cxx_pch', node)
+        # task.run_after.update(set([self.pch_task]))
+
+        task.pch_flag = flag
+        task.pch_include_file = self.pch.change_ext('.hpp%s' % include_ext).get_bld()
+
+        out = '%s%s' % (self.pch.name, pch_ext)
+        task.pch_file = self.pch.parent.get_bld().find_or_declare(out)
+    else:
+        self.create_compiled_task('cxx', node)
+
+class cxx_pch(Task.classes['cxx']):
+    run_str = '${CXX} ${tsk.pch_flag} ${tsk.pch_include_file.abspath()} '\
+              '${ARCH_ST:ARCH} ${CXXFLAGS} ${CPPFLAGS} ' \
+              '${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ' \
+              '${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT[0].abspath()}'
+
+    def scan(self):
+        (nodes, names) = c_preproc.scan(self)
+        nodes.append(self.pch_file)
+        return (nodes, names)
diff --git a/common-pch.hpp b/common-pch.hpp
new file mode 100644
index 0000000..c5c88a6
--- /dev/null
+++ b/common-pch.hpp
@@ -0,0 +1,31 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014  Regents of the University of California,
+ *                     Arizona Board of Regents,
+ *                     Colorado State University,
+ *                     University Pierre & Marie Curie, Sorbonne University,
+ *                     Washington University in St. Louis,
+ *                     Beijing Institute of Technology
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NFD_COMMON_PCH_HPP
+#define NFD_COMMON_PCH_HPP
+
+#include "config.hpp"
+#include "common.hpp"
+
+#endif // NFD_COMMON_PCH_HPP
diff --git a/common.hpp b/common.hpp
index c815bbc..ef2ce3d 100644
--- a/common.hpp
+++ b/common.hpp
@@ -39,13 +39,20 @@
 #define PROTECTED_WITH_TESTS_ELSE_PRIVATE private
 #endif
 
+#include <list>
+#include <set>
+#include <vector>
+
 #include <ndn-cxx/common.hpp>
 #include <ndn-cxx/interest.hpp>
 #include <ndn-cxx/data.hpp>
 
+#include <boost/algorithm/string.hpp>
+#include <boost/asio.hpp>
 #include <boost/assert.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/noncopyable.hpp>
+#include <boost/property_tree/ptree.hpp>
 #include <boost/scoped_ptr.hpp>
 
 namespace nfd {
diff --git a/tests/boost-test.hpp b/tests/boost-test.hpp
new file mode 100644
index 0000000..a3b8579
--- /dev/null
+++ b/tests/boost-test.hpp
@@ -0,0 +1,37 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014,  Regents of the University of California,
+ *                      Arizona Board of Regents,
+ *                      Colorado State University,
+ *                      University Pierre & Marie Curie, Sorbonne University,
+ *                      Washington University in St. Louis,
+ *                      Beijing Institute of Technology,
+ *                      The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_TESTS_BOOST_TEST_HPP
+#define NFD_TESTS_BOOST_TEST_HPP
+
+// suppress warnings from Boost.Test
+#pragma GCC system_header
+#pragma clang system_header
+
+#include <boost/test/unit_test.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/test/output_test_stream.hpp>
+
+#endif // NFD_TESTS_BOOST_TEST_HPP
diff --git a/tests/main.cpp b/tests/main.cpp
index 580d72b..2733634 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -25,4 +25,4 @@
 #define BOOST_TEST_MAIN 1
 #define BOOST_TEST_DYN_LINK 1
 
-#include <boost/test/unit_test.hpp>
+#include "boost-test.hpp"
diff --git a/tests/test-common.hpp b/tests/test-common.hpp
index 8939324..15124cd 100644
--- a/tests/test-common.hpp
+++ b/tests/test-common.hpp
@@ -25,9 +25,11 @@
 #ifndef NFD_TESTS_TEST_COMMON_HPP
 #define NFD_TESTS_TEST_COMMON_HPP
 
-#include <boost/test/unit_test.hpp>
+#include "boost-test.hpp"
+
 #include "core/global-io.hpp"
 #include "core/logger.hpp"
+
 #include <ndn-cxx/security/key-chain.hpp>
 
 namespace nfd {
diff --git a/tests/test-pch.hpp b/tests/test-pch.hpp
new file mode 100644
index 0000000..9f89474
--- /dev/null
+++ b/tests/test-pch.hpp
@@ -0,0 +1,32 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014,  Regents of the University of California,
+ *                      Arizona Board of Regents,
+ *                      Colorado State University,
+ *                      University Pierre & Marie Curie, Sorbonne University,
+ *                      Washington University in St. Louis,
+ *                      Beijing Institute of Technology,
+ *                      The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_TESTS_TEST_PCH_HPP
+#define NFD_TESTS_TEST_PCH_HPP
+
+#include "common.hpp"
+#include "boost-test.hpp"
+
+#endif // NFD_TESTS_TEST_PCH_HPP
diff --git a/tests/wscript b/tests/wscript
index be93c0a..7d8c36d 100644
--- a/tests/wscript
+++ b/tests/wscript
@@ -44,6 +44,7 @@
             use='core-objects unit-tests-main',
             includes='.',
             install_path=None,
+            pch='test-pch.hpp',
           )
 
         # NFD tests
@@ -57,6 +58,7 @@
             use='daemon-objects unit-tests-main',
             includes='.',
             install_path=None,
+            pch='test-pch.hpp',
           )
 
         if bld.env['HAVE_LIBPCAP']:
@@ -75,6 +77,7 @@
             use='rib-objects unit-tests-main',
             includes=['.'],
             install_path=None,
+            pch='test-pch.hpp',
           )
 
     # Other tests (e.g., stress tests that can be enabled even if unit tests are disabled)
diff --git a/waf b/waf
index 78a44f3..53bea56 100755
--- a/waf
+++ b/waf
Binary files differ
diff --git a/wscript b/wscript
index 47aee6c..c43a556 100644
--- a/wscript
+++ b/wscript
@@ -33,7 +33,7 @@
 def options(opt):
     opt.load(['compiler_cxx', 'gnu_dirs'])
     opt.load(['boost', 'unix-socket', 'dependency-checker', 'websocket',
-              'default-compiler-flags', 'coverage',
+              'default-compiler-flags', 'coverage', 'pch',
               'doxygen', 'sphinx_build'],
              tooldir=['.waf-tools'])
 
@@ -55,7 +55,7 @@
 
 def configure(conf):
     conf.load(['compiler_cxx', 'gnu_dirs',
-               'default-compiler-flags',
+               'default-compiler-flags', 'pch',
                'boost', 'dependency-checker', 'websocket',
                'doxygen', 'sphinx_build'])
 
@@ -126,6 +126,7 @@
         use='version BOOST NDN_CXX LIBRT',
         includes='. core',
         export_includes='. core',
+        pch='common-pch.hpp',
         )
 
     nfd_objects = bld(
@@ -140,6 +141,7 @@
         use='core-objects',
         includes='daemon websocketpp',
         export_includes='daemon',
+        pch='common-pch.hpp',
         )
 
     if bld.env['HAVE_LIBPCAP']: