Просмотр исходного кода

added registry entry support and windows app support

Ken Martin 24 лет назад
Родитель
Сommit
639f1fa239

+ 1 - 1
Source/EXEHeader.dsptemplate

@@ -14,7 +14,7 @@
 # EXTRA_DEFINES == compiler defines
 # OUTPUT_LIBNAME  == name of output library
 # CM_LIBRARIES == libraries linked in 
-# TARGTYPE "Win32 (x86) Application" 0x0101
+# TARGTYPE "Win32 (x86) Application" 0x0103
 
 CFG=OUTPUT_LIBNAME - Win32 Debug
 !MESSAGE This is not a valid makefile. To build this project using NMAKE,

+ 130 - 0
Source/EXEWinHeader.dsptemplate

@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="pcbuilder" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# CM DSP Header file
+# This file is read by the build system of cm, and is used as the top part of
+# a microsoft project dsp header file
+# IF this is in a dsp file, then it is not the header, but has
+# already been used, so do not edit here...
+
+# variables to REPLACE
+# 
+# BUILD_INCLUDES == include path
+# EXTRA_DEFINES == compiler defines
+# OUTPUT_LIBNAME  == name of output library
+# CM_LIBRARIES == libraries linked in 
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=OUTPUT_LIBNAME - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "OUTPUT_LIBNAME.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "OUTPUT_LIBNAME.mak" CFG="OUTPUT_LIBNAME - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "OUTPUT_LIBNAME - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "OUTPUT_LIBNAME - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "OUTPUT_LIBNAME - Win32 Release MinSize" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GR /GX /Zm1000 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS"  /FD /c
+# ADD CPP /nologo /MD /W3 /GR /GX /Zm1000 /O2 /D "WIN32" BUILD_INCLUDES EXTRA_DEFINES /D "NDEBUG" /D "_WINDOWS" /D "_MBCS"  /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386  /IGNORE:4089
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386  /IGNORE:4089
+CM_MULTILINE_OPTIMIZED_LIBRARIES
+CM_MULTILINE_LIBRARIES
+
+!ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP  /W3 /GR /Zm1000 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS"  /FD /GZ /c
+# ADD CPP /nologo /W3 /MDd /GR /Gm /GX /Zm1000 /ZI /Od /D "WIN32" BUILD_INCLUDES EXTRA_DEFINES /D "_DEBUG" /D "_WINDOWS" /D "_MBCS"  /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /IGNORE:4089
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /IGNORE:4089
+CM_MULTILINE_DEBUG_LIBRARIES
+CM_MULTILINE_LIBRARIES
+
+
+!ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 Release MinSize"
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseMinSize"
+# PROP BASE Intermediate_Dir "ReleaseMinSize"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseMinSize"
+# PROP Intermediate_Dir "ReleaseMinSize"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GR /GX /Zm1000 /O1 /Gs /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS"  /FD /c
+# ADD CPP /nologo /MD /W3 /GR /GX /Zm1000 /O1 /Gs /D "WIN32" BUILD_INCLUDES EXTRA_DEFINES /D "NDEBUG" /D "_WINDOWS" /D "_MBCS"  /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /IGNORE:4089
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /IGNORE:4089
+CM_MULTILINE_OPTIMIZED_LIBRARIES
+CM_MULTILINE_LIBRARIES
+
+!ENDIF 
+
+# Begin Target
+
+# Name "OUTPUT_LIBNAME - Win32 Release"
+# Name "OUTPUT_LIBNAME - Win32 Debug"
+# Name "OUTPUT_LIBNAME - Win32 Release MinSize"

+ 13 - 3
Source/cmAddExecutableCommand.cxx

@@ -49,11 +49,21 @@ bool cmAddExecutableCommand::Invoke(std::vector<std::string>& args)
     this->SetError("called with incorrect number of arguments");
     return false;
     }
-  
+
   std::vector<std::string>::iterator s = args.begin();
