[Cmake-commits] [cmake-commits] king committed cmExportCommand.cxx 1.11 1.12 cmExportCommand.h 1.9 1.10

cmake-commits at cmake.org cmake-commits at cmake.org
Tue Sep 1 14:04:55 EDT 2009


Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv27149/Source

Modified Files:
	cmExportCommand.cxx cmExportCommand.h 
Log Message:
Teach export(PACKAGE) to fill the package registry

We define the export(PACKAGE) command mode to store the location of the
build tree in the user package registry.  This will help find_package
locate the package in the build tree.  It simplies user workflow for
manually building a series of dependent projects.


Index: cmExportCommand.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportCommand.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -C 2 -d -r1.9 -r1.10
*** cmExportCommand.h	30 Jan 2008 22:25:52 -0000	1.9
--- cmExportCommand.h	1 Sep 2009 18:04:53 -0000	1.10
***************
*** 85,89 ****
        "should never be installed.  "
        "See the install(EXPORT) command to export targets from an "
!       "installation tree.";
      }
  
--- 85,101 ----
        "should never be installed.  "
        "See the install(EXPORT) command to export targets from an "
!       "installation tree."
!       "\n"
!       "  export(PACKAGE <name>)\n"
!       "Store the current build directory in the CMake user package registry "
!       "for package <name>.  "
!       "The find_package command may consider the directory while searching "
!       "for package <name>.  "
!       "This helps dependent projects find and use a package from the "
!       "current project's build tree without help from the user.  "
!       "Note that the entry in the package registry that this command "
!       "creates works only in conjunction with a package configuration "
!       "file (<name>Config.cmake) that works with the build tree."
!       ;
      }
  
***************
*** 99,102 ****
--- 111,122 ----
    friend class cmExportBuildFileGenerator;
    std::string ErrorMessage;
+ 
+   bool HandlePackage(std::vector<std::string> const& args);
+   void StorePackageRegistryWin(std::string const& package,
+                                const char* content, const char* hash);
+   void StorePackageRegistryDir(std::string const& package,
+                                const char* content, const char* hash);
+   void ReportRegistryError(std::string const& msg, std::string const& key,
+                            long err);
  };
  

Index: cmExportCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportCommand.cxx,v
retrieving revision 1.11
retrieving revision 1.12
diff -C 2 -d -r1.11 -r1.12
*** cmExportCommand.cxx	6 Feb 2008 19:20:35 -0000	1.11
--- cmExportCommand.cxx	1 Sep 2009 18:04:53 -0000	1.12
***************
*** 21,24 ****
--- 21,26 ----
  #include "cmake.h"
  
+ #include <cmsys/RegularExpression.hxx>
+ 
  #include "cmExportBuildFileGenerator.h"
  
***************
*** 48,51 ****
--- 50,58 ----
      }
  
+   if(args[0] == "PACKAGE")
+     {
+     return this->HandlePackage(args);
+     }
+ 
    std::vector<std::string> unknownArgs;
    this->Helper.Parse(&args, &unknownArgs);
***************
*** 185,186 ****
--- 192,335 ----
    return true;
  }
