[cmake-commits] alex committed cmBootstrapCommands.cxx 1.10 1.11 cmCoreTryCompile.cxx NONE 1.1 cmCoreTryCompile.h NONE 1.1 cmTryCompileCommand.cxx 1.61 1.62 cmTryCompileCommand.h 1.21 1.22 cmTryRunCommand.cxx 1.26 1.27 cmTryRunCommand.h 1.10 1.11

cmake-commits at cmake.org cmake-commits at cmake.org
Thu May 24 11:27:53 EDT 2007


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

Modified Files:
	cmBootstrapCommands.cxx cmTryCompileCommand.cxx 
	cmTryCompileCommand.h cmTryRunCommand.cxx cmTryRunCommand.h 
Added Files:
	cmCoreTryCompile.cxx cmCoreTryCompile.h 
Log Message:

ENH: add two simple tests for TRY_RUN()
STYLE: create a new base class cmCoreTryCompile, from which
cmTryCompileCommand and cmTryRunCommand are derived, so there are no public
static functions with lots of arguments anymore

Alex


Index: cmTryRunCommand.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTryRunCommand.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- cmTryRunCommand.h	1 May 2007 21:02:19 -0000	1.10
+++ cmTryRunCommand.h	24 May 2007 15:27:51 -0000	1.11
@@ -17,14 +17,14 @@
 #ifndef cmTryRunCommand_h
 #define cmTryRunCommand_h
 
-#include "cmCommand.h"
+#include "cmCoreTryCompile.h"
 
 /** \class cmTryRunCommand
  * \brief Specifies where to install some files
  *
  * cmTryRunCommand is used to test if soucre code can be compiled
  */