-  std::vector<std::string> srclists(++s, args.end());
+  ++s;
+  if (*s == "WIN32")
+    {
+    ++s;
+    std::vector<std::string> srclists(s, args.end());
+    m_Makefile->AddExecutable(args[0].c_str(),srclists, true); 
+    }
+  else
+    {
+    std::vector<std::string> srclists(s, args.end());
+    m_Makefile->AddExecutable(args[0].c_str(),srclists, false); 
+    }
   
-  m_Makefile->AddExecutable(args[0].c_str(),srclists); 
   return true;
 }
 

+ 7 - 1
Source/cmAddExecutableCommand.h

@@ -86,7 +86,13 @@ public:
   virtual const char* GetFullDocumentation()
     {
     return
-      "ADD_EXECUTABLE(exename srclist srclist srclist ...)";
+      "ADD_EXECUTABLE(exename srclist srclist srclist ...)\n"
+      "ADD_EXECUTABLE(exename WIN32 srclist srclist srclist ...)"
+      "This command adds an executable target to the current directory. "
+      "The executable will be built from the source files / source lists "
+      "specified. The second argument to this command can be WIN32 "
+      "which indicates that the executable (when compiled on windows) "
+      "is a windows app (using WinMain)not a console app (using main).";
     }
   
   cmTypeMacro(cmAddExecutableCommand, cmCommand);

+ 10 - 1
Source/cmDSPMakefile.cxx

@@ -100,6 +100,9 @@ void cmDSPMakefile::OutputDSPFile()
       case cmTarget::EXECUTABLE:
         this->SetBuildType(EXECUTABLE,l->first.c_str());
         break;
+      case cmTarget::WIN32_EXECUTABLE:
+        this->SetBuildType(WIN32_EXECUTABLE,l->first.c_str());
+        break;
       case cmTarget::UTILITY:
         this->SetBuildType(UTILITY, l->first.c_str());
         break;
@@ -390,6 +393,12 @@ void cmDSPMakefile::SetBuildType(BuildType b, const char *libName)
       m_DSPFooterTemplate = root;
       m_DSPFooterTemplate += "/EXEFooter.dsptemplate";
       break;
+    case WIN32_EXECUTABLE:
+      m_DSPHeaderTemplate = m_Makefile->GetHomeDirectory();
+      m_DSPHeaderTemplate += "/CMake/Source/EXEWinHeader.dsptemplate";
+      m_DSPFooterTemplate = m_Makefile->GetHomeDirectory();
+      m_DSPFooterTemplate += "/CMake/Source/EXEFooter.dsptemplate";
+      break;
     case UTILITY:
       m_DSPHeaderTemplate = root;
       m_DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
