build+core: Add printing of version number in daemons and tools

This commit also changes how version number is handled.  Version is now
fully controlled from top-level wscript.  In addition to that, a new
NFD_VERSION_BUILD_STRING macro is set to include more detailed
information, including commit ID (e.g., "0.1.0-rc1-1-g5c86570").

Change-Id: I448eb627e0c42dc814de1107cf7bb0dc94fa2a89
Refs: #1575
diff --git a/tools/ndn-autoconfig-server.cpp b/tools/ndn-autoconfig-server.cpp
index abcdf5c..9873bde 100644
--- a/tools/ndn-autoconfig-server.cpp
+++ b/tools/ndn-autoconfig-server.cpp
@@ -22,6 +22,7 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  **/
 
+#include "version.hpp"
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/security/key-chain.hpp>
 
@@ -29,11 +30,12 @@
 void
 usage(const char* programName)
 {
-  std::cout << "Usage:\n" << programName  << " [-h] Uri \n"
-  "   -h print usage and exit\n"
-  "\n"
-  "   Uri - a FaceMgmt URI\n"
-  << std::endl;
+  std::cout << "Usage:\n" << programName  << " [-h] [-V] Uri \n"
+            << "   -h  - print usage and exit\n"
+            << "   -V  - print version number and exit\n"
+            << "\n"
+            << "   Uri - a FaceMgmt URI\n"
+            << std::endl;
 }
 
 using namespace ndn;
@@ -92,35 +94,33 @@
   int opt;
   const char* programName = argv[0];
 