-class cmTryRunCommand : public cmCommand
+class cmTryRunCommand : public cmCoreTryCompile
 {
 public:
   /**
@@ -75,7 +75,7 @@
       "output and standard error into.";
     }
   
-  cmTypeMacro(cmTryRunCommand, cmCommand);
+  cmTypeMacro(cmTryRunCommand, cmCoreTryCompile);
 
 };
 

Index: cmTryCompileCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTryCompileCommand.cxx,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -d -r1.61 -r1.62
--- cmTryCompileCommand.cxx	24 May 2007 12:56:14 -0000	1.61
+++ cmTryCompileCommand.cxx	24 May 2007 15:27:51 -0000	1.62
@@ -15,267 +15,8 @@
 
 =========================================================================*/
 #include "cmTryCompileCommand.h"
-#include "cmake.h"
-#include "cmCacheManager.h"
-#include "cmGlobalGenerator.h"
-#include "cmListFileCache.h"
-#include <cmsys/Directory.hxx>
-
-int cmTryCompileCommand::CoreTryCompileCode(
-  cmMakefile *mf, std::vector<std::string> const& argv, bool clean, 
-  const char* cmakeCommand, std::string& outputFile)
-{
-  // which signature were we called with ?
-  bool srcFileSignature = false;
-  unsigned int i;
-  
-  // where will the binaries be stored
-  const char* binaryDirectory = argv[1].c_str();
-  const char* sourceDirectory = argv[2].c_str();
-  const char* projectName = 0;
-  const char* targetName = 0;
-  std::string tmpString;
-  int extraArgs = 0;
-  
-  // look for CMAKE_FLAGS and store them
-  std::vector<std::string> cmakeFlags;
-  for (i = 3; i < argv.size(); ++i)
-    {
-    if (argv[i] == "CMAKE_FLAGS")
-      {
-     // CMAKE_FLAGS is the first argument because we need an argv[0] that
-     // is not used, so it matches regular command line parsing which has
-     // the program name as arg 0
-      for (; i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" && 
-             argv[i] != "OUTPUT_VARIABLE"; 
-           ++i)
-        {
-        extraArgs++;
-        cmakeFlags.push_back(argv[i]);
-        }
-      break;
-      }
-    }
-
-  // look for OUTPUT_VARIABLE and store them
-  std::string outputVariable;
-  for (i = 3; i < argv.size(); ++i)
-    {
-    if (argv[i] == "OUTPUT_VARIABLE")
-      {
-      if ( argv.size() <= (i+1) )
-        {
-        cmSystemTools::Error(
-          "OUTPUT_VARIABLE specified but there is no variable");
-        return -1;
-        }
-      extraArgs += 2;
-      outputVariable = argv[i+1];
-      break;
-      }
-    }
-
-  // look for COMPILE_DEFINITIONS and store them
-  std::vector<std::string> compileFlags;
-  for (i = 3; i < argv.size(); ++i)
-    {
-    if (argv[i] == "COMPILE_DEFINITIONS")
-      {
-      extraArgs++;
-      for (i = i + 1; i < argv.size() && argv[i] != "CMAKE_FLAGS" && 
-             argv[i] != "OUTPUT_VARIABLE"; 
-           ++i)
-        {
-        extraArgs++;
-        compileFlags.push_back(argv[i]);
-        }
-      break;
-      }
-    }
-
-  // do we have a srcfile signature
-  if (argv.size() - extraArgs == 3)
-    {
-    srcFileSignature = true;
-    }
-
-  // only valid for srcfile signatures
-  if (!srcFileSignature && compileFlags.size())
-    {
-    cmSystemTools::Error(
-      "COMPILE_FLAGS specified on a srcdir type TRY_COMPILE");
-    return -1;
-    }
-
-  // compute the binary dir when TRY_COMPILE is called with a src file
-  // signature
-  if (srcFileSignature)
-    {
-    tmpString = argv[1];
-    tmpString += cmake::GetCMakeFilesDirectory();
-    tmpString += "/CMakeTmp";
-    binaryDirectory = tmpString.c_str();
-    }
-  // make sure the binary directory exists
-  cmSystemTools::MakeDirectory(binaryDirectory);
-  
-  // do not allow recursive try Compiles
-  if (!strcmp(binaryDirectory,mf->GetHomeOutputDirectory()))
-    {
-    cmSystemTools::Error(
-      "Attempt at a recursive or nested TRY_COMPILE in directory ",
-      binaryDirectory);
-    return -1;
-    }
-  
-  std::string outFileName = tmpString + "/CMakeLists.txt";
-  // which signature are we using? If we are using var srcfile bindir
-  if (srcFileSignature)
-    {
-    // remove any CMakeCache.txt files so we will have a clean test
-    std::string ccFile = tmpString + "/CMakeCache.txt";
-    cmSystemTools::RemoveFile(ccFile.c_str());
-    
-    // we need to create a directory and CMakeList file etc...
-    // first create the directories
-    sourceDirectory = binaryDirectory;
-
-    // now create a CMakeList.txt file in that directory
-    FILE *fout = fopen(outFileName.c_str(),"w");
-    if (!fout)
-      {
-      cmSystemTools::Error("Failed to create CMakeList file for ", 
-                           outFileName.c_str());
-      cmSystemTools::ReportLastSystemError("");
-      return -1;
-      }
-
-    std::string source = argv[2];
-    std::string ext = cmSystemTools::GetFilenameExtension(source);
-    const char* lang = (mf->GetCMakeInstance()->GetGlobalGenerator()
-                        ->GetLanguageFromExtension(ext.c_str()));
-    const char* def = mf->GetDefinition("CMAKE_MODULE_PATH");
-    if(def)
-      {
-      fprintf(fout, "SET(CMAKE_MODULE_PATH %s)\n", def);
-      }
-    if(lang)
-      {
-      fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE %s)\n", lang);
-      }
-    else
-      {
-      cmOStringStream err;
-      err << "Unknown extension \"" << ext << "\" for file \""
-          << source << "\".  TRY_COMPILE only works for enabled languages.\n"
-          << "Currently enabled languages are:";
-      std::vector<std::string> langs;
-      mf->GetCMakeInstance()->GetGlobalGenerator()->
-        GetEnabledLanguages(langs);
-      for(std::vector<std::string>::iterator l = langs.begin();
-          l != langs.end(); ++l)
-        {
-        err << " " << *l;
-        }
-      err << "\nSee PROJECT command for help enabling other languages.";
-      cmSystemTools::Error(err.str().c_str());
-      fclose(fout);
-      return -1;
-      }
-    std::string langFlags = "CMAKE_";
-    langFlags +=  lang;
-    langFlags += "_FLAGS";
-    fprintf(fout, "SET(CMAKE_VERBOSE_MAKEFILE 1)\n");
-    fprintf(fout, "SET(CMAKE_%s_FLAGS \"", lang);
-    const char* flags = mf->GetDefinition(langFlags.c_str()); 
-    if(flags)
-      {
-      fprintf(fout, " %s ", flags);
-      }
-    fprintf(fout, " ${COMPILE_DEFINITIONS}\")\n");
-    fprintf(fout, "INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES})\n");
-    fprintf(fout, "LINK_DIRECTORIES(${LINK_DIRECTORIES})\n");
-    // handle any compile flags we need to pass on
-    if (compileFlags.size())
-      {
-      fprintf(fout, "ADD_DEFINITIONS( ");
-      for (i = 0; i < compileFlags.size(); ++i)
-        {
-        fprintf(fout,"%s ",compileFlags[i].c_str());
-        }
-      fprintf(fout, ")\n");
-      }
-    const char* platformOptions = 
-      mf->GetDefinition("CMAKE_TRY_COMPILE_PLATFORM_OPTIONS");
-    if ( platformOptions )
-      {
-      fprintf(fout, "%s\n", platformOptions);
-      }
-    
-    fprintf(fout, "ADD_EXECUTABLE(cmTryCompileExec \"%s\")\n",source.c_str());
-    fprintf(fout, 
-            "TARGET_LINK_LIBRARIES(cmTryCompileExec ${LINK_LIBRARIES})\n");
-    fclose(fout);
-    projectName = "CMAKE_TRY_COMPILE";
-    targetName = "cmTryCompileExec";
-    // if the source is not in CMakeTmp 
-    if(source.find("CMakeTmp") == source.npos)
-      {
-      mf->AddCMakeDependFile(source.c_str());
-      }
-    
-    }
-  // else the srcdir bindir project target signature
-  else
-    {
-    projectName = argv[3].c_str();
-    
-    if (argv.size() - extraArgs == 5)
-      {
-      targetName = argv[4].c_str();
-      }
-    }
-  
-  bool erroroc = cmSystemTools::GetErrorOccuredFlag();
-  cmSystemTools::ResetErrorOccuredFlag();
-  std::string output;
-  // actually do the try compile now that everything is setup
-  int res = mf->TryCompile(sourceDirectory, binaryDirectory,
-                           projectName, targetName, &cmakeFlags, &output);
-  if ( erroroc )
-    {
-    cmSystemTools::SetErrorOccured();
-    }
-  
-  // set the result var to the return value to indicate success or failure
-  mf->AddCacheDefinition(argv[0].c_str(), (res == 0 ? "TRUE" : "FALSE"),
-                         "Result of TRY_COMPILE",
-                         cmCacheManager::INTERNAL);
-
-  if ( outputVariable.size() > 0 )
-    {
-    mf->AddDefinition(outputVariable.c_str(), output.c_str());
-    }
-  
-  // if They specified clean then we clean up what we can
-  if (srcFileSignature)
-    {
-    std::string errorMessage;
-    outputFile = cmTryCompileCommand::GetOutputFile(mf, binaryDirectory, 
-                                                    targetName, cmakeCommand,
-                                                    errorMessage);
-    if (clean)
-      {    
-      if(!mf->GetCMakeInstance()->GetDebugTryCompile())
-        {
-        cmTryCompileCommand::CleanupFiles(binaryDirectory);
-        }
-      }
-    }
-  return res;
-}
 