@@ -461,7 +470,7 @@ void cmDSPMakefile::WriteDSPHeader(std::ostream& fout, const char *libName,
     {
     // add libraries to executables and dlls (but never include
     // a library in a library, bad recursion)
-    if (!(target.GetType() == cmTarget::LIBRARY) || 
+    if (target.GetType() != cmTarget::LIBRARY || 
         (m_LibraryBuildType == DLL && libName != j->first))
       {
       std::string lib = j->first;

+ 1 - 1
Source/cmDSPMakefile.h

@@ -57,7 +57,7 @@ public:
   cmDSPMakefile(cmMakefile*);
   ~cmDSPMakefile();
   void OutputDSPFile();
-  enum BuildType {STATIC_LIBRARY, DLL, EXECUTABLE, UTILITY};
+  enum BuildType {STATIC_LIBRARY, DLL, EXECUTABLE, WIN32_EXECUTABLE, UTILITY};
 
   /**
    * Specify the type of the build: static, dll, or executable.

+ 10 - 1
Source/cmDSPWriter.cxx

@@ -100,6 +100,9 @@ void cmDSPMakefile::OutputDSPFile()
       case cmTarget::EXECUTABLE:
         this->SetBuildType(EXECUTABLE,l->first.c_str());
         break;
+      case cmTarget::WIN32_EXECUTABLE:
+        this->SetBuildType(WIN32_EXECUTABLE,l->first.c_str());
+        break;
       case cmTarget::UTILITY:
         this->SetBuildType(UTILITY, l->first.c_str());
         break;
@@ -390,6 +393,12 @@ void cmDSPMakefile::SetBuildType(BuildType b, const char *libName)
       m_DSPFooterTemplate = root;
       m_DSPFooterTemplate += "/EXEFooter.dsptemplate";
       break;
+    case WIN32_EXECUTABLE:
+      m_DSPHeaderTemplate = m_Makefile->GetHomeDirectory();
+      m_DSPHeaderTemplate += "/CMake/Source/EXEWinHeader.dsptemplate";
+      m_DSPFooterTemplate = m_Makefile->GetHomeDirectory();
+      m_DSPFooterTemplate += "/CMake/Source/EXEFooter.dsptemplate";
+      break;
     case UTILITY:
       m_DSPHeaderTemplate = root;
       m_DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
@@ -461,7 +470,7 @@ void cmDSPMakefile::WriteDSPHeader(std::ostream& fout, const char *libName,
     {
     // add libraries to executables and dlls (but never include
     // a library in a library, bad recursion)
-    if (!(target.GetType() == cmTarget::LIBRARY) || 
+    if (target.GetType() != cmTarget::LIBRARY || 
         (m_LibraryBuildType == DLL && libName != j->first))
       {
       std::string lib = j->first;

+ 1 - 1
Source/cmDSPWriter.h

@@ -57,7 +57,7 @@ public:
   cmDSPMakefile(cmMakefile*);
   ~cmDSPMakefile();
   void OutputDSPFile();
-  enum BuildType {STATIC_LIBRARY, DLL, EXECUTABLE, UTILITY};
+  enum BuildType {STATIC_LIBRARY, DLL, EXECUTABLE, WIN32_EXECUTABLE, UTILITY};
 
   /**
    * Specify the type of the build: static, dll, or executable.

+ 2 - 0
Source/cmFindLibraryCommand.cxx

@@ -90,6 +90,7 @@ bool cmFindLibraryCommand::Invoke(std::vector<std::string>& args)
         }
       else
         {
+        cmSystemTools::ExpandRegistryValues(args[j]);
         path.push_back(args[j]);
         }
       }
@@ -106,6 +107,7 @@ bool cmFindLibraryCommand::Invoke(std::vector<std::string>& args)
       // expand variables
       std::string exp = args[j];
       m_Makefile->ExpandVariablesInString(exp);
+      cmSystemTools::ExpandRegistryValues(exp);
       path.push_back(exp);
       }
     }

+ 1 - 0
Source/cmFindPathCommand.cxx

@@ -73,6 +73,7 @@ bool cmFindPathCommand::Invoke(std::vector<std::string>& args)
     // expand variables
     std::string exp = args[j];
     m_Makefile->ExpandVariablesInString(exp);
+    cmSystemTools::ExpandRegistryValues(exp);
     path.push_back(exp);
     }
 

+ 15 - 1
Source/cmMakefile.cxx

@@ -483,9 +483,23 @@ void cmMakefile::AddLibrary(const char* lname, const std::vector<std::string> &s
 
 void cmMakefile::AddExecutable(const char *exeName, 
                                const std::vector<std::string> &srcs)
+{
+  this->AddExecutable(exeName,srcs,false);
+}
+
+void cmMakefile::AddExecutable(const char *exeName, 
+                               const std::vector<std::string> &srcs,
+                               bool win32)
 {
   cmTarget target;
-  target.SetType(cmTarget::EXECUTABLE);
+  if (win32)
+    {
+    target.SetType(cmTarget::WIN32_EXECUTABLE);
+    }
+  else
+    {
+    target.SetType(cmTarget::EXECUTABLE);
+    }
   target.SetInAll(true);
   target.GetSourceLists() = srcs;
   m_Targets.insert(cmTargets::value_type(exeName,target));

+ 4 - 1
Source/cmMakefile.h

@@ -133,7 +133,10 @@ public:
   /**
    * Add an executable to the build.
    */
-  void AddExecutable(const char *exename, const std::vector<std::string> &srcs);
+  void AddExecutable(const char *exename, 
+                     const std::vector<std::string> &srcs);
+  void AddExecutable(const char *exename, 
+                     const std::vector<std::string> &srcs, bool win32);
 
   /**
    * Add a utility to the build.  A utiltity target is

+ 90 - 0
Source/cmSystemTools.cxx

@@ -176,6 +176,96 @@ void cmSystemTools::ReplaceString(std::string& source,
     }
 }
 
+#ifdef _WIN32
+bool ReadAValue(std::string &res, const char *key)
+{
+  // find the primary key
+  std::string primary = key;
+  std::string second = key;
+  size_t start = primary.find("\\");
+  if (start == std::string::npos)
+    {
+    return false;
+    }
+  primary = primary.substr(0,start);
+  second = second.substr(++start);
+  
+  HKEY primaryKey;
+  if (primary == "HKEY_CURRENT_USER")
+    {
+    primaryKey = HKEY_CURRENT_USER;
+    }
+  if (primary == "HKEY_CURRENT_CONFIG")
+    {
+    primaryKey = HKEY_CURRENT_CONFIG;
+    }
+  if (primary == "HKEY_CLASSES_ROOT")
+    {
+    primaryKey = HKEY_CLASSES_ROOT;
+    }
+  if (primary == "HKEY_LOCAL_MACHINE")
+    {
+    primaryKey = HKEY_LOCAL_MACHINE;
+    }
+  if (primary == "HKEY_USERS")
+    {
+    primaryKey = HKEY_USERS;
+    }
+  
+  HKEY hKey;
+  if(RegOpenKeyEx(primaryKey, second.c_str(), 
+		  0, KEY_READ, &hKey) != ERROR_SUCCESS)
+    {
+    return false;
+    }
+  else
+    {
+    DWORD dwType, dwSize;
+    dwSize = 1023;
+    char val[1024];
+    if(RegQueryValueEx(hKey, NULL, NULL, &dwType, 
+                       (BYTE *)val, &dwSize) == ERROR_SUCCESS)
+      {
+      if (dwType == REG_SZ)
+        {
+        res = val;
+        return true;
+        }
+      }
+    }
+  return false;
+}
+#endif
+
+// replace replace with with as many times as it shows up in source.
+// write the result into source.
+void cmSystemTools::ExpandRegistryValues(std::string& source)
+{
+#if _WIN32  
+  cmRegularExpression regEntry("\\[(HKEY[A-Za-z_0-9\\.\\\\]*)\\]");
+  
+  // check for black line or comment
+  while (regEntry.find(source))
+    {
+    // the arguments are the second match
+    std::string key = regEntry.match(1);
+    std::string val;
+    if (ReadAValue(val,key.c_str()))
+      {
+      std::string reg = "[";
+      reg += key + "]";
+      cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
+      }
+    else
+      {
+      std::string reg = "[";
+      reg += key + "]";
+      cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
+      }
+    }
+#endif  
+}
+
 
 std::string cmSystemTools::EscapeSpaces(const char* str)
 {

+ 5 - 0
Source/cmSystemTools.h

@@ -67,6 +67,11 @@ public:
                             const char* replace,
                             const char* with);
 
+  /**
+   * Look for and replace registry values in a string
+   */
+  static void ExpandRegistryValues(std::string& source);
+
   /**
    * Return a string equivalent to the input string, but with all " " replaced
    * with "\ " to escape the spaces.

+ 3 - 2
Source/cmUnixMakefileGenerator.cxx

@@ -129,8 +129,9 @@ void cmUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
   for(cmTargets::const_iterator l = tgts.begin(); 
       l != tgts.end(); l++)
     {
-    if (l->second.GetType() == cmTarget::EXECUTABLE &&
-	l->second.IsInAll())
+    if ((l->second.GetType() == cmTarget::EXECUTABLE ||
+         l->second.GetType() == cmTarget::WIN32_EXECUTABLE) &&
+        l->second.IsInAll())
       {
       fout << " \\\n" << l->first.c_str();
       }