-  while ((opt = getopt(argc, argv, "h")) != -1)
-  {
-    switch (opt)
-    {
-      case 'h':
-        usage(programName);
-        return 0;
-
-      default:
-        usage(programName);
-        return 1;
+  while ((opt = getopt(argc, argv, "hV")) != -1) {
+    switch (opt) {
+    case 'h':
+      usage(programName);
+      return 0;
+    case 'V':
+      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+      return 0;
+    default:
+      usage(programName);
+      return 1;
     }
   }
 
-  if (argc != optind + 1)
-  {
+  if (argc != optind + 1) {
     usage(programName);
     return 1;
   }
-  // get the configured face managment uri
+  // get the configured face management uri
   NdnAutoconfigServer producer(argv[optind]);
 
-  try
-  {
+  try {
     producer.listen();
   }
-  catch (std::exception& error)
-  {
+  catch (const std::exception& error) {
     std::cerr << "ERROR: " << error.what() << std::endl;
+    return 1;
   }
   return 0;
 }
diff --git a/tools/ndn-autoconfig.cpp b/tools/ndn-autoconfig.cpp
index 84a73d3..fe8ce19 100644
--- a/tools/ndn-autoconfig.cpp
+++ b/tools/ndn-autoconfig.cpp
@@ -22,6 +22,8 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  **/
 
+#include "version.hpp"
+
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/management/nfd-controller.hpp>
 #include <ndn-cxx/security/key-chain.hpp>
@@ -37,6 +39,15 @@
 
 namespace tools {
 
+void
+usage(const char* programName)
+{
+  std::cout << "Usage:\n" << programName  << " [-h] [-V]\n"
+            << "   -h  - print usage and exit\n"
+            << "   -V  - print version number and exit\n"
+            << std::endl;
+}
+
 class NdnAutoconfig
 {
 public:
@@ -311,17 +322,30 @@
 } // namespace tools
 
 int
-main()
+main(int argc, char** argv)
 {
-  try
-    {
-      tools::NdnAutoconfig autoConfigInstance;
+  int opt;
+  const char* programName = argv[0];
 
-      autoConfigInstance.discoverHubStage1();
+  while ((opt = getopt(argc, argv, "hV")) != -1) {
+    switch (opt) {
+    case 'h':
+      tools::usage(programName);
+      return 0;
+    case 'V':
+      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+      return 0;
     }
-  catch (const std::exception& error)
-    {
-      std::cerr << "ERROR: " << error.what() << std::endl;
-    }
+  }
+
+  try {
+    tools::NdnAutoconfig autoConfigInstance;
+
+    autoConfigInstance.discoverHubStage1();
+  }
+  catch (const std::exception& error) {
+    std::cerr << "ERROR: " << error.what() << std::endl;
+    return 1;
+  }
   return 0;
 }
diff --git a/tools/ndn-tlv-peek.cpp b/tools/ndn-tlv-peek.cpp
index ee0436f..ec0a9b0 100644
--- a/tools/ndn-tlv-peek.cpp
+++ b/tools/ndn-tlv-peek.cpp
@@ -25,6 +25,8 @@
  * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
  */
 
+#include "version.hpp"
+
 #include <boost/asio.hpp>
 
 #include <ndn-cxx/face.hpp>
@@ -63,7 +65,9 @@
       "   [-l lifetime] - set InterestLifetime in time::milliseconds\n"
       "   [-p]          - print payload only, not full packet\n"
       "   [-w timeout]  - set Timeout in time::milliseconds\n"
-      "   [-h]          - print help and exit\n\n";
+      "   [-h]          - print help and exit\n"
+      "   [-V]          - print version and exit\n"
+      "\n";
     exit(1);
   }
 
@@ -228,37 +232,40 @@
 {
   int option;
   ndntlvpeek::NdnTlvPeek ndnTlvPeek (argv[0]);
-  while ((option = getopt(argc, argv, "hfrm:M:l:pw:")) != -1)
-    {
-      switch (option) {
-        case 'h':
-          ndnTlvPeek.usage();
-          break;
-        case 'f':
-          ndnTlvPeek.setMustBeFresh();
-          break;
-        case 'r':
-          ndnTlvPeek.setRightmostChildSelector();
-          break;
-        case 'm':
-          ndnTlvPeek.setMinSuffixComponents(atoi(optarg));
-          break;
-        case 'M':
-          ndnTlvPeek.setMaxSuffixComponents(atoi(optarg));
-          break;
-        case 'l':
-          ndnTlvPeek.setInterestLifetime(atoi(optarg));
-          break;
-        case 'p':
-          ndnTlvPeek.setPayloadOnly();
-          break;
-        case 'w':
-          ndnTlvPeek.setTimeout(atoi(optarg));
-          break;
-        default:
-          ndnTlvPeek.usage();
-      }
+  while ((option = getopt(argc, argv, "hfrm:M:l:pw:V")) != -1) {
+    switch (option) {
+    case 'h':
+      ndnTlvPeek.usage();
+      break;
+    case 'f':
+      ndnTlvPeek.setMustBeFresh();
+      break;
+    case 'r':
+      ndnTlvPeek.setRightmostChildSelector();
+      break;
+    case 'm':
+      ndnTlvPeek.setMinSuffixComponents(atoi(optarg));
+      break;
+    case 'M':
+      ndnTlvPeek.setMaxSuffixComponents(atoi(optarg));
+      break;
+    case 'l':
+      ndnTlvPeek.setInterestLifetime(atoi(optarg));
+      break;
+    case 'p':
+      ndnTlvPeek.setPayloadOnly();
+      break;
+    case 'w':
+      ndnTlvPeek.setTimeout(atoi(optarg));
+      break;
+    case 'V':
+      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+      return 0;
+    default:
+      ndnTlvPeek.usage();
+      break;
     }
+  }
 
   argc -= optind;
   argv += optind;
diff --git a/tools/ndn-tlv-poke.cpp b/tools/ndn-tlv-poke.cpp
index 5ff5a50..f90b735 100644
--- a/tools/ndn-tlv-poke.cpp
+++ b/tools/ndn-tlv-poke.cpp
@@ -25,6 +25,8 @@
  * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
  */
 
+#include "version.hpp"
+
 #include <boost/utility.hpp>
 
 #include <ndn-cxx/face.hpp>
@@ -63,7 +65,9 @@
       "   [-F]          - set FinalBlockId to the last component of Name\n"
       "   [-x]          - set FreshnessPeriod in time::milliseconds\n"
       "   [-w timeout]  - set Timeout in time::milliseconds\n"
-      "   [-h]          - print help and exit\n\n";
+      "   [-h]          - print help and exit\n"
+      "   [-V]          - print version and exit\n"
+      "\n";
     exit(1);
   }
 
@@ -228,35 +232,37 @@
 {
   int option;
   ndntlvpoke::NdnTlvPoke ndnTlvPoke(argv[0]);
-  while ((option = getopt(argc, argv, "hfDi:Fx:w:")) != -1)
-    {
-      switch (option) {
-        case 'h':
-          ndnTlvPoke.usage();
-          break;
-        case 'f':
-          ndnTlvPoke.setForceData();
-          break;
-        case 'D':
-          ndnTlvPoke.setUseDigestSha256();
-          break;
-        case 'i':
-          ndnTlvPoke.setIdentityName(optarg);
-          break;
-        case 'F':
-          ndnTlvPoke.setLastAsFinalBlockId();
-          break;
-        case 'x':
-          ndnTlvPoke.setFreshnessPeriod(atoi(optarg));
-          break;
-        case 'w':
-          ndnTlvPoke.setTimeout(atoi(optarg));
-          break;
-        default:
-          ndnTlvPoke.usage();
-          break;
-      }
+  while ((option = getopt(argc, argv, "hfDi:Fx:w:V")) != -1) {
+    switch (option) {
+    case 'h':
+      ndnTlvPoke.usage();
+      break;
+    case 'f':
+      ndnTlvPoke.setForceData();
+      break;
+    case 'D':
+      ndnTlvPoke.setUseDigestSha256();
+      break;
+    case 'i':
+      ndnTlvPoke.setIdentityName(optarg);
+      break;
+    case 'F':
+      ndnTlvPoke.setLastAsFinalBlockId();
+      break;
+    case 'x':
+      ndnTlvPoke.setFreshnessPeriod(atoi(optarg));
+      break;
+    case 'w':
+      ndnTlvPoke.setTimeout(atoi(optarg));
+      break;
+    case 'V':
+      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+      return 0;
+    default:
+      ndnTlvPoke.usage();
+      break;
     }
+  }
 
   argc -= optind;
   argv += optind;
diff --git a/tools/nfd-autoreg.cpp b/tools/nfd-autoreg.cpp
index 1de90ab..40ea488 100644
--- a/tools/nfd-autoreg.cpp
+++ b/tools/nfd-autoreg.cpp
@@ -32,6 +32,7 @@
 #include <boost/program_options/variables_map.hpp>
 #include <boost/program_options/parsers.hpp>
 
+#include "version.hpp"
 #include "core/face-uri.hpp"
 #include "network.hpp"
 
@@ -248,6 +249,7 @@
        "Whitelisted network, e.g., 192.168.2.0/24 or ::1/128")
       ("blacklist,b", po::value<std::vector<Network> >(&m_blackList)->composing(),
        "Blacklisted network, e.g., 192.168.2.32/30 or ::1/128")
+      ("version,V", "show version and exit")
       ;
 
     po::variables_map options;
@@ -269,6 +271,12 @@
         return 0;
       }
 
+    if (options.count("version"))
+      {
+        std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+        return 0;
+      }
+
     if (m_autoregPrefixes.empty())
       {
         std::cerr << "ERROR: at least one --prefix must be specified" << std::endl << std::endl;
diff --git a/tools/nfd-start.sh b/tools/nfd-start.sh
index 9fe9424..4df12d7 100755
--- a/tools/nfd-start.sh
+++ b/tools/nfd-start.sh
@@ -1,5 +1,25 @@
 #!@BASH@
 
+VERSION="@VERSION@"
+
+case "$1" in
+  -h)
+    echo Usage
+    echo $0
+    echo "  Start NFD and RIB Management daemon"
+    exit 0
+    ;;
+  -V)
+    echo $VERSION
+    exit 0
+    ;;
+  "") ;; # do nothing
+  *)
+    echo "Unrecognized option $1"
+    exit 1
+    ;;
+esac
+
 hasProcess() {
   local processName=$1
 
diff --git a/tools/nfd-status-http-server.py b/tools/nfd-status-http-server.py
index 52acae6..6e0f167 100755
--- a/tools/nfd-status-http-server.py
+++ b/tools/nfd-status-http-server.py
@@ -164,8 +164,15 @@
                         help="Enable HTTP robots to crawl; disabled by default.")
     parser.add_argument("-v", default=False, dest="verbose", action="store_true",
                         help="Verbose mode.")
+    parser.add_argument("--version", default=False, dest="version", action="store_true",
+                        help="Show version and exit")
 
     args = vars(parser.parse_args())
+
+    if args['version']:
+        print "@VERSION@"
+        return
+
     localPort = args["port"]
     localAddr = args["addr"]
     verbose = args["verbose"]
diff --git a/tools/nfd-status.cpp b/tools/nfd-status.cpp
index 1c1f415..9e8fa28 100644
--- a/tools/nfd-status.cpp
+++ b/tools/nfd-status.cpp
@@ -25,6 +25,8 @@
  * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
  */
 
+#include "version.hpp"
+
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/name.hpp>
 #include <ndn-cxx/interest.hpp>
@@ -56,7 +58,10 @@
       "  [-h] - print this help message\n"
       "  [-v] - retrieve version information\n"
       "  [-f] - retrieve face status information\n"
-      "  [-b] - retrieve FIB information\n\n"
+      "  [-b] - retrieve FIB information\n"
+      "\n"
+      "  [-V] - show version information of nfd-status and exit\n"
+      "\n"
       "If no options are provided, all information is retrieved.\n"
       ;
   }
@@ -299,12 +304,12 @@
 
 }
 
-int main( int argc, char* argv[] )
+int main(int argc, char* argv[])
 {
   int option;
-  ndn::NfdStatus nfdStatus (argv[0]);
+  ndn::NfdStatus nfdStatus(argv[0]);
 
-  while ((option = getopt(argc, argv, "hvfb")) != -1) {
+  while ((option = getopt(argc, argv, "hvfbV")) != -1) {
     switch (option) {
     case 'h':
       nfdStatus.usage();
@@ -318,6 +323,9 @@
     case 'b':
       nfdStatus.enableFibEnumerationRetrieval();
       break;
+    case 'V':
+      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+      return 0;
     default:
       nfdStatus.usage();
       return 1;
diff --git a/tools/nfd-stop.sh b/tools/nfd-stop.sh
index c0b46bd..ed55929 100755
--- a/tools/nfd-stop.sh
+++ b/tools/nfd-stop.sh
@@ -1,4 +1,24 @@
 #!@BASH@
 
+VERSION="@VERSION@"
+
+case "$1" in
+  -h)
+    echo Usage
+    echo $0
+    echo "  Stop NFD and RIB Management daemon"
+    exit 0
+    ;;
+  -V)
+    echo $VERSION
+    exit 0
+    ;;
+  "") ;; # do nothing
+  *)
+    echo "Unrecognized option $1"
+    exit 1
+    ;;
+esac
+
 sudo killall nrd
 sudo killall nfd
diff --git a/tools/nfdc.cpp b/tools/nfdc.cpp
index 729dcb8..1b3499b 100644
--- a/tools/nfdc.cpp
+++ b/tools/nfdc.cpp
@@ -22,7 +22,10 @@
  * 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 "nfdc.hpp"
+#include "version.hpp"
+
 #include <boost/lexical_cast.hpp>
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/regex_find_format.hpp>
@@ -31,8 +34,9 @@
 void
 usage(const char* programName)
 {
-  std::cout << "Usage:\n" << programName  << " [-h] COMMAND [<Command Options>]\n"
+  std::cout << "Usage:\n" << programName  << " [-h] [-V] COMMAND [<Command Options>]\n"
     "       -h print usage and exit\n"
+    "       -V print version and exit\n"
     "\n"
     "   COMMAND can be one of the following:\n"
     "       register [-I] [-C] [-c cost] name <faceId | faceUri>\n"
@@ -402,6 +406,11 @@
     return 0;
   }
 
+  if (!strcmp(argv[1], "-V")) {
+    std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+    return 0;
+  }
+
   ::optind = 2; //start reading options from 2nd argument i.e. Command
   int opt;
   while ((opt = ::getopt(argc, argv, "ICc:")) != -1) {