-// cmExecutableCommand
+// cmTryCompileCommand
 bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv)
 {
   if(argv.size() < 3)
@@ -283,119 +24,16 @@
     return false;
     }
 
-  std::string dummy;
-  cmTryCompileCommand::CoreTryCompileCode(this->Makefile,argv, true, 
-                                          this->GetName(), dummy);
-  
-  return true;
-}
+  this->TryCompileCode(argv);
 
-void cmTryCompileCommand::CleanupFiles(const char* binDir)
-{
-  if ( !binDir )
-    {
-    return;
-    }
-  
-  std::string bdir = binDir;
-  if(bdir.find("CMakeTmp") == std::string::npos)
-    {
-    cmSystemTools::Error(
-      "TRY_COMPILE attempt to remove -rf directory that does not contain "
-      "CMakeTmp:", binDir);
-    return;
-    }
-  
-  cmsys::Directory dir;
-  dir.Load(binDir);
-  size_t fileNum;
-  std::set<cmStdString> deletedFiles;
-  for (fileNum = 0; fileNum <  dir.GetNumberOfFiles(); ++fileNum)
+  // if They specified clean then we clean up what we can
+  if (this->SrcFileSignature)
     {
-    if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
-        strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
+    if(!this->Makefile->GetCMakeInstance()->GetDebugTryCompile())
       {
-      
-      if(deletedFiles.find( dir.GetFile(static_cast<unsigned long>(fileNum))) 
-         == deletedFiles.end())
-        {
-        deletedFiles.insert(dir.GetFile(static_cast<unsigned long>(fileNum)));
-        std::string fullPath = binDir;
-        fullPath += "/";
-        fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
-        if(cmSystemTools::FileIsDirectory(fullPath.c_str()))
-          {
-          cmTryCompileCommand::CleanupFiles(fullPath.c_str());
-          }
-        else
-          {
-          if(!cmSystemTools::RemoveFile(fullPath.c_str()))
-            {
-            std::string m = "Remove failed on file: ";
-            m += fullPath;
-            cmSystemTools::ReportLastSystemError(m.c_str());
-            }
-          }
-        }
+      this->CleanupFiles(this->BinaryDirectory.c_str());
       }
     }
+  return true;
 }
 
