Commit 3abf39ed authored by Ken Martin's avatar Ken Martin
Browse files

ENH: support for --build-config-sample feature #1022

parent fc7c4334
......@@ -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}
......
......@@ -22,6 +22,7 @@
#include "cmake.h"
#include "cmGlobalGenerator.h"
#include <cmsys/Process.h>
#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<std::string> extraPaths;
std::vector<std::string> 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<std::string> attempted;
std::vector<std::string> 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<std::string> 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);
}
}
// 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());
}
}
extraPaths.push_back(tempPath);
}
std::vector<std::string> 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;
}
......@@ -65,6 +65,7 @@ protected:
std::vector<std::string> BuildOptions;
bool BuildTwoConfig;
std::string BuildMakeProgram;
std::string ConfigSample;
std::string SourceDir;
std::string BinaryDir;
std::string BuildProject;
......
......@@ -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<cmStdString>& 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<std::string> extraPaths;
std::vector<std::string> 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()))
{
return fullPath;
}
// add additional configuraitons to the search path
void cmCTestTestHandler
::AddConfigurations(cmCTest *ctest,
std::vector<std::string> &attempted,
std::vector<std::string> &attemptedConfigs,
std::string filepath,
std::string &filename)
{
std::string tempPath;
// next try the current directory as the subdir
if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"."))
if (filepath.size())
{
return fullPath;
filepath += "/";
}
// try without the config subdir
if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,""))
tempPath = filepath + filename;
attempted.push_back(tempPath);
attemptedConfigs.push_back("");
if(ctest->GetConfigType().size())
{
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());
}
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() == "" )
{
// No config type, so try to guess it
if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Deployment"))
{
return fullPath;
}
if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Development"))
{
return fullPath;
}
//----------------------------------------------------------------------
// Find the appropriate executable to run for a test
std::string cmCTestTestHandler
::FindExecutable(cmCTest *ctest,
const char *testCommand,
std::string &resultingConfig,
std::vector<std::string> &extraPaths,
std::vector<std::string> &failed)
{
// now run the compiled test if we can find it
std::vector<std::string> attempted;
std::vector<std::string> attemptedConfigs;
std::string tempPath;
std::string filepath =
cmSystemTools::GetFilenamePath(testCommand);
std::string filename =
cmSystemTools::GetFilenameName(testCommand);
if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Release"))
{
return fullPath;
}
cmCTestTestHandler::AddConfigurations(ctest, attempted,
attemptedConfigs,
filepath,filename);
if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Debug"))
// if extraPaths are provided and we were not passed a full path, try them,
// try any extra paths
if (filepath.size() == 0)
{
for (unsigned int i = 0; i < extraPaths.size(); ++i)
{
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;
if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"MinSizeRel"))
// 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()))
{
return fullPath;
fullPath = cmSystemTools::CollapseFullPath(attempted[ai].c_str());
resultingConfig = attemptedConfigs[ai];
}
if (::TryExecutable(dir.c_str(),file.c_str(),&fullPath,"RelWithDebInfo"))
// then try with the exe extension
else
{
return fullPath;
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;
}
......
......@@ -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<std::string> &attempted,
std::vector<std::string> &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<std::string> &extraPaths,
std::vector<std::string> &failed);
protected:
virtual int PreProcessHandler();
virtual int PostProcessHandler();
......
......@@ -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"
},
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment