build: align minimum build dependencies with ndn-cxx

 * Recommend boost >= 1.65.1 and gcc >= 7.4.0
 * Require clang >= 4.0, or Xcode >= 9.0 on macOS
 * Silence an ABI-related diagnostic message from gcc on armv7

Refs: #5087, #5106
Change-Id: I88ef0e0f183736f19ac414a84baebb0e1073381b
diff --git a/.jenkins.d/01-ndn-cxx.sh b/.jenkins.d/01-ndn-cxx.sh
index 7bf1cfe..4e0e154 100755
--- a/.jenkins.d/01-ndn-cxx.sh
+++ b/.jenkins.d/01-ndn-cxx.sh
@@ -35,16 +35,12 @@
 
 pushd ndn-cxx >/dev/null
 
-if has Linux $NODE_LABELS && [[ $CXX != clang* && -z $DISABLE_ASAN ]]; then
-    # https://stackoverflow.com/a/47022141
-    ASAN="--with-sanitizer=address"
-fi
 if has CentOS-8 $NODE_LABELS; then
     # https://bugzilla.redhat.com/show_bug.cgi?id=1721553
     PCH="--without-pch"
 fi
 
-./waf --color=yes configure --disable-static --enable-shared --without-osx-keychain $ASAN $PCH
+./waf --color=yes configure --disable-static --enable-shared --without-osx-keychain $PCH
 ./waf --color=yes build -j$WAF_JOBS
 sudo_preserve_env PATH -- ./waf --color=yes install
 
diff --git a/.jenkins.d/20-tests.sh b/.jenkins.d/20-tests.sh
index 226c77d..81c00b1 100755
--- a/.jenkins.d/20-tests.sh
+++ b/.jenkins.d/20-tests.sh
@@ -4,21 +4,6 @@
 # Prepare environment
 rm -rf ~/.ndn
 
-BOOST_VERSION=$(python3 -c "import sys; sys.path.append('build/c4che'); import _cache; print(_cache.BOOST_VERSION_NUMBER);")
-
-ut_log_args() {
-    if (( BOOST_VERSION >= 106200 )); then
-        echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-${1:-report}.xml
-    else
-        if [[ -n $XUNIT ]]; then
-            echo --log_level=all $( (( BOOST_VERSION >= 106000 )) && echo -- ) \
-                 --log_format2=XML --log_sink2=build/xunit-${1:-report}.xml
-        else
-            echo --log_level=test_suite
-        fi
-    fi
-}
-
 # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
 ASAN_OPTIONS="color=always"
 ASAN_OPTIONS+=":check_initialization_order=1"
@@ -31,6 +16,8 @@
 
 export BOOST_TEST_BUILD_INFO=1
 export BOOST_TEST_COLOR_OUTPUT=1
+export BOOST_TEST_DETECT_MEMORY_LEAK=0
+export BOOST_TEST_LOGGER=HRF,test_suite,stdout:XML,all,build/xunit-log.xml
 
 # Run unit tests
-./build/unit-tests $(ut_log_args)
+./build/unit-tests
diff --git a/.travis.yml b/.travis.yml
index 3d5ee08..8990ac7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,7 +18,10 @@
 jobs:
   include:
     # Linux
+    - env: COMPILER=g++-5
+    - env: COMPILER=g++-6
     - env: COMPILER=g++-8
+    - env: COMPILER=clang++-4.0
     - env: COMPILER=clang++-5.0
     - env: COMPILER=clang++-7
     - env: COMPILER=clang++-8
@@ -38,8 +41,14 @@
     - os: osx
       osx_image: xcode11.3
       env: # default compiler
+    - os: osx
+      osx_image: xcode11.4
+      env: # default compiler
 
   allow_failures:
+    - env: COMPILER=g++-5
+    - env: COMPILER=g++-6
+    - env: COMPILER=clang++-4.0
     - env: COMPILER=clang++-11
 
   fast_finish: true
diff --git a/.waf-tools/default-compiler-flags.py b/.waf-tools/default-compiler-flags.py
index 9e045c3..f3be6e7 100644
--- a/.waf-tools/default-compiler-flags.py
+++ b/.waf-tools/default-compiler-flags.py
@@ -1,10 +1,11 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
+import platform
 from waflib import Configure, Logs, Utils
 
 def options(opt):
     opt.add_option('--debug', '--with-debug', action='store_true', default=False,
-                   help='Compile in debugging mode with minimal optimizations (-O0 or -Og)')
+                   help='Compile in debugging mode with minimal optimizations (-Og)')
 
 def configure(conf):
     conf.start_msg('Checking C++ compiler version')
@@ -17,15 +18,21 @@
     if cxx == 'gcc':
         if ccver < (5, 3, 0):
             errmsg = ('The version of gcc you are using is too old.\n'
-                      'The minimum supported gcc version is 5.3.0.')
+                      'The minimum supported gcc version is 7.4.0.')
+        elif ccver < (7, 4, 0):
+            warnmsg = ('Using a version of gcc older than 7.4.0 is not '
+                       'officially supported and may result in build failures.')
         conf.flags = GccFlags()
     elif cxx == 'clang':
-        if ccver < (3, 6, 0):
+        if Utils.unversioned_sys_platform() == 'darwin' and ccver < (9, 0, 0):
+            errmsg = ('The version of Xcode you are using is too old.\n'
+                      'The minimum supported Xcode version is 9.0.')
+        elif ccver < (4, 0, 0):
             errmsg = ('The version of clang you are using is too old.\n'
-                      'The minimum supported clang version is 3.6.0.')
+                      'The minimum supported clang version is 4.0.')
         conf.flags = ClangFlags()
     else:
-        warnmsg = 'Note: %s compiler is unsupported' % cxx
+        warnmsg = '%s compiler is unsupported' % cxx
         conf.flags = CompilerFlags()
 
     if errmsg:
@@ -33,7 +40,7 @@
         conf.fatal(errmsg)
     elif warnmsg:
         conf.end_msg(ccverstr, color='YELLOW')
-        Logs.warn(warnmsg)
+        Logs.warn('WARNING: ' + warnmsg)
     else:
         conf.end_msg(ccverstr)
 
@@ -137,13 +144,14 @@
 
     def getDebugFlags(self, conf):
         flags = super(GccBasicFlags, self).getDebugFlags(conf)