-const char* cmTryCompileCommand::GetOutputFile(cmMakefile* mf, 
-                                               const char* binaryDirectory, 
-                                               const char* targetName,
-                                               const char* cmakeCommand,
-                                               std::string& errorMessage)
-{
-  errorMessage = "";
-  std::string outputFile = "/";
-  outputFile += targetName;
-  outputFile += mf->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");
-
-  // a list of directories where to search for the compilation result
-  // at first directly in the binary dir
-  std::vector<std::string> searchDirs;
-  searchDirs.push_back("");
-
-  const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
-  // if a config was specified try that first
-  if (config && config[0])
-    {
-    std::string tmp = "/";
-    tmp += config;
-    searchDirs.push_back(tmp);
-    }
-  searchDirs.push_back("/Debug");
-  searchDirs.push_back("/Development");
-
-  for(std::vector<std::string>::const_iterator it = searchDirs.begin();
-      it != searchDirs.end();
-      ++it)
-    {
-    std::string command = binaryDirectory;
-    command += *it;
-    command += outputFile;
-    if(cmSystemTools::FileExists(command.c_str()))
-      {
-      outputFile = cmSystemTools::CollapseFullPath(command.c_str());
-      return outputFile.c_str();
-      }
-    }
-
-  cmOStringStream emsg;
-  emsg << "Unable to find executable for " << cmakeCommand << ": tried \"";
-  for (unsigned int i = 0; i < searchDirs.size(); ++i)
-    {
-    emsg << binaryDirectory << searchDirs[i] << outputFile;
-    if (i < searchDirs.size() - 1)
-      {
-      emsg << "\" and \"";
-      }
-    else
-      {
-      emsg << "\".";
-      }
-    }
-  errorMessage = emsg.str();
-  return "";
-}

Index: cmBootstrapCommands.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmBootstrapCommands.cxx,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- cmBootstrapCommands.cxx	13 May 2007 11:16:24 -0000	1.10
+++ cmBootstrapCommands.cxx	24 May 2007 15:27:51 -0000	1.11
@@ -66,6 +66,7 @@
 #include "cmStringCommand.cxx"
 #include "cmSubdirCommand.cxx"
 #include "cmTargetLinkLibrariesCommand.cxx"
+#include "cmCoreTryCompile.cxx"
 #include "cmTryCompileCommand.cxx"
 #include "cmTryRunCommand.cxx"
 

Index: cmTryRunCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTryRunCommand.cxx,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- cmTryRunCommand.cxx	24 May 2007 12:56:14 -0000	1.26
+++ cmTryRunCommand.cxx	24 May 2007 15:27:51 -0000	1.27
@@ -71,62 +71,62 @@
       }
     }
   // do the try compile
-  std::string fullPath;
-  int res = cmTryCompileCommand::CoreTryCompileCode(this->Makefile, tryCompile, 
-                                             false, this->GetName(), fullPath);
+  int res = this->TryCompileCode(tryCompile);
 
   // now try running the command if it compiled
