summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmBootstrapCommands.cxx1
-rw-r--r--Source/cmCoreTryCompile.cxx376
-rw-r--r--Source/cmCoreTryCompile.h65
-rw-r--r--Source/cmTryCompileCommand.cxx376
-rw-r--r--Source/cmTryCompileCommand.h32
-rw-r--r--Source/cmTryRunCommand.cxx84
-rw-r--r--Source/cmTryRunCommand.h6
-rw-r--r--Tests/TryCompile/CMakeLists.txt32
-rw-r--r--Tests/TryCompile/exit_success.c4
-rw-r--r--Tests/TryCompile/exit_with_error.c4
10 files changed, 535 insertions, 445 deletions
diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx
index c4bfeae..19be6df 100644
--- a/Source/cmBootstrapCommands.cxx
+++ b/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"
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
new file mode 100644
index 0000000..4b6e742
--- /dev/null
+++ b/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;
+}
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
new file mode 100644
index 0000000..f57bfda
--- /dev/null
+++ b/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
diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx
index e3d47ee..a48f723 100644
--- a/Source/cmTryCompileCommand.cxx
+++ b/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 "";
-}
diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h
index 25fbea5..38230d4 100644
--- a/Source/cmTryCompileCommand.h
+++ b/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:
/**
@@ -55,32 +55,6 @@ public:
}
/**
- * 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);
};
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index 8179a77..bcebd0f 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/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;
}
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index 40c3de5..b11a7c4 100644
--- a/Source/cmTryRunCommand.h
+++ b/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);
};
diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt
index a9a0883..0de616f 100644
--- a/Tests/TryCompile/CMakeLists.txt
+++ b/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")
+
diff --git a/Tests/TryCompile/exit_success.c b/Tests/TryCompile/exit_success.c
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/TryCompile/exit_success.c
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/Tests/TryCompile/exit_with_error.c b/Tests/TryCompile/exit_with_error.c
new file mode 100644
index 0000000..a9a283d
--- /dev/null
+++ b/Tests/TryCompile/exit_with_error.c
@@ -0,0 +1,4 @@
+int main()
+{
+ return -1;
+}