diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 4051da5e7..c7a55d838 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -653,11 +653,12 @@ IF(BUILD_TESTING) SET(COMPILER_IS_COMO 1) ENDIF(CMAKE_BASE_NAME MATCHES "^como$") IF(NOT COMPILER_IS_COMO) - ADD_TEST(complex ${CMAKE_CTEST_COMMAND} + ADD_TEST(complex ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/Complex" "${CMake_BINARY_DIR}/Tests/Complex" --build-two-config + --build-config-sample "${CMAKE_CTEST_COMMAND}" --build-generator ${CMAKE_TEST_GENERATOR} --build-project Complex --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM} diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index c47029980..d1a7736b9 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -22,6 +22,7 @@ #include "cmake.h" #include "cmGlobalGenerator.h" #include +#include "cmCTestTestHandler.h" //---------------------------------------------------------------------- cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler() @@ -161,6 +162,28 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) return 1; } + if ( this->CTest->GetConfigType().size() == 0 && + this->ConfigSample.size()) + { + // use the config sample to set the ConfigType + std::string fullPath; + std::string resultingConfig; + std::vector extraPaths; + std::vector failed; + fullPath = + cmCTestTestHandler::FindExecutable(this->CTest, + this->ConfigSample.c_str(), + resultingConfig, + extraPaths, + failed); + if (fullPath.size() && resultingConfig.size()) + { + this->CTest->SetConfigType(resultingConfig.c_str()); + } + out << "Using config sample with results: " + << fullPath << " and " << resultingConfig << std::endl; + } + // we need to honor the timeout specified, the timeout include cmake, build // and test time double clock_start = cmSystemTools::GetTime(); @@ -243,99 +266,26 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) } // now run the compiled test if we can find it - std::vector attempted; - std::vector failed; - std::string tempPath; - std::string filepath = - cmSystemTools::GetFilenamePath(this->TestCommand); - std::string filename = - cmSystemTools::GetFilenameName(this->TestCommand); - // if full path specified then search that first - if (filepath.size()) - { - tempPath = filepath; - tempPath += "/"; - tempPath += filename; - attempted.push_back(tempPath); - if(this->CTest->GetConfigType().size()) - { - tempPath = filepath; - tempPath += "/"; - tempPath += this->CTest->GetConfigType(); - tempPath += "/"; - tempPath += filename; - attempted.push_back(tempPath); - // If the file is an OSX bundle then the configtyp - // will be at the start of the path - tempPath = this->CTest->GetConfigType(); - tempPath += "/"; - tempPath += filepath; - tempPath += "/"; - tempPath += filename; - attempted.push_back(tempPath); - } - } - // otherwise search local dirs - else - { - attempted.push_back(filename); - if(this->CTest->GetConfigType().size()) - { - tempPath = this->CTest->GetConfigType(); - tempPath += "/"; - tempPath += filename; - attempted.push_back(tempPath); - } - } + // store the final location in fullPath + std::string fullPath; + std::string resultingConfig; + std::vector extraPaths; // if this->ExecutableDirectory is set try that as well if (this->ExecutableDirectory.size()) { - tempPath = this->ExecutableDirectory; + std::string tempPath = this->ExecutableDirectory; tempPath += "/"; tempPath += this->TestCommand; - attempted.push_back(tempPath); - if(this->CTest->GetConfigType().size()) - { - tempPath = this->ExecutableDirectory; - tempPath += "/"; - tempPath += this->CTest->GetConfigType(); - tempPath += "/"; - tempPath += filename; - attempted.push_back(tempPath); - } + extraPaths.push_back(tempPath); } - - // store the final location in fullPath - std::string fullPath; - - // now look in the paths we specified above - for(unsigned int ai=0; - ai < attempted.size() && fullPath.size() == 0; ++ai) - { - // first check without exe extension - if(cmSystemTools::FileExists(attempted[ai].c_str()) - && !cmSystemTools::FileIsDirectory(attempted[ai].c_str())) - { - fullPath = cmSystemTools::CollapseFullPath(attempted[ai].c_str()); - } - // then try with the exe extension - else - { - failed.push_back(attempted[ai].c_str()); - tempPath = attempted[ai]; - tempPath += cmSystemTools::GetExecutableExtension(); - if(cmSystemTools::FileExists(tempPath.c_str()) - && !cmSystemTools::FileIsDirectory(tempPath.c_str())) - { - fullPath = cmSystemTools::CollapseFullPath(tempPath.c_str()); - } - else - { - failed.push_back(tempPath.c_str()); - } - } - } - + std::vector failed; + fullPath = + cmCTestTestHandler::FindExecutable(this->CTest, + this->TestCommand.c_str(), + resultingConfig, + extraPaths, + failed); + if(!cmSystemTools::FileExists(fullPath.c_str())) { out << "Could not find path to executable, perhaps it was not built: " @@ -489,6 +439,12 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments( idx++; this->BuildMakeProgram = allArgs[idx]; } + if(currentArg.find("--build-config-sample",0) == 0 && + idx < allArgs.size() - 1) + { + idx++; + this->ConfigSample = allArgs[idx]; + } if(currentArg.find("--build-noclean",0) == 0) { this->BuildNoClean = true; @@ -525,4 +481,3 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments( return 1; } - diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h index b5fd639db..c77ff9ade 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.h +++ b/Source/CTest/cmCTestBuildAndTestHandler.h @@ -65,6 +65,7 @@ protected: std::vector BuildOptions; bool BuildTwoConfig; std::string BuildMakeProgram; + std::string ConfigSample; std::string SourceDir; std::string BinaryDir; std::string BuildProject; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 4d91f3af0..7552f7522 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -218,8 +218,10 @@ bool cmCTestSetTestsPropertiesCommand::InitialPass( // of where it was found. The directory and filename to search for are passed // in as well an a subdir (typically used for configuraitons such as // Release/Debug/etc) -bool TryExecutable(const char *dir, const char *file, - std::string *fullPath, const char *subdir) +bool cmCTestTestHandler::TryExecutable(const char *dir, + const char *file, + std::string *fullPath, + const char *subdir) { // try current directory std::string tryPath; @@ -1080,88 +1082,171 @@ int cmCTestTestHandler::ExecuteCommands(std::vector& vec) // Find the appropriate executable to run for a test std::string cmCTestTestHandler::FindTheExecutable(const char *exe) { - std::string fullPath = ""; - std::string dir; - std::string file; + std::string resConfig; + std::vector extraPaths; + std::vector failedPaths; + return cmCTestTestHandler::FindExecutable(this->CTest, + exe, resConfig, + extraPaths, + failedPaths); +} - cmSystemTools::SplitProgramPath(exe, dir, file); - // first try to find the executable given a config type subdir if there is - // one - if(this->CTest->GetConfigType() != "" && - ::TryExecutable(dir.c_str(), file.c_str(), &fullPath, - this->CTest->GetConfigType().c_str())) +// add additional configuraitons to the search path +void cmCTestTestHandler +::AddConfigurations(cmCTest *ctest, + std::vector &attempted, + std::vector &attemptedConfigs, + std::string filepath, + std::string &filename) +{ + std::string tempPath; + + if (filepath.size()) { - return fullPath; + filepath += "/"; } - - // next try the current directory as the subdir - if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,".")) + tempPath = filepath + filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back(""); + + if(ctest->GetConfigType().size()) { - return fullPath; + tempPath = filepath; + tempPath += ctest->GetConfigType(); + tempPath += "/"; + tempPath += filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back(ctest->GetConfigType()); + // If the file is an OSX bundle then the configtyp + // will be at the start of the path + tempPath = ctest->GetConfigType(); + tempPath += "/"; + tempPath += filepath; + tempPath += filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back(ctest->GetConfigType()); } - - // try without the config subdir - if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"")) + else { - return fullPath; + // no config specified to try some options + tempPath = filepath; + tempPath += "Deployment/"; + tempPath += filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back("Deployment"); + tempPath = filepath; + tempPath += "Development/"; + tempPath += filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back("Deployment"); + tempPath = filepath; + tempPath += "Release/"; + tempPath += filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back("Release"); + tempPath = filepath; + tempPath += "Debug/"; + tempPath += filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back("Debug"); + tempPath = filepath; + tempPath += "MinSizeRel/"; + tempPath += filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back("MinSizeRel"); + tempPath = filepath; + tempPath += "RelWithDebInfo/"; + tempPath += filename; + attempted.push_back(tempPath); + attemptedConfigs.push_back("RelWithDebInfo"); } +} - if ( this->CTest->GetConfigType() == "" ) + +//---------------------------------------------------------------------- +// Find the appropriate executable to run for a test +std::string cmCTestTestHandler +::FindExecutable(cmCTest *ctest, + const char *testCommand, + std::string &resultingConfig, + std::vector &extraPaths, + std::vector &failed) +{ + // now run the compiled test if we can find it + std::vector attempted; + std::vector attemptedConfigs; + std::string tempPath; + std::string filepath = + cmSystemTools::GetFilenamePath(testCommand); + std::string filename = + cmSystemTools::GetFilenameName(testCommand); + + cmCTestTestHandler::AddConfigurations(ctest, attempted, + attemptedConfigs, + filepath,filename); + + // if extraPaths are provided and we were not passed a full path, try them, + // try any extra paths + if (filepath.size() == 0) { - // No config type, so try to guess it - if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Deployment")) + for (unsigned int i = 0; i < extraPaths.size(); ++i) { - return fullPath; - } - - if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Development")) - { - return fullPath; - } - - if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Release")) - { - return fullPath; - } - - if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Debug")) - { - return fullPath; - } - - if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"MinSizeRel")) - { - return fullPath; - } - - if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"RelWithDebInfo")) - { - return fullPath; + std::string filepathExtra = + cmSystemTools::GetFilenamePath(extraPaths[i]); + std::string filenameExtra = + cmSystemTools::GetFilenameName(extraPaths[i]); + cmCTestTestHandler::AddConfigurations(ctest,attempted, + attemptedConfigs, + filepathExtra, + filenameExtra); } } + // store the final location in fullPath + std::string fullPath; + + // now look in the paths we specified above + for(unsigned int ai=0; + ai < attempted.size() && fullPath.size() == 0; ++ai) + { + // first check without exe extension + if(cmSystemTools::FileExists(attempted[ai].c_str()) + && !cmSystemTools::FileIsDirectory(attempted[ai].c_str())) + { + fullPath = cmSystemTools::CollapseFullPath(attempted[ai].c_str()); + resultingConfig = attemptedConfigs[ai]; + } + // then try with the exe extension + else + { + failed.push_back(attempted[ai].c_str()); + tempPath = attempted[ai]; + tempPath += cmSystemTools::GetExecutableExtension(); + if(cmSystemTools::FileExists(tempPath.c_str()) + && !cmSystemTools::FileIsDirectory(tempPath.c_str())) + { + fullPath = cmSystemTools::CollapseFullPath(tempPath.c_str()); + resultingConfig = attemptedConfigs[ai]; + } + else + { + failed.push_back(tempPath.c_str()); + } + } + } + // if everything else failed, check the users path, but only if a full path - // wasn;t specified - if (dir.size() == 0) + // wasn't specified + if (fullPath.size() == 0 && filepath.size() == 0) { - std::string path = cmSystemTools::FindProgram(file.c_str()); + std::string path = cmSystemTools::FindProgram(filename.c_str()); if (path != "") { + resultingConfig = ""; return path; } } - - if ( this->CTest->GetConfigType() != "" ) - { - dir += "/"; - dir += this->CTest->GetConfigType(); - dir += "/"; - dir += file; - cmSystemTools::Error("config type specified on the command line, but " - "test executable not found.", - dir.c_str()); - return ""; - } + return fullPath; } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index c23089f23..6b81f8aa3 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -103,6 +103,25 @@ public: cmCTestTestProperties* Properties; }; + // useful function for looking for a test + static bool TryExecutable(const char *dir, const char *file, + std::string *fullPath, + const char *subdir); + + // add configuraitons to a search path for an executable + static void AddConfigurations(cmCTest *ctest, + std::vector &attempted, + std::vector &attemptedConfigs, + std::string filepath, + std::string &filename); + + // full signature static method to find an executable + static std::string FindExecutable(cmCTest *ctest, + const char *testCommand, + std::string &resultingConfig, + std::vector &extraPaths, + std::vector &failed); + protected: virtual int PreProcessHandler(); virtual int PostProcessHandler(); diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 864ae2688..346977c3d 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -162,6 +162,10 @@ static const cmDocumentationEntry cmDocumentationOptions[] = {"--build-project", "Specify the name of the project to build.", "" }, {"--build-makeprogram", "Specify the make program to use.", "" }, {"--build-noclean", "Skip the make clean step.", "" }, + {"--build-config-sample", + "A sample executable to use to determine the configuraiton", + "A sample executable to use to determine the configuraiton that " + "should be used. e.g. Debug/Release/etc" }, {"--build-options", "Add extra options to the build step.", "This option must be the last option with the exception of --test-command" },