-  if (!res==0)
-  {
-    if (fullPath.size() > 0)
+  if (!res)
     {
-    int retVal = -1;
-    std::string output;
-    std::string finalCommand = fullPath;
-    finalCommand = cmSystemTools::ConvertToRunCommandPath(fullPath.c_str());
-    if(runArgs.size())
+      fprintf(stderr, "running %s\n", this->OutputFile.c_str());
+    if (this->OutputFile.size() == 0)
       {
-      finalCommand += runArgs;
+      cmSystemTools::Error(this->FindErrorMessage.c_str());
       }
-    int timeout = 0;
-    bool worked = cmSystemTools::RunSingleCommand(finalCommand.c_str(),
-                                                  &output, &retVal,
-                                                  0, false, timeout);
-    if(outputVariable.size())
+    else
       {
-      // if the TryCompileCore saved output in this outputVariable then
-      // prepend that output to this output
-      const char* compileOutput
-        = this->Makefile->GetDefinition(outputVariable.c_str());
-      if(compileOutput)
+      int retVal = -1;
+      std::string output;
+      std::string finalCommand = cmSystemTools::ConvertToRunCommandPath(
+                                                     this->OutputFile.c_str());
+      if(runArgs.size())
         {
-        output = std::string(compileOutput) + output;
+        finalCommand += runArgs;
         }
-      this->Makefile->AddDefinition(outputVariable.c_str(), output.c_str());
-      }
-    // set the run var
-    char retChar[1000];
-    if(worked)
-      {
-      sprintf(retChar,"%i",retVal);
-      }
-    else
-      {
-      strcpy(retChar, "FAILED_TO_RUN");
+      int timeout = 0;
+      bool worked = cmSystemTools::RunSingleCommand(finalCommand.c_str(),
+                                                    &output, &retVal,
+                                                    0, false, timeout);
+      if(outputVariable.size())
+        {
+        // if the TryCompileCore saved output in this outputVariable then
+        // prepend that output to this output
+        const char* compileOutput
+          = this->Makefile->GetDefinition(outputVariable.c_str());
+        if(compileOutput)
+          {
+          output = std::string(compileOutput) + output;
+          }
+        this->Makefile->AddDefinition(outputVariable.c_str(), output.c_str());
+        }
+      // set the run var
+      char retChar[1000];
+      if(worked)
+        {
+        sprintf(retChar,"%i",retVal);
+        }
+      else
+        {
+        strcpy(retChar, "FAILED_TO_RUN");
+        }
+      this->Makefile->AddCacheDefinition(argv[0].c_str(), retChar,
+                                      "Result of TRY_RUN",
+                                          cmCacheManager::INTERNAL);
       }
-    this->Makefile->AddCacheDefinition(argv[0].c_str(), retChar,
-                                    "Result of TRY_RUN",
-                                        cmCacheManager::INTERNAL);
-    }
   }
     
   // if we created a directory etc, then cleanup after ourselves
   if(!this->Makefile->GetCMakeInstance()->GetDebugTryCompile())
     {
-    std::string binaryDirectory = argv[2];
-    binaryDirectory += cmake::GetCMakeFilesDirectory();
-    binaryDirectory += "/CMakeTmp"; 
-    cmTryCompileCommand::CleanupFiles(binaryDirectory.c_str());
+    this->CleanupFiles(this->BinaryDirectory.c_str());
     }
   return true;
 }

--- NEW FILE: cmCoreTryCompile.cxx ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmCoreTryCompile.cxx,v $
  Language:  C++
  Date:      $Date: 2007/05/24 15:27:51 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2007 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "cmCoreTryCompile.h"
#include "cmake.h"
#include "cmCacheManager.h"
#include "cmGlobalGenerator.h"
#include <cmsys/Directory.hxx>

