From c19988525d57719d14766de128f915d3e5656c87 Mon Sep 17 00:00:00 2001
From: Nils Gladitz <nilsgladitz@gmail.com>
Date: Fri, 7 Jun 2013 22:48:52 +0200
Subject: [PATCH] implemented new cmake_host_system_information command

---
 Source/cmCMakeHostSystemInformationCommand.cxx     | 99 ++++++++++++++++++++++
 Source/cmCMakeHostSystemInformationCommand.h       | 96 +++++++++++++++++++++
 Source/cmCommands.cxx                              |  2 +
 .../CMakeHostSystemInformation-BadArg1.cmake       |  1 +
 .../CMakeHostSystemInformation-BadArg2.cmake       |  1 +
 .../CMakeHostSystemInformation-BadArg3.cmake       |  1 +
 .../CMakeHostSystemInformationTest.cmake.in        | 30 +++++++
 Tests/CMakeTests/CMakeLists.txt                    |  1 +
 8 files changed, 231 insertions(+)
 create mode 100644 Source/cmCMakeHostSystemInformationCommand.cxx
 create mode 100644 Source/cmCMakeHostSystemInformationCommand.h
 create mode 100644 Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake
 create mode 100644 Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake
 create mode 100644 Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake
 create mode 100644 Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in

diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
new file mode 100644
index 0000000..915dc88
--- /dev/null
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -0,0 +1,99 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmCMakeHostSystemInformationCommand.h"
+
+#include <cmsys/SystemInformation.hxx>
+
+#include <cmsys/ios/sstream>
+
+// cmCMakeHostSystemInformation
+bool cmCMakeHostSystemInformationCommand
+::InitialPass(std::vector<std::string> const &args, cmExecutionStatus &)
+{
+  if(args.size() != 2 )
+    {
+    this->SetError("must be called with exactly two arguments.");
+    return false;
+    }
+
+  std::string key = args[0];
+  std::string variable = args[1];
+
+  cmsys::SystemInformation info;
+  info.RunCPUCheck();
+  info.RunOSCheck();
+  info.RunMemoryCheck();
+
+  if(key == "NUMBER_OF_LOGICAL_CORES")
+    {
+    this->SetValue(variable, info.GetNumberOfLogicalCPU());
+    }
+  else if(key == "NUMBER_OF_PHYSICAL_CORES")
+    {
+    this->SetValue(variable, info.GetNumberOfPhysicalCPU());
+    }
+  else if(key == "HOSTNAME")
+    {
+    this->SetValue(variable, info.GetHostname());
+    }
+  else if(key == "FQDN")
+    {
+    this->SetValue(variable, info.GetFullyQualifiedDomainName());
+    }
+  else if(key == "TOTAL_VIRTUAL_MEMORY")
+    {
+    this->SetValue(variable, info.GetTotalVirtualMemory());
+    }
+  else if(key == "AVAILABLE_VIRTUAL_MEMORY")
+    {
+    this->SetValue(variable, info.GetAvailableVirtualMemory());
+    }
+  else if(key == "TOTAL_PHYSICAL_MEMORY")
+    {
+    this->SetValue(variable, info.GetTotalPhysicalMemory());
+    }
+  else if(key == "AVAILABLE_PHYSICAL_MEMORY")
+    {
+    this->SetValue(variable, info.GetAvailablePhysicalMemory());
+    }
+  else
+    {
+    std::string e = "does not recognize <key> " + key;
+    this->SetError(e.c_str());
+    return false;
+    }
+
+  return true;
+}
+
+void cmCMakeHostSystemInformationCommand
+::SetValue(std::string const& variable, std::size_t value)
+{
+  cmsys_ios::stringstream tmp;
+  tmp << value;
+
+  this->SetValue(variable, tmp.str());
+}
+
+void cmCMakeHostSystemInformationCommand
+::SetValue(std::string const& variable, const char* value)
+{
+  std::string safe_string = value ? value : "";
+
+  this->SetValue(variable, safe_string);
+}
+
+void cmCMakeHostSystemInformationCommand
+::SetValue(std::string const& variable, std::string const& value)
+{
+  this->Makefile->AddDefinition(variable.c_str(), value.c_str());
+}
diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h
new file mode 100644
index 0000000..82dba4a
--- /dev/null
+++ b/Source/cmCMakeHostSystemInformationCommand.h
@@ -0,0 +1,96 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmCMakeHostSystemInformationCommand_h
+#define cmCMakeHostSystemInformationCommand_h
+
+#include "cmCommand.h"
+
+/** \class cmCMakeHostSystemInformationCommand
+ * \brief Query host system specific information
+ *
+ * cmCMakeHostSystemInformationCommand queries system information of
+ * the sytem on which CMake runs.
+ */
+class cmCMakeHostSystemInformationCommand : public cmCommand
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone()
+    {
+    return new cmCMakeHostSystemInformationCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args,
+               cmExecutionStatus &status);
+
+   /**
+   * This determines if the command is invoked when in script mode.
+   */
+  virtual bool IsScriptable() const { return true; }
+
+   /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() const
+    {
+    return "cmake_host_system_information";
+    }
+
+   /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() const
+    {
+    return "Query host system specific information.";
+    }
+
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation() const
+    {
+    return
+    "  cmake_host_system_information(<key> <variable>)\n"
+    "Queries system information of the host system on which cmake runs. "
+    "The queried value is stored in <variable>. "
+    "<key> selects the information to be queried and can be one of the "
+    "following values:\n"
+    "  NUMBER_OF_LOGICAL_CORES   = Number of logical cores.\n"
+    "  NUMBER_OF_PHYSICAL_CORES  = Number of physical cores.\n"
+    "  HOSTNAME                  = Hostname.\n"
+    "  FQDN                      = Fully qualified domain name.\n"
+    "  TOTAL_VIRTUAL_MEMORY      = "
+      "Total virtual memory in megabytes.\n"
+    "  AVAILABLE_VIRTUAL_MEMORY  = "
+      "Available virtual memory in megabytes.\n"
+    "  TOTAL_PHYSICAL_MEMORY     = "
+      "Total physical memory in megabytes.\n"
+    "  AVAILABLE_PHYSICAL_MEMORY = "
+      "Available physical memory in megabytes.\n"
+    ;
+    }
+
+  cmTypeMacro(cmCMakeHostSystemInformationCommand, cmCommand);
+
+  private:
+  void SetValue(std::string const& variable, std::size_t value);
+  void SetValue(std::string const& variable, const char* value);
+  void SetValue(std::string const& variable, std::string const& value);
+};
+
+#endif
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 3cfbf43..1e2a85c 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -14,6 +14,7 @@
 #include "cmAddCompileOptionsCommand.cxx"
 #include "cmAuxSourceDirectoryCommand.cxx"
 #include "cmBuildNameCommand.cxx"
