Jelajahi Sumber

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

Alexander Neundorf 18 tahun lalu
induk
melakukan
7d7aba292c

+ 1 - 0
Source/cmBootstrapCommands.cxx

@@ -66,6 +66,7 @@
 #include "cmStringCommand.cxx"
 #include "cmSubdirCommand.cxx"
 #include "cmTargetLinkLibrariesCommand.cxx"
+#include "cmCoreTryCompile.cxx"
 #include "cmTryCompileCommand.cxx"
 #include "cmTryRunCommand.cxx"
 

+ 376 - 0
Source/cmCoreTryCompile.cxx

@@ -0,0 +1,376 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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;
+}

+ 65 - 0
Source/cmCoreTryCompile.h

@@ -0,0 +1,65 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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

+ 7 - 369
Source/cmTryCompileCommand.cxx

@@ -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 @@ bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv)
     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 "";
-}

+ 3 - 29
Source/cmTryCompileCommand.h

@@ -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:
   /**
@@ -54,32 +54,6 @@ public:
     return "Try compiling some code.";
     }
 
-  /**
-   * 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 @@ public:
       "";
     }
   
-  cmTypeMacro(cmTryCompileCommand, cmCommand);
+  cmTypeMacro(cmTryCompileCommand, cmCoreTryCompile);
 
 };
 

+ 42 - 42
Source/cmTryRunCommand.cxx

@@ -71,62 +71,62 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv)
       }
     }
   // 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;
 }

+ 3 - 3
Source/cmTryRunCommand.h

@@ -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 @@ public:
       "output and standard error into.";
     }
   
-  cmTypeMacro(cmTryRunCommand, cmCommand);
+  cmTypeMacro(cmTryRunCommand, cmCoreTryCompile);
 
 };
 

+ 30 - 2
Tests/TryCompile/CMakeLists.txt

@@ -61,8 +61,7 @@ IF (CMAKE_ANSI_FOR_SCOPE)
    MESSAGE("Compiler supports ansi for")
 ELSE(CMAKE_ANSI_FOR_SCOPE)
    MESSAGE("Compiler does not support ansi for scope")
-ENDIF(CMAKE_ANSI_FOR_SCOPE)
-        
+ENDIF(CMAKE_ANSI_FOR_SCOPE)        
 
 MESSAGE("use the module now")
 INCLUDE(${CMAKE_ROOT}/Modules/TestForANSIForScope.cmake)
@@ -73,3 +72,32 @@ ELSE(CMAKE_ANSI_FOR_SCOPE)
 ENDIF(CMAKE_ANSI_FOR_SCOPE)
 
 ADD_EXECUTABLE(TryCompile pass.c)
+
+######################################
+
+# now two tests for TRY_RUN
+
+# try to run a file that should compile and run without error
+TRY_RUN(SHOULD_RUN SHOULD_COMPILE
+    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp  
+    ${TryCompile_SOURCE_DIR}/exit_success.c
+    OUTPUT_VARIABLE TRY_OUT)
+IF(NOT SHOULD_COMPILE)
+  MESSAGE(SEND_ERROR "exit_success failed compiling: ${TRY_OUT}")
+ENDIF(NOT SHOULD_COMPILE)
+IF(NOT "${SHOULD_RUN}" STREQUAL "0")
+  MESSAGE(SEND_ERROR "exit_success failed running with exit code ${SHOULD_RUN}")
+ENDIF(NOT "${SHOULD_RUN}" STREQUAL "0")
+
+# try to run a file that should compile and run, but return an error
+TRY_RUN(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE
+    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp  
+    ${TryCompile_SOURCE_DIR}/exit_with_error.c
+    OUTPUT_VARIABLE TRY_OUT)
+IF(NOT SHOULD_COMPILE)
+  MESSAGE(STATUS " exit_with_error failed compiling: ${TRY_OUT}")
+ENDIF(NOT SHOULD_COMPILE)
+IF("${SHOULD_EXIT_WITH_ERROR}" STREQUAL "0")
+  MESSAGE(SEND_ERROR " exit_with_error passed with exit code ${SHOULD_EXIT_WITH_ERROR}")
+ENDIF("${SHOULD_EXIT_WITH_ERROR}" STREQUAL "0")
+

+ 4 - 0
Tests/TryCompile/exit_success.c

@@ -0,0 +1,4 @@
+int main()
+{
+  return 0;
+}

+ 4 - 0
Tests/TryCompile/exit_with_error.c

@@ -0,0 +1,4 @@
+int main()
+{
+  return -1;
+}