int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
{
  
  this->BinaryDirectory = argv[1].c_str();
  this->OutputFile = "";
  // which signature were we called with ?
  this->SrcFileSignature = false;
  unsigned int i;
  
  const char* sourceDirectory = argv[2].c_str();
  const char* projectName = 0;
  const char* targetName = 0;
  int extraArgs = 0;
  
  // look for CMAKE_FLAGS and store them
  std::vector<std::string> cmakeFlags;
  for (i = 3; i < argv.size(); ++i)
    {
    if (argv[i] == "CMAKE_FLAGS")
      {
     // CMAKE_FLAGS is the first argument because we need an argv[0] that
     // is not used, so it matches regular command line parsing which has
     // the program name as arg 0
      for (; i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" && 
             argv[i] != "OUTPUT_VARIABLE"; 
           ++i)
        {
        extraArgs++;
        cmakeFlags.push_back(argv[i]);
        }
      break;
      }
    }

  // look for OUTPUT_VARIABLE and store them
  std::string outputVariable;
  for (i = 3; i < argv.size(); ++i)
    {
    if (argv[i] == "OUTPUT_VARIABLE")
      {
      if ( argv.size() <= (i+1) )
        {
        cmSystemTools::Error(
          "OUTPUT_VARIABLE specified but there is no variable");
        return -1;
        }
      extraArgs += 2;
      outputVariable = argv[i+1];
      break;
      }
    }

  // look for COMPILE_DEFINITIONS and store them
  std::vector<std::string> compileFlags;
  for (i = 3; i < argv.size(); ++i)
    {
    if (argv[i] == "COMPILE_DEFINITIONS")
      {
      extraArgs++;
      for (i = i + 1; i < argv.size() && argv[i] != "CMAKE_FLAGS" && 
             argv[i] != "OUTPUT_VARIABLE"; 
           ++i)
        {
        extraArgs++;
        compileFlags.push_back(argv[i]);
        }
      break;
      }
    }

  // do we have a srcfile signature
  if (argv.size() - extraArgs == 3)
    {
    this->SrcFileSignature = true;
    }

  // compute the binary dir when TRY_COMPILE is called with a src file
  // signature
  if (this->SrcFileSignature)
    {
    this->BinaryDirectory += cmake::GetCMakeFilesDirectory();
    this->BinaryDirectory += "/CMakeTmp";
    }
  else
    {
    // only valid for srcfile signatures
    if (compileFlags.size())
      {
      cmSystemTools::Error(
        "COMPILE_FLAGS specified on a srcdir type TRY_COMPILE");
      return -1;
      }
    }
  // make sure the binary directory exists
  cmSystemTools::MakeDirectory(this->BinaryDirectory.c_str());
  
  // do not allow recursive try Compiles
  if (this->BinaryDirectory == this->Makefile->GetHomeOutputDirectory())
    {
    cmSystemTools::Error(
      "Attempt at a recursive or nested TRY_COMPILE in directory ",
      this->BinaryDirectory.c_str());
    return -1;
    }
  
  std::string outFileName = this->BinaryDirectory + "/CMakeLists.txt";
  // which signature are we using? If we are using var srcfile bindir
  if (this->SrcFileSignature)
    {
    // remove any CMakeCache.txt files so we will have a clean test
    std::string ccFile = this->BinaryDirectory + "/CMakeCache.txt";
    cmSystemTools::RemoveFile(ccFile.c_str());
    
    // we need to create a directory and CMakeList file etc...
    // first create the directories
    sourceDirectory = this->BinaryDirectory.c_str();

    // now create a CMakeList.txt file in that directory
    FILE *fout = fopen(outFileName.c_str(),"w");
    if (!fout)
      {
      cmSystemTools::Error("Failed to create CMakeList file for ", 
                           outFileName.c_str());
      cmSystemTools::ReportLastSystemError("");
      return -1;
      }

    std::string source = argv[2];
    std::string ext = cmSystemTools::GetFilenameExtension(source);
    const char* lang =(this->Makefile->GetCMakeInstance()->GetGlobalGenerator()
                        ->GetLanguageFromExtension(ext.c_str()));
    const char* def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH");
    if(def)
      {
      fprintf(fout, "SET(CMAKE_MODULE_PATH %s)\n", def);
      }
    if(lang)
      {
      fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE %s)\n", lang);
      }
    else
      {
      cmOStringStream err;
      err << "Unknown extension \"" << ext << "\" for file \""
          << source << "\".  TRY_COMPILE only works for enabled languages.\n"
          << "Currently enabled languages are:";
      std::vector<std::string> langs;
      this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->
        GetEnabledLanguages(langs);
      for(std::vector<std::string>::iterator l = langs.begin();
          l != langs.end(); ++l)
        {
        err << " " << *l;
        }
      err << "\nSee PROJECT command for help enabling other languages.";
      cmSystemTools::Error(err.str().c_str());
      fclose(fout);
      return -1;
      }
    std::string langFlags = "CMAKE_";
    langFlags +=  lang;
    langFlags += "_FLAGS";
    fprintf(fout, "SET(CMAKE_VERBOSE_MAKEFILE 1)\n");
    fprintf(fout, "SET(CMAKE_%s_FLAGS \"", lang);
    const char* flags = this->Makefile->GetDefinition(langFlags.c_str()); 
    if(flags)
      {
      fprintf(fout, " %s ", flags);
      }
    fprintf(fout, " ${COMPILE_DEFINITIONS}\")\n");
    fprintf(fout, "INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES})\n");
    fprintf(fout, "LINK_DIRECTORIES(${LINK_DIRECTORIES})\n");
    // handle any compile flags we need to pass on
    if (compileFlags.size())
      {
      fprintf(fout, "ADD_DEFINITIONS( ");
      for (i = 0; i < compileFlags.size(); ++i)
        {
        fprintf(fout,"%s ",compileFlags[i].c_str());
        }
      fprintf(fout, ")\n");
      }
    const char* platformOptions = 
      this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_PLATFORM_OPTIONS");
    if ( platformOptions )
      {
      fprintf(fout, "%s\n", platformOptions);
      }
    
    fprintf(fout, "ADD_EXECUTABLE(cmTryCompileExec \"%s\")\n",source.c_str());
    fprintf(fout, 
            "TARGET_LINK_LIBRARIES(cmTryCompileExec ${LINK_LIBRARIES})\n");
    fclose(fout);
    projectName = "CMAKE_TRY_COMPILE";
    targetName = "cmTryCompileExec";
    // if the source is not in CMakeTmp 
    if(source.find("CMakeTmp") == source.npos)
      {
      this->Makefile->AddCMakeDependFile(source.c_str());
      }
    
    }
  // else the srcdir bindir project target signature
  else
    {
    projectName = argv[3].c_str();
    
    if (argv.size() - extraArgs == 5)
      {
      targetName = argv[4].c_str();
      }
    }
  
  bool erroroc = cmSystemTools::GetErrorOccuredFlag();
  cmSystemTools::ResetErrorOccuredFlag();
  std::string output;
  // actually do the try compile now that everything is setup
  int res = this->Makefile->TryCompile(sourceDirectory, 
                                       this->BinaryDirectory.c_str(),
                                       projectName, 
                                       targetName, 
                                       &cmakeFlags, 
                                       &output);
  if ( erroroc )
    {
    cmSystemTools::SetErrorOccured();
    }
  
  // set the result var to the return value to indicate success or failure
  this->Makefile->AddCacheDefinition(argv[0].c_str(),
                                     (res == 0 ? "TRUE" : "FALSE"),
                                     "Result of TRY_COMPILE",
                                     cmCacheManager::INTERNAL);

  if ( outputVariable.size() > 0 )
    {
    this->Makefile->AddDefinition(outputVariable.c_str(), output.c_str());
    }
  
  if (this->SrcFileSignature)
    {
    this->FindOutputFile(targetName);
    }
  return res;
}

