From 0ac14cf55aca6cf63aad9828ef56fad20f5209cb Mon Sep 17 00:00:00 2001
From: Patrick Gansterer <paroga@paroga.com>
Date: Sat, 14 Jul 2012 12:03:23 +0200
Subject: [PATCH 3/4] VS: Add support for CMAKE_WINCE_SDK varibale

If set CMake will look up the SDK in the WCE.VCPlatform.config
and if successful, the CMake variables for cross compiling will
be set to the corresponding values.
---
 Source/cmGlobalVisualStudio8Generator.cxx |  238 +++++++++++++++++++++++++++++
 Source/cmGlobalVisualStudio8Generator.h   |   19 ++-
 2 files changed, 255 insertions(+), 2 deletions(-)

diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 1c6385d..a010f20 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -15,6 +15,169 @@
 #include "cmMakefile.h"
 #include "cmake.h"
 #include "cmGeneratedFileStream.h"
+#include "cmXMLParser.h"
+
+
+// This class is used to parse XML with configuration
+// of installed SDKs in system
+class cmGlobalVisualStudio8Generator::cmWCEConfigParser : public cmXMLParser
+{
+public:
+  cmWCEConfigParser(const char* name)
+      : RequiredName(name)
+      , FoundRequiredName(false)
+    {
+    }
+
+  bool Found() const {return this->FoundRequiredName;}
+
+  std::string GetOSVersion() const
+    {
+    if (this->OSMinorVersion.empty())
+      {
+      return OSMajorVersion;
+      }
+
+    return OSMajorVersion + "." + OSMinorVersion;
+    }
+
+  const char* GetInstructionset() const
+    {
+    std::map<std::string, std::string>::const_iterator it =
+      this->Macros.find("INSTRUCTIONSET");
+    if (it != this->Macros.end())
+      {
+      return it->second.c_str();
+      }
+
+    return 0;
+    }
+
+  const char* GetArchitectureId() const
+    {
+    struct Instructionset2ArchitectureId
+      {
+        const char* Instructionset;
+        const char* ArchitectureId;
+      };
+
+    static const Instructionset2ArchitectureId convertInfo[] =
+      {
+        {"ARMV4",     "ARM" },
+        {"ARMV4I",    "THUMB"},
+        {"MIPSII",    "MIPS"},
+        {"MIPSII_FP", "MIPSFPU"},
+        {"MIPSIV",    "MIPS16"},
+        {"MIPSIV_FP", "MIPSFPU16"},
+        {"SH4",       "SH4"},
+        {"x86",       "X86"}
+      };
+
+    const char* instructionset = this->GetInstructionset();
+
+    if (!instructionset)
+      {
+      return 0;
+      }
+
+    // find corresponding flag value for obtained architecture
+    for(int i = 0; i < sizeof(convertInfo) / sizeof(convertInfo[0]); ++i)
+      {
+      if(strcmp(instructionset, convertInfo[i].Instructionset) == 0)
+        {
+        return convertInfo[i].ArchitectureId;
+        }
+      }
+
+    return 0;
+    }
+
+  virtual void StartElement(const char* name, const char** attributes)
+    {
+    if(this->FoundRequiredName)
+      {
+      return;
+      }
+
+    this->CharacterData.clear();
+
+    if(strcmp(name, "PlatformData") == 0)
+      {
+      this->PlatformName.clear();
+      this->OSMajorVersion.clear();
+      this->OSMinorVersion.clear();
+      this->Macros.clear();
+      }
+
+    if(strcmp(name, "Macro") == 0)
+      {
+      std::string name;
+      std::string value;
+
+      for(const char** attr = attributes; *attr; attr += 2)
+        {
+        if(strcmp(attr[0], "Name") == 0)
+          {
+          name = attr[1];
+          }
+        else if(strcmp(attr[0], "Value") == 0)
+          {
+          value = attr[1];
+          }
+        }
+
+      if(!name.empty())
+        {
+        this->Macros[name] = value;
+        }
+      }
+    }
+
+  void EndElement(const char* name)
+    {
+    if(this->FoundRequiredName)
+      {
+      return;
+      }
+
+    if(strcmp(name, "PlatformName") == 0)
+      {
+      this->PlatformName = this->CharacterData;
+      }
+    else if(strcmp(name, "OSMajorVersion") == 0)
+      {
+      this->OSMajorVersion = this->CharacterData;
+      }
+    else if(strcmp(name, "OSMinorVersion") == 0)
+      {
+      this->OSMinorVersion = this->CharacterData;
+      }
+    else if(strcmp(name, "Platform") == 0)
+      {
+      if(this->PlatformName == this->RequiredName)
+        {
+        this->FoundRequiredName = true;
+        }
+      }
+    }
+
+   void CharacterDataHandler(const char* data, int length)
+   {
+     this->CharacterData.append(data, length);
+   }
+
+private:
+  std::string CharacterData;
+
+  std::string PlatformName;
+  std::string OSMajorVersion;
+  std::string OSMinorVersion;
+  std::map<std::string, std::string> Macros;
+
+  bool FoundRequiredName;
+  const char* RequiredName;
+};
+
 
 //----------------------------------------------------------------------------
 cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator()
@@ -22,6 +185,7 @@ cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator()
   this->VersionId = "MSVC80";
   this->FindMakeProgramFile = "CMakeVS8FindMake.cmake";
   this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms";