-        flags['CXXFLAGS'] += ['-O0',
-                              '-Og', # gcc >= 4.8, clang >= 4.0
+        flags['CXXFLAGS'] += ['-Og',
                               '-g3',
                               '-pedantic',
                               '-Wall',
                               '-Wextra',
                               '-Werror',
+                              '-Wcatch-value=2',
+                              '-Wextra-semi',
                               '-Wnon-virtual-dtor',
                               '-Wno-error=deprecated-declarations', # Bug #3795
                               '-Wno-error=maybe-uninitialized', # Bug #1615
@@ -159,6 +167,8 @@
                               '-pedantic',
                               '-Wall',
                               '-Wextra',
+                              '-Wcatch-value=2',
+                              '-Wextra-semi',
                               '-Wnon-virtual-dtor',
                               '-Wno-unused-parameter',
                               ]
@@ -168,49 +178,50 @@
 class GccFlags(GccBasicFlags):
     def getDebugFlags(self, conf):
         flags = super(GccFlags, self).getDebugFlags(conf)
-        flags['CXXFLAGS'] += ['-fdiagnostics-color']
+        flags['CXXFLAGS'] += ['-fdiagnostics-color',
+                              '-Wredundant-tags',
+                              ]
+        if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
+            flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
         return flags
 
     def getOptimizedFlags(self, conf):
         flags = super(GccFlags, self).getOptimizedFlags(conf)
-        flags['CXXFLAGS'] += ['-fdiagnostics-color']
+        flags['CXXFLAGS'] += ['-fdiagnostics-color',
+                              '-Wredundant-tags',
+                              ]
+        if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
+            flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
         return flags
 
 class ClangFlags(GccBasicFlags):
     def getGeneralFlags(self, conf):
         flags = super(ClangFlags, self).getGeneralFlags(conf)
-        if Utils.unversioned_sys_platform() == 'darwin' and self.getCompilerVersion(conf) >= (9, 0, 0):
+        if Utils.unversioned_sys_platform() == 'darwin':
             # Bug #4296
             flags['CXXFLAGS'] += [['-isystem', '/usr/local/include'], # for Homebrew
                                   ['-isystem', '/opt/local/include']] # for MacPorts
-        if Utils.unversioned_sys_platform() == 'freebsd':
-            flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']] # Bug #4790
+        elif Utils.unversioned_sys_platform() == 'freebsd':
+            # Bug #4790
+            flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']]
         return flags
 
     def getDebugFlags(self, conf):
         flags = super(ClangFlags, self).getDebugFlags(conf)
         flags['CXXFLAGS'] += ['-fcolor-diagnostics',
-                              '-Wextra-semi',
                               '-Wundefined-func-template',
                               '-Wno-unused-local-typedef', # Bugs #2657 and #3209
                               ]
-        version = self.getCompilerVersion(conf)
-        if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
-            flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
-        if version < (6, 0, 0):
+        if self.getCompilerVersion(conf) < (6, 0, 0):
             flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
         return flags
 
     def getOptimizedFlags(self, conf):
         flags = super(ClangFlags, self).getOptimizedFlags(conf)
         flags['CXXFLAGS'] += ['-fcolor-diagnostics',
-                              '-Wextra-semi',
                               '-Wundefined-func-template',
                               '-Wno-unused-local-typedef', # Bugs #2657 and #3209
                               ]
-        version = self.getCompilerVersion(conf)
-        if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
-            flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
-        if version < (6, 0, 0):
+        if self.getCompilerVersion(conf) < (6, 0, 0):
             flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
         return flags
diff --git a/README-dev.md b/README-dev.md
index d3b2cec..0a76f22 100644
--- a/README-dev.md
+++ b/README-dev.md
@@ -2,12 +2,12 @@
 
 ## Licensing Requirements
 
-Contributions to ndn-tools MUST be licensed under GPL 3.0 or a compatible license.
+Contributions to ndn-tools must be licensed under the GPL 3.0 or a compatible license.
 If you choose GPL 3.0, include the following license boilerplate into all C++ code files:
 
     /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     /*
-     * Copyright (c) [Year(s)],  [Copyright Holder(s)].
+     * Copyright (c) [Year(s)] [Copyright Holder(s)].
      *
      * This file is part of ndn-tools (Named Data Networking Essential Tools).
      * See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -26,59 +26,59 @@
 
 ## Directory Structure and Build Script
 
-All tools are placed in subdirectories under `tools/` directory.
+All tools are placed in subdirectories of the [`tools`](tools) directory.
 
 A tool can consist of one or more programs.
 For instance, a pair of consumer and producer programs that are designed to work together
 should be considered a single tool, not two separate tools.
 
-Each tool MUST have a `wscript` build script in its subdirectory.
-It will be invoked if this tool is selected for the build.
-It SHOULD compile the programs into `build/bin` directory (`target='../../bin/foo'`).
+Each tool must have a `wscript` build script in its subdirectory. This script will be
+invoked automatically if the corresponding tool is selected for the build. It should
+compile the source code and produce one or more binaries in the `build/bin` directory
+(e.g., use `target='../../bin/foo'`).
 
 ### Shared Modules
 
-Modules shared among multiple tools SHOULD be placed in `core/` directory.
+Modules shared among multiple tools should be placed in the [`core`](core) directory.
 They are available for use in all tools.
 
 A header in `core/` can be included in a tool like `#include "core/foo.hpp"`.
 
-`wscript` of a tool can link a program with modules in `core/` with `use='core-objects'`.
+The `wscript` of a tool can link a program with modules in `core/` with `use='core-objects'`.
 
 ### Documentation
 
-`README.md` in the subdirectory of a tool SHOULD give a brief description.
+A file named `README.md` in the subdirectory of each tool should provide a brief
+description.
 
-Manual pages for each program SHOULD be written in reStructuredText format
-and placed in `manpages/` directory.
+Manual pages for each program should be written in reStructuredText format
+and placed in the [`manpages`](manpages) directory.
 
 ## Code Guidelines
 
-C++ code SHOULD conform to
-[ndn-cxx code style](http://named-data.net/doc/ndn-cxx/current/code-style.html).
+C++ code should conform to the
+[ndn-cxx code style](https://named-data.net/doc/ndn-cxx/current/code-style.html).
 
 ### Namespace
 
-Types in each tool SHOULD be declared in a sub-namespace inside `namespace ndn`.
-For example, a tool in `tools/foo` directory has namespace `ndn::foo`.  
+Types in each tool should be declared in a sub-namespace inside `namespace ndn`.
+For example, a tool in `tools/foo` directory has namespace `ndn::foo`.
 This allows the tool to reference ndn-cxx types with unqualified name lookup.
 This also prevents name conflicts between ndn-cxx and tools.
 
-Types in `core/` SHOULD be declared directly inside `namespace ndn`,
+Types in `core/` should be declared directly inside `namespace ndn`,
 or in a sub-namespace if desired.
 
-`using namespace` SHOULD NOT be used except in block scope.
-
 ### main Function
 
-The `main` function of a program SHOULD be declared as a static function in
+The `main` function of a program should be declared as a static function in
 the namespace of the corresponding tool. This allows referencing types in
 ndn-cxx and the tool via unqualified name lookup.
 
 Then, another (non-static) `main` function must be defined in the global
 namespace, and from there call the `main` function in the tool namespace.
 
-These two functions SHOULD appear in a file named `main.cpp` in the tool's
+These two functions should appear in a file named `main.cpp` in the tool's
 subdirectory.
 
 Example:
@@ -116,5 +116,5 @@
 
 ### Command Line Arguments
 
-[Boost.Program\_options](https://www.boost.org/doc/libs/1_58_0/doc/html/program_options.html) is
-preferred over getopt(3) for parsing command line arguments.
+[Boost.Program\_options](https://www.boost.org/doc/libs/1_65_1/doc/html/program_options.html)
+is strongly preferred over `getopt(3)` for parsing command line arguments.
diff --git a/README.md b/README.md
index daf3dde..b2b7a47 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,9 @@
 
 ## Contributing
 
-You're encouraged to contribute to ndn-tools!  If you are new to the NDN
+We greatly appreciate contributions to ndn-tools. If you are new to the NDN
 software community, please read [`README-dev.md`](README-dev.md) and the
-[Contributor's Guide](https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md)
+[Contributor's Guide](https://github.com/named-data/.github/blob/master/CONTRIBUTING.md)
 to get started.
 
 ## License
diff --git a/core/common.hpp b/core/common.hpp
index 9770a05..07971f1 100644
--- a/core/common.hpp
+++ b/core/common.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2019,  Regents of the University of California,
+ * Copyright (c) 2014-2020,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -52,8 +52,8 @@
 
 #include <boost/asio.hpp>
 #include <boost/assert.hpp>
+#include <boost/core/noncopyable.hpp>
 #include <boost/lexical_cast.hpp>
-#include <boost/noncopyable.hpp>
 #include <boost/program_options/options_description.hpp>
 #include <boost/program_options/variables_map.hpp>
 #include <boost/program_options/parsers.hpp>
diff --git a/tests/README.md b/tests/README.md
index 83cab77..ca34f42 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -1,13 +1,12 @@
-ndn-tools unit tests
-====================
+# ndn-tools unit tests
 
 ## Assumptions
 
-Unit tests for a tool `foo` should be placed in the folder `foo` and build script for the tool
-should define `foo-objects` that includes all object files for the tool, except object files
-defining main function.
+Unit tests for a tool `foo` should be placed in the folder `foo` and the build script
+for the tool should define `foo-objects` that includes all object files for that tool,
+except the object that contains the `main()` function.
 
-For example,
+For example:
 
     bld(features='cxx',
         name='tool-subtool-objects',
diff --git a/tests/main.cpp b/tests/main.cpp
index c111daf..1a6b9b0 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2019,  Regents of the University of California,
+ * Copyright (c) 2014-2020,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -23,6 +23,5 @@
  * ndn-tools, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#define BOOST_TEST_MODULE ndn-tools Unit Tests
-
-#include "boost-test.hpp"
+#define BOOST_TEST_MODULE ndn-tools
+#include "tests/boost-test.hpp"
diff --git a/tests/test-case.t.cpp.sample b/tests/test-case.t.cpp.sample
index 77d22c1..44223a6 100644
--- a/tests/test-case.t.cpp.sample
+++ b/tests/test-case.t.cpp.sample
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016,  Arizona Board of Regents.
+/*
+ * Copyright (c) 2014-2020  Arizona Board of Regents.
  *
  * This file is part of ndn-tools (Named Data Networking Essential Tools).
  * See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -17,22 +17,22 @@
  * ndn-tools, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-// #include "unit-under-test.hpp"
-// Unit being tested MUST be included first, to ensure header compiles on its own.
+// The unit being tested should be included first, to ensure the header compiles on its own.
 // For further information about test naming conventions, see
-// http://redmine.named-data.net/projects/nfd/wiki/UnitTesting
+// https://redmine.named-data.net/projects/nfd/wiki/UnitTesting
+//#include "unit-under-test.hpp"
 
 #include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tool_name {
 namespace tests {
-// Unit tests SHOULD go inside ndn::tool_name::tests namespace.
+// Unit tests should go inside the ndn::tool_name::tests namespace.
 
-// Common fixtures in ndn::tests can be imported.
+// Common fixtures in ndn::tests can be imported if needed.
 using namespace ndn::tests;
 
-// See http://redmine.named-data.net/projects/nfd/wiki/UnitTesting on how to name a test suite.
+// See https://redmine.named-data.net/projects/nfd/wiki/UnitTesting for a guide on how to name a test suite.
 BOOST_AUTO_TEST_SUITE(TestSkeleton)
 
 BOOST_AUTO_TEST_CASE(Test1)
@@ -40,16 +40,16 @@
   int i = 0;
 
   // For reference of available Boost.Test macros, see
-  // https://www.boost.org/doc/libs/1_58_0/libs/test/doc/html/utf/testing-tools/reference.html
+  // https://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/boost_test/testing_tools/summary.html
 
   BOOST_REQUIRE_NO_THROW(i = 1);
-  BOOST_REQUIRE_EQUAL(i, 1);
+  BOOST_CHECK_EQUAL(i, 1);
 }
 
 // Use UnitTestTimeFixture to mock clocks.
 BOOST_FIXTURE_TEST_CASE(Test2, UnitTestTimeFixture)
 {
-  // this->advanceClocks increments mock clocks.
+  // advanceClocks() increments mock clocks.
   boost::asio::io_service io;
   this->advanceClocks(io, time::milliseconds(500));
 }
diff --git a/wscript b/wscript
index b6fd731..772f89c 100644
--- a/wscript
+++ b/wscript
@@ -1,12 +1,12 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
+from waflib import Context, Logs, Utils
+import os, subprocess
+
 VERSION = '0.7'
 APPNAME = 'ndn-tools'
 GIT_TAG_PREFIX = 'ndn-tools-'
 
-from waflib import Utils, Context
-import os, subprocess
-
 def options(opt):
     opt.load(['compiler_cxx', 'gnu_dirs'])
     opt.load(['default-compiler-flags',
@@ -14,16 +14,16 @@
               'sphinx_build'],
              tooldir=['.waf-tools'])
 
-    opt_group = opt.add_option_group('Tools Options')
-
-    opt_group.add_option('--with-tests', action='store_true', default=False,
-                         help='Build unit tests')
+    optgrp = opt.add_option_group('Tools Options')
+    optgrp.add_option('--with-tests', action='store_true', default=False,
+                      help='Build unit tests')
 
     opt.recurse('tools')
 
 def configure(conf):
     conf.load(['compiler_cxx', 'gnu_dirs',
-               'default-compiler-flags', 'boost', 'sphinx_build'])
+               'default-compiler-flags', 'boost',
+               'sphinx_build'])
 
     conf.env.WITH_TESTS = conf.options.with_tests
 
@@ -37,9 +37,13 @@
 
     conf.check_boost(lib=boost_libs, mt=True)
     if conf.env.BOOST_VERSION_NUMBER < 105800:
-        conf.fatal('Minimum required Boost version is 1.58.0\n'
-                   'Please upgrade your distribution or manually install a newer version of Boost'
-                   ' (https://redmine.named-data.net/projects/nfd/wiki/Boost_FAQ)')
+        conf.fatal('The minimum supported version of Boost is 1.65.1.\n'
+                   'Please upgrade your distribution or manually install a newer version of Boost.\n'
+                   'For more information, see https://redmine.named-data.net/projects/nfd/wiki/Boost')
+    elif conf.env.BOOST_VERSION_NUMBER < 106501:
+        Logs.warn('WARNING: Using a version of Boost older than 1.65.1 is not officially supported and may not work.\n'
+                  'If you encounter any problems, please upgrade your distribution or manually install a newer version of Boost.\n'
+                  'For more information, see https://redmine.named-data.net/projects/nfd/wiki/Boost')
 
     conf.recurse('tools')