void cmCoreTryCompile::CleanupFiles(const char* binDir)
{
  if ( !binDir )
    {
    return;
    }
  
  std::string bdir = binDir;
  if(bdir.find("CMakeTmp") == std::string::npos)
    {
    cmSystemTools::Error(
      "TRY_COMPILE attempt to remove -rf directory that does not contain "
      "CMakeTmp:", binDir);
    return;
    }
  
  cmsys::Directory dir;
  dir.Load(binDir);
  size_t fileNum;
  std::set<cmStdString> deletedFiles;
  for (fileNum = 0; fileNum <  dir.GetNumberOfFiles(); ++fileNum)
    {
    if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
        strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
      {
      
      if(deletedFiles.find( dir.GetFile(static_cast<unsigned long>(fileNum))) 
         == deletedFiles.end())
        {
        deletedFiles.insert(dir.GetFile(static_cast<unsigned long>(fileNum)));
        std::string fullPath = binDir;
        fullPath += "/";
        fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
        if(cmSystemTools::FileIsDirectory(fullPath.c_str()))
          {
          this->CleanupFiles(fullPath.c_str());
          }
        else
          {
          if(!cmSystemTools::RemoveFile(fullPath.c_str()))
            {
            std::string m = "Remove failed on file: ";
            m += fullPath;
            cmSystemTools::ReportLastSystemError(m.c_str());
            }
          }
        }
      }
    }
}

void cmCoreTryCompile::FindOutputFile(const char* targetName)
{
  this->FindErrorMessage = "";
  this->OutputFile = "";
  std::string tmpOutputFile = "/";
  tmpOutputFile += targetName;
  tmpOutputFile +=this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");

  // a list of directories where to search for the compilation result
  // at first directly in the binary dir
  std::vector<std::string> searchDirs;
  searchDirs.push_back("");

  const char* config = this->Makefile->GetDefinition(
                                            "CMAKE_TRY_COMPILE_CONFIGURATION");
  // if a config was specified try that first
  if (config && config[0])
    {
    std::string tmp = "/";
    tmp += config;
    searchDirs.push_back(tmp);
    }
  searchDirs.push_back("/Debug");
  searchDirs.push_back("/Development");

  for(std::vector<std::string>::const_iterator it = searchDirs.begin();
      it != searchDirs.end();
      ++it)
    {
    std::string command = this->BinaryDirectory;
    command += *it;
    command += tmpOutputFile;
    if(cmSystemTools::FileExists(command.c_str()))
      {
      tmpOutputFile = cmSystemTools::CollapseFullPath(command.c_str());
      this->OutputFile = tmpOutputFile;
      return;
      }
    }

  cmOStringStream emsg;
  emsg << "Unable to find executable for " << this->GetName() << ": tried \"";
  for (unsigned int i = 0; i < searchDirs.size(); ++i)
    {
    emsg << this->BinaryDirectory << searchDirs[i] << tmpOutputFile;
    if (i < searchDirs.size() - 1)
      {
      emsg << "\" and \"";
      }
    else
      {
      emsg << "\".";
      }
    }
  this->FindErrorMessage = emsg.str();
  return;
}

