build: add PCHs for ndnsec and unit tests, fine-tune the existing ones

A full debug+tests build now takes 10% less time with gcc-9 and 21% less
with clang-10. Release builds (without tests) are only marginally faster
with gcc and 7% faster with clang.

Change-Id: I494778fe44cecc6209819a49f48a03f4d16c36af
diff --git a/tools/ndnsec/accumulator.hpp b/tools/ndnsec/accumulator.hpp
new file mode 100644
index 0000000..7c08581
--- /dev/null
+++ b/tools/ndnsec/accumulator.hpp
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2020 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_ACCUMULATOR_HPP
+#define NDN_TOOLS_NDNSEC_ACCUMULATOR_HPP
+
+#include <boost/program_options/value_semantic.hpp>
+
+namespace ndn {
+namespace ndnsec {
+
+/**
+ * @brief An accumulating option value to handle multiple incrementing options.
+ *
+ * Based on https://gitorious.org/bwy/bwy/source/8753148c324ddfacb1f3cdc315650586bd7b75a4:use/accumulator.hpp
+ * @sa http://benjaminwolsey.de/node/103
+ */
+template<typename T>
+class AccumulatorType : public boost::program_options::value_semantic
+{
+public:
+  explicit
+  AccumulatorType(T* store)
+    : m_store(store)
+    , m_interval(1)
+    , m_default(0)
+  {
+  }
+
+  /// @brief Set the default value for this option.
+  AccumulatorType*
+  setDefaultValue(const T& t)
+  {
+    m_default = t;
+    return this;
+  }
+
+  /**
+   * @brief Set the interval for this option.
+   *
+   * Unlike for program_options::value, this specifies a value
+   * to be applied on each occurrence of the option.
+   */
+  AccumulatorType*
+  setInterval(const T& t)
+  {
+    m_interval = t;
+    return this;
+  }
+
+  std::string
+  name() const final
+  {
+    return std::string();
+  }
+
+  // There are no tokens for an AccumulatorType
+  unsigned
+  min_tokens() const final
+  {
+    return 0;
+  }
+
+  unsigned
+  max_tokens() const final
+  {
+    return 0;
+  }
+
+  // Accumulating from different sources is silly.
+  bool
+  is_composing() const final
+  {
+    return false;
+  }
+
+  // Requiring one or more appearances is unlikely.
+  bool
+  is_required() const final
+  {
+    return false;
+  }
+
+  /**
+   * @brief Parse options
+   *
+   * Every appearance of the option simply increments the value
+   * There should never be any tokens.
+   */
+  void
+  parse(boost::any& value_store, const std::vector<std::string>& new_tokens, bool utf8) const final
+  {
+    if (value_store.empty())
+      value_store = T();
+    boost::any_cast<T&>(value_store) += m_interval;
+  }
+
+  /**
+   * @brief If the option doesn't appear, this is the default value.
+   */
+  bool
+  apply_default(boost::any& value_store) const final
+  {
+    value_store = m_default;
+    return true;
+  }
+
+  /**
+   * @brief Notify the user function with the value of the value store.
+   */
+  void
+  notify(const boost::any& value_store) const final
+  {
+    const T* val = boost::any_cast<T>(&value_store);
+    if (m_store)
+      *m_store = *val;
+  }
+
+#if (BOOST_VERSION >= 105900) && (BOOST_VERSION < 106500)
+  bool
+  adjacent_tokens_only() const final
+  {
+    return false;
+  }
+#endif // (BOOST_VERSION >= 105900) && (BOOST_VERSION < 106500)
+
+private:
+  T* m_store;
+  T m_interval;
+  T m_default;
+};
+
+template <typename T>
+AccumulatorType<T>*
+accumulator()
+{
+  return new AccumulatorType<T>(nullptr);
+}
+
+template <typename T>
+AccumulatorType<T>*
+accumulator(T* store)
+{
+  return new AccumulatorType<T>(store);
+}
+
+} // namespace ndnsec
+} // namespace ndn
+
+#endif // NDN_TOOLS_NDNSEC_ACCUMULATOR_HPP