+#include "cmCMakeHostSystemInformationCommand.cxx"
 #include "cmElseIfCommand.cxx"
 #include "cmExportCommand.cxx"
 #include "cmExportLibraryDependencies.cxx"
@@ -56,6 +57,7 @@ void GetPredefinedCommands(std::list<cmCommand*>&
   commands.push_back(new cmAddCompileOptionsCommand);
   commands.push_back(new cmAuxSourceDirectoryCommand);
   commands.push_back(new cmBuildNameCommand);
+  commands.push_back(new cmCMakeHostSystemInformationCommand);
   commands.push_back(new cmElseIfCommand);
   commands.push_back(new cmExportCommand);
   commands.push_back(new cmExportLibraryDependenciesCommand);
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake
new file mode 100644
index 0000000..1655eb4
--- /dev/null
+++ b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake
@@ -0,0 +1 @@
+cmake_host_system_information(HOSTNAME)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake
new file mode 100644
index 0000000..8a2bc5c
--- /dev/null
+++ b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake
@@ -0,0 +1 @@
+cmake_host_system_information(HOSTNAME FQDN RESULT)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake
new file mode 100644
index 0000000..cadde79
--- /dev/null
+++ b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake
@@ -0,0 +1 @@
+cmake_host_system_information(FOOBAR RESULT)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in b/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in
new file mode 100644
index 0000000..ed93579
--- /dev/null
+++ b/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in
@@ -0,0 +1,30 @@
+set(BadArg1-RESULT 1)
+set(BadArg1-STDERR "must be called with exactly two arguments")
+set(BadArg2-RESULT 1)
+set(BadArg2-STDERR "must be called with exactly two arguments")
+set(BadArg3-RESULT 1)
+set(BadArg3-STDERR "does not recognize <key> FOOBAR")
+
+function(try_and_print key)
+	cmake_host_system_information(${key} RESULT)
+	message(STATUS "[${key}] [${RESULT}]")
+endfunction()
+
+message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
+
+try_and_print(NUMBER_OF_LOGICAL_CORES)
+try_and_print(NUMBER_OF_PHYSICAL_CORES)
+try_and_print(HOSTNAME)
+try_and_print(FQDN)
+try_and_print(TOTAL_VIRTUAL_MEMORY)
+try_and_print(AVAILABLE_VIRTUAL_MEMORY)
+try_and_print(TOTAL_PHYSICAL_MEMORY)
+try_and_print(AVAILABLE_PHYSICAL_MEMORY)
+
+include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake")
+
+check_cmake_test(CMakeHostSystemInformation
+	BadArg1
+	BadArg2
+	BadArg3
+)
diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt
index b049995..344b772 100644
--- a/Tests/CMakeTests/CMakeLists.txt
+++ b/Tests/CMakeTests/CMakeLists.txt
@@ -32,6 +32,7 @@ AddCMakeTest(CompilerIdVendor "")
 AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>")
 AddCMakeTest(PushCheckState "")
 AddCMakeTest(While "")
+AddCMakeTest(CMakeHostSystemInformation "")
 
 AddCMakeTest(FileDownload "")
 set_property(TEST CMake.FileDownload PROPERTY
-- 
1.8.1.2