Index: cmTryCompileCommand.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTryCompileCommand.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- cmTryCompileCommand.h	24 May 2007 12:56:14 -0000	1.21
+++ cmTryCompileCommand.h	24 May 2007 15:27:51 -0000	1.22
@@ -17,14 +17,14 @@
 #ifndef cmTryCompileCommand_h
 #define cmTryCompileCommand_h
 
-#include "cmCommand.h"
+#include "cmCoreTryCompile.h"
 
 /** \class cmTryCompileCommand
  * \brief Specifies where to install some files
  *
  * cmTryCompileCommand is used to test if soucre code can be compiled
  */
-class cmTryCompileCommand : public cmCommand
+class cmTryCompileCommand : public cmCoreTryCompile
 {
 public:
   /**
@@ -55,32 +55,6 @@
     }
 
   /**
-   * This is the core code for try compile. It is here so that other
-   * commands, such as TryRun can access the same logic without
-   * duplication. 
-   */
-  static int CoreTryCompileCode(cmMakefile *mf, 
-                                std::vector<std::string> const& argv, 
-                                bool clean, 
-                                const char* cmakeCommand, 
-                                std::string& outputFile);
-
-  /** 
-   * This deletes all the files created by TRY_COMPILE or TRY_RUN
-   * code. This way we do not have to rely on the timing and
-   * dependencies of makefiles.
-   */
-  static void CleanupFiles(const char* binDir);
-
-  /** 
-   * This tries to find the (executable) file created by TRY_COMPILE or 
-   * TRY_RUN. If nothing is found an empty string will be returned.
-   */
-  static const char* GetOutputFile(cmMakefile* mf, const char* binaryDirectory, 
-                             const char* targetName, const char* cmakeCommand, 
-                             std::string& errorMessage);
-
-  /**
    * More documentation.  */
   virtual const char* GetFullDocumentation()
     {
@@ -125,7 +99,7 @@
       "";
     }
   
-  cmTypeMacro(cmTryCompileCommand, cmCommand);
+  cmTypeMacro(cmTryCompileCommand, cmCoreTryCompile);
 
 };
 

--- NEW FILE: cmCoreTryCompile.h ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmCoreTryCompile.h,v $
  Language:  C++
  Date:      $Date: 2007/05/24 15:27:51 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2007 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef cmCoreTryCompile_h
#define cmCoreTryCompile_h

#include "cmCommand.h"

/** \class cmCoreTryCompile
 * \brief Base class for cmTryCompileCommand and cmTryRunCommand
 *
 * cmCoreTryCompile implements the functionality to build a program.
 * It is the base class for cmTryCompileCommand and cmTryRunCommand.
 */
class cmCoreTryCompile : public cmCommand
{
public:

  protected:
  /**
   * This is the core code for try compile. It is here so that other
   * commands, such as TryRun can access the same logic without
   * duplication. 
   */
  int TryCompileCode(std::vector<std::string> const& argv);

  /** 
   * This deletes all the files created by TryCompileCode. 
   * This way we do not have to rely on the timing and
   * dependencies of makefiles.
   */
  void CleanupFiles(const char* binDir);

  /** 
   * This tries to find the (executable) file created by 
  TryCompileCode. The result is stored in OutputFile. If nothing is found,
  the error message is stored in FindErrorMessage.
   */
  void FindOutputFile(const char* targetName);

  
  cmTypeMacro(cmCoreTryCompile, cmCommand);
  
  std::string BinaryDirectory;
  std::string OutputFile;
  std::string FindErrorMessage;
  bool SrcFileSignature;

};


#endif



More information about the Cmake-commits mailing list