+  this->WindowsCE = false;
 }
 
 //----------------------------------------------------------------------------
@@ -54,13 +218,87 @@ void cmGlobalVisualStudio8Generator
 }
 
 //----------------------------------------------------------------------------
+void cmGlobalVisualStudio8Generator::AddTryCompileCacheEntries(cmake& cm)
+{
+  const char* sdk =
+    this->GetCMakeInstance()->GetCacheDefinition("CMAKE_WINCE_SDK");
+  if(sdk)
+    {
+    cm.AddCacheEntry("CMAKE_WINCE_SDK", sdk, "", cmCacheManager::INTERNAL);
+    }
+}
+
+//----------------------------------------------------------------------------
 void cmGlobalVisualStudio8Generator::Configure()
 {
+  this->ConfigurePlatform();
   this->cmGlobalVisualStudio7Generator::Configure();
   this->CreateGUID(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
 }
 
 //----------------------------------------------------------------------------
+void cmGlobalVisualStudio8Generator::ConfigurePlatform()
+{
+  const char* sdk =
+    this->GetCMakeInstance()->GetCacheDefinition("CMAKE_WINCE_SDK");
+  if(!sdk)
+    {
+    this->PlatformName = "Win32";
+    return;
+    }
+
+  if(!this->ConfigurePlatformSDK(sdk))
+    {
+    cmSystemTools::Error(
+      "CMAKE_WINCE_SDK must be a valid Windows CE platform SDK!");
+    cmSystemTools::SetFatalErrorOccured();
+    }
+}
+
+//----------------------------------------------------------------------------
+bool cmGlobalVisualStudio8Generator::ConfigurePlatformSDK(const char* name)
+{
+  std::string vskey = this->GetRegistryBase();
+  vskey += "\\Setup\\VS;ProductDir";
+
+  std::string vsInstallPath;
+  if(!cmSystemTools::ReadRegistryValue(vskey.c_str(), vsInstallPath))
+    {
+    return false;
+    }
+  cmSystemTools::ConvertToUnixSlashes(vsInstallPath);
+
+  const std::string configFilename =
+    vsInstallPath + "/VC/vcpackages/WCE.VCPlatform.config";
+
+  // parse XML containing all information that we need
+  cmWCEConfigParser parser(name);
+  parser.ParseFile(configFilename.c_str());
+
+  if(!parser.Found())
+    {
+    return false;
+    }
+
+  this->ArchitectureId = parser.GetArchitectureId();
+  this->PlatformName = name;
+  this->WindowsCE = true;
+
+  this->GetCMakeInstance()->AddCacheEntry("CMAKE_SYSTEM_NAME",
+    "WindowsCE", "", cmCacheManager::INTERNAL);
+  this->GetCMakeInstance()->AddCacheEntry("CMAKE_SYSTEM_VERSION",
+    parser.GetOSVersion().c_str(), "", cmCacheManager::INTERNAL);
+  this->GetCMakeInstance()->AddCacheEntry("CMAKE_SYSTEM_PROCESSOR",
+    parser.GetArchitectureId(), "", cmCacheManager::INTERNAL);
+  this->GetCMakeInstance()->AddCacheEntry("CMAKE_C_COMPILER",
+    "cl", "", cmCacheManager::INTERNAL);
+  this->GetCMakeInstance()->AddCacheEntry("CMAKE_CXX_COMPILER",
+    "cl", "", cmCacheManager::INTERNAL);
+
+  return this->ArchitectureId && !this->PlatformName.empty();
+}
+
+//----------------------------------------------------------------------------
 std::string cmGlobalVisualStudio8Generator::GetUserMacrosDirectory()
 {
   // Some VS8 sp0 versions cannot run macros.
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index 6982896..ffb66a4 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -32,11 +32,15 @@ public:
     return cmGlobalVisualStudio8Generator::GetActualName();}
   static const char* GetActualName() {return "Visual Studio 8 2005";}
 
-  virtual const char* GetPlatformName() const {return "Win32";}
+  virtual const char* GetPlatformName() const {
+    return this->PlatformName.c_str();}
 
   /** Get the documentation entry for this generator.  */
   virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-  
+
+  ///! Add inital cache entries for TryCompile.
+  virtual void AddTryCompileCacheEntries(cmake& cm);
+
   ///! Create a local generator appropriate to this Global Generator
   virtual cmLocalGenerator *CreateLocalGenerator();
 
@@ -64,6 +68,9 @@ public:
       LinkLibraryDependencies and link to .sln dependencies. */
   virtual bool NeedLinkLibraryDependencies(cmTarget& target);
 
+  /** Return true if building for Windows CE */
+  virtual bool TargetsWindowsCE() const { return this->WindowsCE; }
+
 protected:
   virtual const char* GetIDEVersion() { return "8.0"; }
 
@@ -81,5 +88,13 @@ protected:
   virtual bool ComputeTargetDepends();
   virtual void WriteProjectDepends(std::ostream& fout, const char* name,
                                    const char* path, cmTarget &t);
+
+private:
+  class cmWCEConfigParser;
+
+  void ConfigurePlatform();
+  bool ConfigurePlatformSDK(const char* name);
+  std::string PlatformName;
+  bool WindowsCE;
 };
 #endif
-- 
1.7.10.msysgit.1