+ 
+ //----------------------------------------------------------------------------
+ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args)
+ {
+   // Parse PACKAGE mode arguments.
+   enum Doing { DoingNone, DoingPackage };
+   Doing doing = DoingPackage;
+   std::string package;
+   for(unsigned int i=1; i < args.size(); ++i)
+     {
+     if(doing == DoingPackage)
+       {
+       package = args[i];
+       doing = DoingNone;
+       }
+     else
+       {
+       cmOStringStream e;
+       e << "PACKAGE given unknown argumsnt: " << args[i];
+       this->SetError(e.str().c_str());
+       return false;
+       }
+     }
+ 
+   // Verify the package name.
+   if(package.empty())
+     {
+     this->SetError("PACKAGE must be given a package name.");
+     return false;
+     }
+   const char* packageExpr = "^[A-Za-z0-9_.-]+$";
+   cmsys::RegularExpression packageRegex(packageExpr);
+   if(!packageRegex.find(package.c_str()))
+     {
+     cmOStringStream e;
+     e << "PACKAGE given invalid package name \"" << package << "\".  "
+       << "Package names must match \"" << packageExpr << "\".";
+     this->SetError(e.str().c_str());
+     return false;
+     }
+ 
+   // We store the current build directory in the registry as a value
+   // named by a hash of its own content.  This is deterministic and is
+   // unique with high probability.
+   const char* outDir = this->Makefile->GetCurrentOutputDirectory();
+   std::string hash = cmSystemTools::ComputeStringMD5(outDir);
+ #if defined(_WIN32) && !defined(__CYGWIN__)
+   this->StorePackageRegistryWin(package, outDir, hash.c_str());
+ #else
+   this->StorePackageRegistryDir(package, outDir, hash.c_str());
+ #endif
+ 
+   return true;
+ }
+ 
+ #if defined(_WIN32) && !defined(__CYGWIN__)
+ # include <windows.h>
+ # undef GetCurrentDirectory
+ //----------------------------------------------------------------------------
+ void cmExportCommand::ReportRegistryError(std::string const& msg,
+                                           std::string const& key,
+                                           long err)
+ {
+   cmOStringStream e;
+   e << msg << "\n"
+     << "  HKEY_CURRENT_USER\\" << key << "\n";
+   char winmsg[1024];
+   if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+                    FORMAT_MESSAGE_IGNORE_INSERTS, 0, err,
+                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                    winmsg, 1024, 0) > 0)
+     {
+     e << "Windows reported:\n"
+       << "  " << winmsg;
+     }
+   this->Makefile->IssueMessage(cmake::WARNING, e.str());
+ }
+ 
+ //----------------------------------------------------------------------------
+ void cmExportCommand::StorePackageRegistryWin(std::string const& package,
+                                               const char* content,
+                                               const char* hash)
+ {
+   std::string key = "Software\\Kitware\\CMake\\Packages\\";
+   key += package;
+   HKEY hKey;
+   LONG err = RegCreateKeyEx(HKEY_CURRENT_USER,
+                             key.c_str(), 0, 0, REG_OPTION_NON_VOLATILE,
+                             KEY_SET_VALUE, 0, &hKey, 0);
+   if(err != ERROR_SUCCESS)
+     {
+     this->ReportRegistryError(
+       "Cannot create/open registry key", key, err);
+     return;
+     }
+   err = RegSetValueEx(hKey, hash, 0, REG_SZ, (BYTE const*)content,
+                       static_cast<DWORD>(strlen(content)+1));
+   RegCloseKey(hKey);
+   if(err != ERROR_SUCCESS)
+     {
+     cmOStringStream msg;
+     msg << "Cannot set registry value \"" << hash << "\" under key";
+     this->ReportRegistryError(msg.str(), key, err);
+     return;
+     }
+ }
+ #else
+ //----------------------------------------------------------------------------
+ void cmExportCommand::StorePackageRegistryDir(std::string const& package,
+                                               const char* content,
+                                               const char* hash)
+ {
+   const char* home = cmSystemTools::GetEnv("HOME");
+   if(!home)
+     {
+     return;
+     }
+   std::string fname = home;
+   cmSystemTools::ConvertToUnixSlashes(fname);
+   fname += "/.cmake/packages/";
+   fname += package;
+   cmSystemTools::MakeDirectory(fname.c_str());
+   fname += "/";
+   fname += hash;
+   if(!cmSystemTools::FileExists(fname.c_str()))
+     {
+     cmGeneratedFileStream entry(fname.c_str(), true);
+     if(entry)
+       {
+       entry << content << "\n";
+       }
+     else
+       {
+       cmOStringStream e;
+       e << "Cannot create package registry file:\n"
+         << "  " << fname << "\n"
+         << cmSystemTools::GetLastSystemError() << "\n";
+       this->Makefile->IssueMessage(cmake::WARNING, e.str());
+       }
+     }
+ }
+ #endif



More information about the Cmake-commits mailing list