build: make precompiled headers more useful

This can reduce the compilation time of a release
build (without tests) by more than 40%

Refs: #5212
Change-Id: I977aff0c0c7becbfee8a8b55605b81d0c014829b
diff --git a/core/common.hpp b/core/common.hpp
index 96d34a7..aff3ab2 100644
--- a/core/common.hpp
+++ b/core/common.hpp
@@ -71,11 +71,8 @@
 #include <ndn-cxx/util/span.hpp>
 #include <ndn-cxx/util/time.hpp>
 
-#include <boost/asio.hpp>
 #include <boost/assert.hpp>
 #include <boost/core/noncopyable.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/property_tree/ptree.hpp>
 
 namespace nfd {
 
diff --git a/core/network.cpp b/core/network.cpp
index bfecec5..5e75b7f 100644
--- a/core/network.cpp
+++ b/core/network.cpp
@@ -25,9 +25,13 @@
 
 #include "network.hpp"
 
+#include <boost/lexical_cast.hpp>
 #include <boost/utility/value_init.hpp>
+
 #include <algorithm>
 #include <cctype>
+#include <istream>
+#include <ostream>
 
 namespace nfd {
 
diff --git a/core/network.hpp b/core/network.hpp
index cc6c2bb..f9fbe4f 100644
--- a/core/network.hpp
+++ b/core/network.hpp
@@ -26,7 +26,8 @@
 #ifndef NFD_CORE_NETWORK_HPP
 #define NFD_CORE_NETWORK_HPP
 
-#include "common.hpp"
+#include <boost/asio/ip/address.hpp>
+#include <string_view>
 
 namespace nfd {
 
diff --git a/daemon/common/global.hpp b/daemon/common/global.hpp
index ccc5160..25102f9 100644
--- a/daemon/common/global.hpp
+++ b/daemon/common/global.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021  Regents of the University of California,
+ * Copyright (c) 2014-2022  Regents of the University of California,
  *                          Arizona Board of Regents,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University,
@@ -27,6 +27,8 @@
 
 #include "core/common.hpp"
 
+#include <boost/asio/io_service.hpp>
+
 namespace nfd {
 
 /** \brief Returns the global io_service instance for the calling thread.
diff --git a/daemon/face/ethernet-channel.hpp b/daemon/face/ethernet-channel.hpp
index 2096585..bc9b141 100644
--- a/daemon/face/ethernet-channel.hpp
+++ b/daemon/face/ethernet-channel.hpp
@@ -30,6 +30,7 @@
 #include "ethernet-protocol.hpp"
 #include "pcap-helper.hpp"
 
+#include <boost/asio/posix/stream_descriptor.hpp>
 #include <ndn-cxx/net/network-interface.hpp>
 
 namespace nfd::face {
diff --git a/daemon/face/ethernet-transport.hpp b/daemon/face/ethernet-transport.hpp
index 951d56a..8fa7a6a 100644
--- a/daemon/face/ethernet-transport.hpp
+++ b/daemon/face/ethernet-transport.hpp
@@ -30,6 +30,7 @@
 #include "pcap-helper.hpp"
 #include "transport.hpp"
 
+#include <boost/asio/posix/stream_descriptor.hpp>
 #include <ndn-cxx/net/network-interface.hpp>
 
 namespace nfd::face {
diff --git a/daemon/face/multicast-udp-transport.cpp b/daemon/face/multicast-udp-transport.cpp
index bb373fd..e0b7ac5 100644
--- a/daemon/face/multicast-udp-transport.cpp
+++ b/daemon/face/multicast-udp-transport.cpp
@@ -29,6 +29,8 @@
 
 #include "common/privilege-helper.hpp"
 
+#include <boost/asio/ip/multicast.hpp>
+#include <boost/asio/ip/v6_only.hpp>
 #include <boost/functional/hash.hpp>
 
 #ifdef __linux__
diff --git a/daemon/face/multicast-udp-transport.hpp b/daemon/face/multicast-udp-transport.hpp
index b881e81..5a19a0c 100644
--- a/daemon/face/multicast-udp-transport.hpp
+++ b/daemon/face/multicast-udp-transport.hpp
@@ -28,6 +28,7 @@
 
 #include "datagram-transport.hpp"
 
+#include <boost/asio/ip/udp.hpp>
 #include <ndn-cxx/net/network-interface.hpp>
 
 namespace nfd::face {
diff --git a/daemon/face/network-predicate.cpp b/daemon/face/network-predicate.cpp
index a13d886..340ef82 100644
--- a/daemon/face/network-predicate.cpp
+++ b/daemon/face/network-predicate.cpp
@@ -29,6 +29,8 @@
 
 #include <fnmatch.h>
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::face {
 
 NetworkPredicateBase::NetworkPredicateBase()
diff --git a/daemon/face/network-predicate.hpp b/daemon/face/network-predicate.hpp
index 2ea79d6..5a758da 100644
--- a/daemon/face/network-predicate.hpp
+++ b/daemon/face/network-predicate.hpp
@@ -28,6 +28,7 @@
 
 #include "core/common.hpp"
 
+#include <boost/property_tree/ptree_fwd.hpp>
 #include <ndn-cxx/net/network-interface.hpp>
 
 namespace nfd::face {
diff --git a/daemon/face/stream-transport.hpp b/daemon/face/stream-transport.hpp
index ec33b26..b6ad18b 100644
--- a/daemon/face/stream-transport.hpp
+++ b/daemon/face/stream-transport.hpp
@@ -32,6 +32,8 @@
 
 #include <queue>
 
+#include <boost/asio/write.hpp>
+
 namespace nfd::face {
 
 /** \brief Implements Transport for stream-based protocols.
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index be029d0..e3c9910 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -29,6 +29,8 @@
 #include "tcp-transport.hpp"
 #include "common/global.hpp"
 
+#include <boost/asio/ip/v6_only.hpp>
+
 namespace nfd::face {
 
 NFD_LOG_INIT(TcpChannel);
diff --git a/daemon/face/tcp-channel.hpp b/daemon/face/tcp-channel.hpp
index 7193851..811ee5e 100644
--- a/daemon/face/tcp-channel.hpp
+++ b/daemon/face/tcp-channel.hpp
@@ -28,6 +28,8 @@
 
 #include "channel.hpp"
 
+#include <boost/asio/ip/tcp.hpp>
+
 namespace nfd::tcp {
 using Endpoint = boost::asio::ip::tcp::endpoint;
 } // namespace nfd::tcp
diff --git a/daemon/face/tcp-factory.cpp b/daemon/face/tcp-factory.cpp
index 8ff04cc..1d25419 100644
--- a/daemon/face/tcp-factory.cpp
+++ b/daemon/face/tcp-factory.cpp
@@ -25,6 +25,8 @@
 
 #include "tcp-factory.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::face {
 
 namespace ip = boost::asio::ip;
diff --git a/daemon/face/tcp-transport.hpp b/daemon/face/tcp-transport.hpp
index 595e574..ed147fe 100644
--- a/daemon/face/tcp-transport.hpp
+++ b/daemon/face/tcp-transport.hpp
@@ -28,6 +28,8 @@
 
 #include "stream-transport.hpp"
 
+#include <boost/asio/ip/tcp.hpp>
+
 namespace nfd::face {
 
 NFD_LOG_MEMBER_DECL_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>);
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index 4e91045..80c6878 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -29,6 +29,8 @@
 #include "unicast-udp-transport.hpp"
 #include "common/global.hpp"
 
+#include <boost/asio/ip/v6_only.hpp>
+
 namespace nfd::face {
 
 NFD_LOG_INIT(UdpChannel);
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index 4feec76..331174d 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -28,6 +28,7 @@
 #include "multicast-udp-transport.hpp"
 #include "common/global.hpp"
 
+#include <boost/lexical_cast.hpp>
 #include <boost/range/adaptor/map.hpp>
 #include <boost/range/algorithm/copy.hpp>
 
diff --git a/daemon/face/udp-protocol.hpp b/daemon/face/udp-protocol.hpp
index ebd3dad..1b6e363 100644
--- a/daemon/face/udp-protocol.hpp
+++ b/daemon/face/udp-protocol.hpp
@@ -28,9 +28,11 @@
 
 #include "core/common.hpp"
 
+#include <boost/asio/ip/udp.hpp>
+
 namespace nfd::udp {
 
-typedef boost::asio::ip::udp::endpoint Endpoint;
+using Endpoint = boost::asio::ip::udp::endpoint;
 
 /** \brief computes maximum payload size in a UDP packet
  */
diff --git a/daemon/face/unicast-udp-transport.hpp b/daemon/face/unicast-udp-transport.hpp
index 7c96fef..82982fc 100644
--- a/daemon/face/unicast-udp-transport.hpp
+++ b/daemon/face/unicast-udp-transport.hpp
@@ -28,6 +28,8 @@
 
 #include "datagram-transport.hpp"
 
+#include <boost/asio/ip/udp.hpp>
+
 namespace nfd::face {
 
 NFD_LOG_MEMBER_DECL_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Unicast>));
diff --git a/daemon/face/unix-stream-channel.hpp b/daemon/face/unix-stream-channel.hpp
index 0c2eb2e..b0fdf2c 100644
--- a/daemon/face/unix-stream-channel.hpp
+++ b/daemon/face/unix-stream-channel.hpp
@@ -28,6 +28,8 @@
 
 #include "channel.hpp"
 
+#include <boost/asio/local/stream_protocol.hpp>
+
 namespace nfd::unix_stream {
 using Endpoint = boost::asio::local::stream_protocol::endpoint;
 } // namespace nfd::unix_stream
diff --git a/daemon/face/unix-stream-transport.hpp b/daemon/face/unix-stream-transport.hpp
index 8ad8a46..47b6a7e 100644
--- a/daemon/face/unix-stream-transport.hpp
+++ b/daemon/face/unix-stream-transport.hpp
@@ -28,6 +28,8 @@
 
 #include "stream-transport.hpp"
 
+#include <boost/asio/local/stream_protocol.hpp>
+
 #ifndef NFD_HAVE_UNIX_SOCKETS
 #error "Cannot include this file when UNIX sockets are not available"
 #endif
diff --git a/daemon/fw/self-learning-strategy.hpp b/daemon/fw/self-learning-strategy.hpp
index 118fe3d..59cf98b 100644
--- a/daemon/fw/self-learning-strategy.hpp
+++ b/daemon/fw/self-learning-strategy.hpp
@@ -28,7 +28,7 @@
 
 #include "fw/strategy.hpp"
 
-#include <ndn-cxx/lp/prefix-announcement-header.hpp>
+#include <ndn-cxx/prefix-announcement.hpp>
 
 namespace nfd::fw {
 
diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp
index 4c9a2e5..ce8ba23 100644
--- a/daemon/fw/strategy.hpp
+++ b/daemon/fw/strategy.hpp
@@ -29,6 +29,8 @@
 #include "forwarder.hpp"
 #include "table/measurements-accessor.hpp"
 
+#include <boost/lexical_cast/try_lexical_convert.hpp>
+
 namespace nfd::fw {
 
 class StrategyParameters;
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 6d29646..60a589a 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -33,6 +33,7 @@
 
 #include <string.h> // for strsignal()
 
+#include <boost/asio/signal_set.hpp>
 #include <boost/config.hpp>
 #include <boost/exception/diagnostic_information.hpp>
 #include <boost/filesystem.hpp>
diff --git a/daemon/mgmt/command-authenticator.cpp b/daemon/mgmt/command-authenticator.cpp
index ebf7991..d9dfba0 100644
--- a/daemon/mgmt/command-authenticator.cpp
+++ b/daemon/mgmt/command-authenticator.cpp
@@ -32,7 +32,6 @@
 #include <ndn-cxx/security/validation-policy.hpp>
 #include <ndn-cxx/security/validation-policy-accept-all.hpp>
 #include <ndn-cxx/security/validation-policy-command-interest.hpp>
-#include <ndn-cxx/security/validator.hpp>
 #include <ndn-cxx/util/io.hpp>
 
 #include <boost/filesystem.hpp>
diff --git a/daemon/mgmt/strategy-choice-manager.cpp b/daemon/mgmt/strategy-choice-manager.cpp
index ea0c056..fa18856 100644
--- a/daemon/mgmt/strategy-choice-manager.cpp
+++ b/daemon/mgmt/strategy-choice-manager.cpp
@@ -30,6 +30,8 @@
 
 #include <ndn-cxx/mgmt/nfd/strategy-choice.hpp>
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd {
 
 NFD_LOG_INIT(StrategyChoiceManager);
diff --git a/tools/nfdc/available-commands.hpp b/daemon/nfd-pch.hpp
similarity index 76%
copy from tools/nfdc/available-commands.hpp
copy to daemon/nfd-pch.hpp
index ad6525c..1692179 100644
--- a/tools/nfdc/available-commands.hpp
+++ b/daemon/nfd-pch.hpp
@@ -23,16 +23,18 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NFD_TOOLS_NFDC_AVAILABLE_COMMANDS_HPP
-#define NFD_TOOLS_NFDC_AVAILABLE_COMMANDS_HPP
+#ifndef NFD_DAEMON_NFD_PCH_HPP
+#define NFD_DAEMON_NFD_PCH_HPP
 
-#include "command-parser.hpp"
+#include "core/common.hpp"
 
-namespace nfd::tools::nfdc {
+#include <boost/lexical_cast.hpp>
+#include <boost/property_tree/ptree.hpp>
 
-void
-registerCommands(CommandParser& parser);
+#include <ndn-cxx/lp/packet.hpp>
+#include <ndn-cxx/mgmt/dispatcher.hpp>
+#include <ndn-cxx/mgmt/nfd/controller.hpp>
+#include <ndn-cxx/security/validator.hpp>
+#include <ndn-cxx/util/logger.hpp>
 
-} // namespace nfd::tools::nfdc
-
-#endif // NFD_TOOLS_NFDC_AVAILABLE_COMMANDS_HPP
+#endif // NFD_DAEMON_NFD_PCH_HPP
diff --git a/daemon/table/name-tree-iterator.hpp b/daemon/table/name-tree-iterator.hpp
index fc04fb6..4a76a53 100644
--- a/daemon/table/name-tree-iterator.hpp
+++ b/daemon/table/name-tree-iterator.hpp
@@ -28,6 +28,8 @@
 
 #include "name-tree-hashtable.hpp"
 
+#include <boost/range/iterator_range_core.hpp>
+
 namespace nfd::name_tree {
 
 class NameTree;
diff --git a/tests/core/network.t.cpp b/tests/core/network.t.cpp
index 1dfd084..e65bad5 100644
--- a/tests/core/network.t.cpp
+++ b/tests/core/network.t.cpp
@@ -27,6 +27,8 @@
 
 #include "tests/test-common.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::tests {
 
 BOOST_AUTO_TEST_SUITE(TestNetwork)
diff --git a/tests/daemon/face/stream-transport.t.cpp b/tests/daemon/face/stream-transport.t.cpp
index 80524b5..9c13653 100644
--- a/tests/daemon/face/stream-transport.t.cpp
+++ b/tests/daemon/face/stream-transport.t.cpp
@@ -28,6 +28,7 @@
 
 #include "transport-test-common.hpp"
 
+#include <boost/asio/read.hpp>
 #include <boost/mpl/vector.hpp>
 
 namespace nfd::tests {
diff --git a/tests/daemon/face/tcp-factory.t.cpp b/tests/daemon/face/tcp-factory.t.cpp
index 2547e30..fba95fe 100644
--- a/tests/daemon/face/tcp-factory.t.cpp
+++ b/tests/daemon/face/tcp-factory.t.cpp
@@ -29,6 +29,8 @@
 #include "factory-test-common.hpp"
 #include "tests/daemon/limited-io.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::tests {
 
 using face::TcpChannel;
diff --git a/tests/daemon/face/websocket-factory.t.cpp b/tests/daemon/face/websocket-factory.t.cpp
index 5043d87..aac1eca 100644
--- a/tests/daemon/face/websocket-factory.t.cpp
+++ b/tests/daemon/face/websocket-factory.t.cpp
@@ -28,6 +28,8 @@
 #include "face-system-fixture.hpp"
 #include "factory-test-common.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::tests {
 
 using face::WebSocketChannel;
diff --git a/tests/daemon/rib/rib.t.cpp b/tests/daemon/rib/rib.t.cpp
index b635207..ad42323 100644
--- a/tests/daemon/rib/rib.t.cpp
+++ b/tests/daemon/rib/rib.t.cpp
@@ -29,6 +29,8 @@
 #include "tests/daemon/global-io-fixture.hpp"
 #include "tests/daemon/rib/create-route.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::tests {
 
 using rib::Route;
diff --git a/tests/daemon/rib/route.t.cpp b/tests/daemon/rib/route.t.cpp
index 910e641..dc999b7 100644
--- a/tests/daemon/rib/route.t.cpp
+++ b/tests/daemon/rib/route.t.cpp
@@ -28,6 +28,8 @@
 #include "tests/test-common.hpp"
 #include "tests/daemon/global-io-fixture.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::tests {
 
 using rib::Route;
diff --git a/tests/other/face-benchmark.cpp b/tests/other/face-benchmark.cpp
index c9a28b6..a81ba2c 100644
--- a/tests/other/face-benchmark.cpp
+++ b/tests/other/face-benchmark.cpp
@@ -28,7 +28,9 @@
 #include "face/tcp-channel.hpp"
 #include "face/udp-channel.hpp"
 
+#include <boost/asio/signal_set.hpp>
 #include <boost/exception/diagnostic_information.hpp>
+#include <boost/lexical_cast.hpp>
 
 #include <fstream>
 #include <iostream>
diff --git a/tests/tools/nfdc/command-definition.t.cpp b/tests/tools/nfdc/command-definition.t.cpp
index 6314e2e..bf1f1a0 100644
--- a/tests/tools/nfdc/command-definition.t.cpp
+++ b/tests/tools/nfdc/command-definition.t.cpp
@@ -28,6 +28,8 @@
 
 #include "tests/test-common.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::tools::nfdc::tests {
 
 BOOST_AUTO_TEST_SUITE(Nfdc)
diff --git a/tests/tools/nfdc/command-parser.t.cpp b/tests/tools/nfdc/command-parser.t.cpp
index c9de564..a2cecc9 100644
--- a/tests/tools/nfdc/command-parser.t.cpp
+++ b/tests/tools/nfdc/command-parser.t.cpp
@@ -27,6 +27,8 @@
 
 #include "tests/test-common.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace nfd::tools::nfdc::tests {
 
 BOOST_AUTO_TEST_SUITE(Nfdc)
diff --git a/tests/tools/nfdc/execute-command-fixture.hpp b/tests/tools/nfdc/execute-command-fixture.hpp
index 4a9df2d..7d73355 100644
--- a/tests/tools/nfdc/execute-command-fixture.hpp
+++ b/tests/tools/nfdc/execute-command-fixture.hpp
@@ -27,7 +27,7 @@
 #define NFD_TESTS_TOOLS_NFDC_EXECUTE_COMMAND_FIXTURE_HPP
 
 #include "mock-nfd-mgmt-fixture.hpp"
-#include "nfdc/available-commands.hpp"
+#include "nfdc/command-parser.hpp"
 
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/split.hpp>
diff --git a/tools/ndn-autoconfig/main.cpp b/tools/ndn-autoconfig/main.cpp
index 2f8e561..3b30001 100644
--- a/tools/ndn-autoconfig/main.cpp
+++ b/tools/ndn-autoconfig/main.cpp
@@ -29,6 +29,7 @@
 #include <signal.h>
 #include <string.h>
 
+#include <boost/asio/signal_set.hpp>
 #include <boost/exception/diagnostic_information.hpp>
 #include <boost/program_options/options_description.hpp>
 #include <boost/program_options/parsers.hpp>
diff --git a/tools/nfd-autoreg.cpp b/tools/nfd-autoreg.cpp
index 7a72b82..fe079de 100644
--- a/tools/nfd-autoreg.cpp
+++ b/tools/nfd-autoreg.cpp
@@ -33,6 +33,7 @@
 #include <ndn-cxx/net/face-uri.hpp>
 #include <ndn-cxx/security/key-chain.hpp>
 
+#include <boost/asio/signal_set.hpp>
 #include <boost/exception/diagnostic_information.hpp>
 #include <boost/program_options/options_description.hpp>
 #include <boost/program_options/parsers.hpp>
@@ -42,6 +43,9 @@
 
 namespace nfd::tools::autoreg {
 
+using ndn::FaceUri;
+using ndn::Name;
+
 class AutoregServer : boost::noncopyable
 {
 public:
@@ -101,7 +105,7 @@
           .setFaceId(faceId)
           .setOrigin(ndn::nfd::ROUTE_ORIGIN_AUTOREG)
           .setCost(m_cost)
-          .setExpirationPeriod(time::milliseconds::max()),
+          .setExpirationPeriod(ndn::time::milliseconds::max()),
         [=] (auto&&...) { onRegisterCommandSuccess(faceId, prefix); },
         [=] (const auto& response) { onRegisterCommandFailure(faceId, prefix, response); });
     }
diff --git a/tools/nfdc/available-commands.cpp b/tools/nfdc/available-commands.cpp
deleted file mode 100644
index 6df761a..0000000
--- a/tools/nfdc/available-commands.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2022,  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/>.
- */
-
-#include "available-commands.hpp"
-#include "cs-module.hpp"
-#include "face-module.hpp"
-#include "rib-module.hpp"
-#include "status.hpp"
-#include "strategy-choice-module.hpp"
-
-namespace nfd::tools::nfdc {
-
-void
-registerCommands(CommandParser& parser)
-{
-  registerStatusCommands(parser);
-  FaceModule::registerCommands(parser);
-  RibModule::registerCommands(parser);
-  CsModule::registerCommands(parser);
-  StrategyChoiceModule::registerCommands(parser);
-}
-
-} // namespace nfd::tools::nfdc
diff --git a/tools/nfdc/command-definition.cpp b/tools/nfdc/command-definition.cpp
index 08952fd..c98197e 100644
--- a/tools/nfdc/command-definition.cpp
+++ b/tools/nfdc/command-definition.cpp
@@ -26,6 +26,7 @@
 #include "command-definition.hpp"
 #include "status-report.hpp"
 
+#include <boost/lexical_cast.hpp>
 #include <ndn-cxx/util/logger.hpp>
 
 namespace nfd::tools::nfdc {
diff --git a/tools/nfdc/command-parser.cpp b/tools/nfdc/command-parser.cpp
index 19bb5a2..2dff2ff 100644
--- a/tools/nfdc/command-parser.cpp
+++ b/tools/nfdc/command-parser.cpp
@@ -24,7 +24,12 @@
  */
 
 #include "command-parser.hpp"
-#include "format-helpers.hpp"
+
+#include "cs-module.hpp"
+#include "face-module.hpp"
+#include "rib-module.hpp"
+#include "status.hpp"
+#include "strategy-choice-module.hpp"
 
 #include <ndn-cxx/util/logger.hpp>
 
@@ -127,4 +132,14 @@
   return {def.getNoun(), def.getVerb(), def.parse(tokens, nConsumed), i->second->execute};
 }
 
+void
+registerCommands(CommandParser& parser)
+{
+  registerStatusCommands(parser);
+  FaceModule::registerCommands(parser);
+  RibModule::registerCommands(parser);
+  CsModule::registerCommands(parser);
+  StrategyChoiceModule::registerCommands(parser);
+}
+
 } // namespace nfd::tools::nfdc
diff --git a/tools/nfdc/command-parser.hpp b/tools/nfdc/command-parser.hpp
index e0849b0..52ba292 100644
--- a/tools/nfdc/command-parser.hpp
+++ b/tools/nfdc/command-parser.hpp
@@ -123,6 +123,9 @@
   std::vector<CommandContainer::const_iterator> m_commandOrder;
 };
 
+void
+registerCommands(CommandParser& parser);
+
 } // namespace nfd::tools::nfdc
 
 #endif // NFD_TOOLS_NFDC_COMMAND_PARSER_HPP
diff --git a/tools/nfdc/face-module.cpp b/tools/nfdc/face-module.cpp
index 08409f7..4d9d3a2 100644
--- a/tools/nfdc/face-module.cpp
+++ b/tools/nfdc/face-module.cpp
@@ -27,6 +27,8 @@
 #include "canonizer.hpp"
 #include "find-face.hpp"
 
+#include <boost/lexical_cast/try_lexical_convert.hpp>
+
 namespace nfd::tools::nfdc {
 
 void
diff --git a/tools/nfdc/main.cpp b/tools/nfdc/main.cpp
index 78da697..b89a3f9 100644
--- a/tools/nfdc/main.cpp
+++ b/tools/nfdc/main.cpp
@@ -23,10 +23,11 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "available-commands.hpp"
-#include "core/version.hpp"
+#include "command-parser.hpp"
 #include "help.hpp"
 
+#include "core/version.hpp"
+
 #include <boost/tokenizer.hpp>
 #include <fstream>
 #include <iostream>
diff --git a/tools/nfdc/available-commands.hpp b/tools/nfdc/nfdc-pch.hpp
similarity index 82%
rename from tools/nfdc/available-commands.hpp
rename to tools/nfdc/nfdc-pch.hpp
index ad6525c..b2e789d 100644
--- a/tools/nfdc/available-commands.hpp
+++ b/tools/nfdc/nfdc-pch.hpp
@@ -23,16 +23,13 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NFD_TOOLS_NFDC_AVAILABLE_COMMANDS_HPP
-#define NFD_TOOLS_NFDC_AVAILABLE_COMMANDS_HPP
+#ifndef NFD_TOOLS_NFDC_NFDC_PCH_HPP
+#define NFD_TOOLS_NFDC_NFDC_PCH_HPP
 
-#include "command-parser.hpp"
+#include "core/common.hpp"
 
-namespace nfd::tools::nfdc {
+#include <ndn-cxx/mgmt/nfd/controller.hpp>
+#include <ndn-cxx/security/validator-null.hpp>
+#include <ndn-cxx/util/logger.hpp>
 
-void
-registerCommands(CommandParser& parser);
-
-} // namespace nfd::tools::nfdc
-
-#endif // NFD_TOOLS_NFDC_AVAILABLE_COMMANDS_HPP
+#endif // NFD_TOOLS_NFDC_NFDC_PCH_HPP
diff --git a/tools/wscript b/tools/wscript
index 7f4ff7f..f3ee6a8 100644
--- a/tools/wscript
+++ b/tools/wscript
@@ -1,6 +1,6 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 """
-Copyright (c) 2014-2018,  Regents of the University of California,
+Copyright (c) 2014-2022,  Regents of the University of California,
                           Arizona Board of Regents,
                           Colorado State University,
                           University Pierre & Marie Curie, Sorbonne University,
@@ -23,49 +23,55 @@
 NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 """
 
-top = '..'
-
 from waflib import Context, Utils
 
-def build(bld):
-    commonDeps = 'core-objects NDN_CXX BOOST LIBRESOLV'
+top = '../'
 
+def build(bld):
     # Single object tools:
-    # tools/example-tool.cpp is a self-contained tool with a main() function
-    # and is built as build/bin/example-tool.
-    # These tools cannot be unit-tested.
+    # tools/foo.cpp is a self-contained tool with a main() function
+    # and is built as build/bin/foo. These tools cannot be unit-tested.
     for tool in bld.path.ant_glob('*.cpp'):
         name = tool.change_ext('').path_from(bld.path.get_bld())
         bld.program(name=name,
-                    target='../bin/%s' % name,
+                    target=top + 'bin/%s' % name,
                     source=[tool],
-                    use=commonDeps)
+                    use='core-objects')
 
     # Sub-directory tools:
-    # tools/example-tool/**/*.cpp is compiled and linked into build/bin/example-tool.
-    # tools/example-tool/main.cpp must exist and must contain the main() function.
+    # tools/foo/**/*.cpp are compiled and linked into build/bin/foo.
+    # tools/foo/main.cpp must exist and must contain the main() function.
     # All other objects are collected into 'tools-objects' and can be unit-tested.
     testableObjects = []
     for subdir in bld.path.ant_glob('*', dir=True, src=False):
+        name = subdir.path_from(bld.path)
+        subWscript = subdir.find_node('wscript')
+        if subWscript:
+            # if the subdir has a wscript, delegate to it
+            bld.recurse(name)
+            continue
+
         mainFile = subdir.find_node('main.cpp')
         if mainFile is None:
-            continue # not a C++ tool
+            # not a C++ tool, skip the subdir
+            continue
 
-        name = subdir.path_from(bld.path)
         srcFiles = subdir.ant_glob('**/*.cpp', excl=['main.cpp'])
         srcObjects = ''
         if srcFiles:
             srcObjects = 'tools-%s-objects' % name
             bld.objects(target=srcObjects,
                         source=srcFiles,
-                        use=commonDeps,
+                        features='pch',
+                        headers=subdir.find_node(name + '-pch.hpp'),
+                        use='core-objects LIBRESOLV',
                         includes=name)
             testableObjects.append(srcObjects)
 
         bld.program(name=name,
-                    target='../bin/%s' % name,
+                    target=top + 'bin/%s' % name,
                     source=[mainFile],
-                    use=commonDeps + ' ' + srcObjects,
+                    use='core-objects ' + srcObjects,
                     includes=name)
 
     bld.objects(target='tools-objects',
@@ -78,7 +84,7 @@
         name = script.change_ext('').path_from(bld.path.get_bld())
         bld(features='subst',
             name=name,
-            target='../bin/%s' % name,
+            target=top + 'bin/%s' % name,
             source=[script],
             install_path='${BINDIR}',
             chmod=Utils.O755,
diff --git a/wscript b/wscript
index 647347d..2ddc5a5 100644
--- a/wscript
+++ b/wscript
@@ -155,12 +155,10 @@
 
     bld.objects(
         target='core-objects',
-        features='pch',
         source=bld.path.find_node('core').ant_glob('*.cpp') + ['core/version.cpp'],
         use='version.cpp version.hpp NDN_CXX BOOST LIBRT',
         includes='.',
-        export_includes='.',
-        headers='core/common.hpp')
+        export_includes='.')
 
     nfd_objects = bld.objects(
         target='daemon-objects',
@@ -170,6 +168,8 @@
                                        'daemon/face/unix*.cpp',
                                        'daemon/face/websocket*.cpp',
                                        'daemon/main.cpp']),
+        features='pch',
+        headers='daemon/nfd-pch.hpp',
         use='core-objects',
         includes='daemon',
         export_includes='daemon')