Commit 4d30cb30 authored by Ken Martin's avatar Ken Martin
Browse files

ENH: ctest now uses CMake global generator to do the build part of build-and-test

parent 832fa0e6
......@@ -1733,53 +1733,50 @@ void CMakeStdoutCallback(const char* m, int len, void* s)
out->append(m, len);
}
int cmCTest::RunCMakeAndTest(std::string* outstring)
{
int cmCTest::RunCMake(std::string* outstring, cmOStringStream &out,
std::string &cmakeOutString, std::string &cwd,
cmake *cm)
{
unsigned int k;
std::string cmakeOutString;
cmSystemTools::SetErrorCallback(CMakeMessageCallback, &cmakeOutString);
cmSystemTools::SetStdoutCallback(CMakeStdoutCallback, &cmakeOutString);
cmOStringStream out;
cmake cm;
double timeout = m_TimeOut;
// default to the build type of ctest itself
if(m_ConfigType.size() == 0)
std::vector<std::string> args;
args.push_back(m_CMakeSelf);
args.push_back(m_SourceDir);
if(m_BuildGenerator.size())
{
#ifdef CMAKE_INTDIR
m_ConfigType = CMAKE_INTDIR;
#endif
std::string generator = "-G";
generator += m_BuildGenerator;
args.push_back(generator);
}
if ( m_ConfigType.size() > 0 )
{
std::string btype = "-DBUILD_TYPE:STRING=" + m_ConfigType;
args.push_back(btype);
}
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
out << "Internal cmake changing into directory: " << m_BinaryDir << "\n";
if (!cmSystemTools::FileIsDirectory(m_BinaryDir.c_str()))
for(k=0; k < m_BuildOptions.size(); ++k)
{
cmSystemTools::MakeDirectory(m_BinaryDir.c_str());
args.push_back(m_BuildOptions[k]);
}
cmSystemTools::ChangeDirectory(m_BinaryDir.c_str());
if(!m_BuildNoCMake)
if (cm->Run(args) != 0)
{
std::vector<std::string> args;
args.push_back(m_CMakeSelf);
args.push_back(m_SourceDir);
if(m_BuildGenerator.size())
{
std::string generator = "-G";
generator += m_BuildGenerator;
args.push_back(generator);
}
if ( m_ConfigType.size() > 0 )
out << "Error: cmake execution failed\n";
out << cmakeOutString << "\n";
// return to the original directory
cmSystemTools::ChangeDirectory(cwd.c_str());
if(outstring)
{
std::string btype = "-DBUILD_TYPE:STRING=" + m_ConfigType;
args.push_back(btype);
*outstring = out.str();
}
for(k=0; k < m_BuildOptions.size(); ++k)
else
{
args.push_back(m_BuildOptions[k]);
std::cerr << out.str() << "\n";
}
if (cm.Run(args) != 0)
return 1;
}
// do another config?
if(m_BuildTwoConfig)
{
if (cm->Run(args) != 0)
{
out << "Error: cmake execution failed\n";
out << cmakeOutString << "\n";
......@@ -1795,222 +1792,76 @@ int cmCTest::RunCMakeAndTest(std::string* outstring)
}
return 1;
}
if(m_BuildTwoConfig)
{
if (cm.Run(args) != 0)
{
out << "Error: cmake execution failed\n";
out << cmakeOutString << "\n";
// return to the original directory
cmSystemTools::ChangeDirectory(cwd.c_str());
if(outstring)
{
*outstring = out.str();
}
else
{
std::cerr << out.str() << "\n";
}
return 1;
}
}
}
}
return 0;
}
cmSystemTools::SetErrorCallback(0, 0);
out << cmakeOutString << "\n";
if(m_BuildMakeProgram.size() == 0)
{
out << "Error: cmake does not have a valid MAKEPROGRAM\n";
out << "Did you specify a --build-makeprogram and a --build-generator?\n";
if(outstring)
{
*outstring = out.str();
}
else
{
std::cerr << out.str() << "\n";
}
return 1;
}
int cmCTest::RunCMakeAndTest(std::string* outstring)
{
unsigned int k;
std::string cmakeOutString;
cmSystemTools::SetErrorCallback(CMakeMessageCallback, &cmakeOutString);
cmSystemTools::SetStdoutCallback(CMakeStdoutCallback, &cmakeOutString);
cmOStringStream out;
double timeout = m_TimeOut;
int retVal = 0;
std::string makeCommand = cmSystemTools::ConvertToOutputPath(m_BuildMakeProgram.c_str());
std::string lowerCaseCommand = cmSystemTools::LowerCase(makeCommand);
// if msdev is the make program then do the following
// MSDEV 6.0
if(lowerCaseCommand.find("msdev") != std::string::npos)
// default to the build type of ctest itself
if(m_ConfigType.size() == 0)
{
// if there are spaces in the makeCommand, assume a full path
// and convert it to a path with no spaces in it as the
// RunSingleCommand does not like spaces
#if defined(_WIN32) && !defined(__CYGWIN__)
if(makeCommand.find(' ') != std::string::npos)
{
cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
}
#ifdef CMAKE_INTDIR
m_ConfigType = CMAKE_INTDIR;
#endif
makeCommand += " ";
makeCommand += m_BuildProject;
makeCommand += ".dsw /MAKE \"";
if(m_BuildTarget.size())
{
makeCommand += m_BuildTarget;
}
else
{
makeCommand += "ALL_BUILD";
}
makeCommand += " - ";
makeCommand += m_ConfigType;
if(m_BuildNoClean)
{
makeCommand += "\" /BUILD";
}
else
{
makeCommand += "\" /REBUILD";
}
}
// MSDEV 7.0 .NET
else if (lowerCaseCommand.find("devenv") != std::string::npos)
// make sure the binary dir is there
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
out << "Internal cmake changing into directory: " << m_BinaryDir << "\n";
if (!cmSystemTools::FileIsDirectory(m_BinaryDir.c_str()))
{
#if defined(_WIN32) && !defined(__CYGWIN__)
if(makeCommand.find(' ') != std::string::npos)
{
cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
}
#endif
makeCommand += " ";
makeCommand += m_BuildProject;
makeCommand += ".sln ";
if(m_BuildNoClean)
{
makeCommand += "/build ";
}
else
{
makeCommand += "/rebuild ";
}
makeCommand += m_ConfigType + " /project ";
if(m_BuildTarget.size())
{
makeCommand += m_BuildTarget;
}
else
{
makeCommand += "ALL_BUILD";
}
}
else if (lowerCaseCommand.find("xcode") != std::string::npos)
{
makeCommand += " -project ";
makeCommand += m_BuildProject;
makeCommand += ".xcode";
makeCommand += " build -target ";
if (m_BuildTarget.size())
{
makeCommand += m_BuildTarget;
}
else
{
makeCommand += "ALL_BUILD ";
}
makeCommand += " -buildstyle Development ";
}
else if (lowerCaseCommand.find("make") != std::string::npos)
{
// assume a make sytle program
// clean first
if(!m_BuildNoClean)
{
std::string cleanCommand = makeCommand;
cleanCommand += " clean";
out << "Running make clean command: " << cleanCommand.c_str() << " ...\n";
retVal = 0;
std::string output;
if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), &output, &retVal, 0,
false, timeout) ||
retVal)
{
out << "Error: " << cleanCommand.c_str() << " execution failed\n";
out << output.c_str() << "\n";
// return to the original directory
cmSystemTools::ChangeDirectory(cwd.c_str());
out << "Return value: " << retVal << std::endl;
if(outstring)
{
*outstring = out.str();
}
else
{
std::cerr << out.str() << "\n";
}
return 1;
}
out << output;
}
cmSystemTools::MakeDirectory(m_BinaryDir.c_str());
}
cmSystemTools::ChangeDirectory(m_BinaryDir.c_str());
if(m_BuildTarget.size())
// should we cmake?
cmake cm;
cm.SetGlobalGenerator(cm.CreateGlobalGenerator(m_BuildGenerator.c_str()));
if(!m_BuildNoCMake)
{
// do the cmake step
if (this->RunCMake(outstring,out,cmakeOutString,cwd,&cm))
{
makeCommand += " ";
makeCommand += m_BuildTarget;
return 1;
}
}
// command line make program
out << "Running make command: " << makeCommand.c_str() << "\n";
retVal = 0;
// do the build
std::string output;
if (!cmSystemTools::RunSingleCommand(makeCommand.c_str(), &output, &retVal, 0, false, timeout))
retVal = cm.GetGlobalGenerator()->Build(
m_SourceDir.c_str(), m_BinaryDir.c_str(),
m_BuildProject.c_str(), m_BuildTarget.c_str(),
&output, m_BuildMakeProgram.c_str(),
m_ConfigType.c_str(),!m_BuildNoClean);
out << output;
if(outstring)
{
out << "Error: " << makeCommand.c_str() << " execution failed\n";
out << output.c_str() << "\n";
// return to the original directory
cmSystemTools::ChangeDirectory(cwd.c_str());
out << "Return value: " << retVal << std::endl;
if(outstring)
{
*outstring = out.str();
}
else
{
std::cerr << out.str() << "\n";
}
return 1;
*outstring = out.str();
}
if ( retVal )
// if the build failed then return
if (retVal)
{
if(outstring)
{
*outstring = out.str();
*outstring += "Building of project failed\n";
*outstring += output;
*outstring += "\n";
}
else
{
std::cerr << "Building of project failed\n";
std::cerr << out.str() << output << "\n";
}
// return to the original directory
cmSystemTools::ChangeDirectory(cwd.c_str());
return 1;
}
out << output;
if(m_TestCommand.size() == 0)
// if not test was specified then we are done
if (!m_TestCommand.size())
{
if(outstring)
{
*outstring = out.str();
}
else
{
std::cout << out.str() << "\n";
}
return retVal;
return 0;
}
// now run the compiled test if we can find it
std::vector<std::string> attempted;
std::vector<std::string> failed;
......
......@@ -23,6 +23,7 @@
#include "cmListFileCache.h"
#include <time.h>
class cmake;
class cmMakefile;
class cmCTestGenericHandler;
class cmGeneratedFileStream;
......@@ -279,6 +280,10 @@ private:
///! Run CMake and build a test and then run it as a single test.
int RunCMakeAndTest(std::string* output);
int RunCMake(std::string* outstring, cmOStringStream &out,
std::string &cmakeOutString,
std::string &cwd, cmake *cm);
///! Find the running cmake
void FindRunningCMake(const char* arg0);
......
......@@ -637,11 +637,11 @@ void cmGlobalGenerator::LocalGenerate()
delete lg;
}
int cmGlobalGenerator::TryCompile(const char *, const char *bindir,
const char *, const char *target,
std::string *output, cmMakefile*)
int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
const char *projectName,
const char *target,
std::string *output, cmMakefile *mf)
{
// now build the test
std::string makeCommand =
m_CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
if(makeCommand.size() == 0)
......@@ -650,6 +650,41 @@ int cmGlobalGenerator::TryCompile(const char *, const char *bindir,
"Generator cannot find the appropriate make command.");
return 1;
}
std::string newTarget;
if (target && strlen(target))
{
newTarget += target;
#if 0
#if defined(_WIN32) || defined(__CYGWIN__)
std::string tmp = target;
// if the target does not already end in . something
// then assume .exe
if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
{
newTarget += ".exe";
}
#endif // WIN32
#endif
}
const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
return this->Build(srcdir,bindir,projectName,
newTarget.c_str(),
output,makeCommand.c_str(),config,false);
}
int cmGlobalGenerator::Build(
const char *, const char *bindir,
const char *, const char *target,
std::string *output,
const char *makeCommandCSTR,
const char *config,
bool clean)
{
*output += "\nTesting TryCompileWithoutMakefile\n";
// now build the test
std::string makeCommand = makeCommandCSTR;
makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand.c_str());
/**
......@@ -664,39 +699,58 @@ int cmGlobalGenerator::TryCompile(const char *, const char *bindir,
{
makeCommand += " /NOLOGO ";
}
int retVal;
int timeout = cmGlobalGenerator::s_TryCompileTimeout;
bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
cmSystemTools::SetRunCommandHideConsole(true);
// should we do a clean first?
if (clean)
{
std::string cleanCommand = makeCommand + " clean";
if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), output,
&retVal, 0, false, timeout))
{
cmSystemTools::SetRunCommandHideConsole(hideconsole);
cmSystemTools::Error("Generator: execution of make clean failed.");
if (output)
{
*output += "\nGenerator: execution of make clean failed.\n";
}
// return to the original directory
cmSystemTools::ChangeDirectory(cwd.c_str());
return 1;
}
}
// now build
if (target)
if (target && strlen(target))
{
makeCommand += " ";
makeCommand += target;
#if defined(_WIN32) || defined(__CYGWIN__)
std::string tmp = target;
// if the target does not already end in . something
// then assume .exe
if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
{
makeCommand += ".exe";
}
#endif // WIN32
}
else
{
makeCommand += " all";
}
int retVal;
int timeout = cmGlobalGenerator::s_TryCompileTimeout;
bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
cmSystemTools::SetRunCommandHideConsole(true);
if (!cmSystemTools::RunSingleCommand(makeCommand.c_str(), output,
&retVal, 0, false, timeout))
&retVal, 0, false, timeout))
{
cmSystemTools::SetRunCommandHideConsole(hideconsole);
cmSystemTools::Error("Generator: execution of make failed.");
if (output)
{
*output += "\nGenerator: execution of make failed.\n";
}
// return to the original directory
cmSystemTools::ChangeDirectory(cwd.c_str());
return 1;
}
cmSystemTools::SetRunCommandHideConsole(hideconsole);
// The SGI MipsPro 7.3 compiler does not return an error code when
......
......@@ -93,6 +93,19 @@ public:
const char *projectName, const char *targetName,
std::string *output, cmMakefile* mf);
/**
* Build a file given the following information. This is a more direct call
* that is used by both CTest and TryCompile. If target name is NULL or
* empty then all is assumed. clean indicates if a "make clean" should be
* done first.
*/
virtual int Build(const char *srcdir, const char *bindir,
const char *projectName, const char *targetName,
std::string *output,
const char *makeProgram, const char *config,
bool clean);
///! Set the CMake instance
void SetCMakeInstance(cmake *cm) {
this->m_CMakeInstance = cm; };
......
......@@ -67,21 +67,23 @@ void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile* mf)
}
}
int cmGlobalVisualStudio6Generator::TryCompile(const char *,
const char *bindir,
const char *projectName,
const char *targetName,
std::string *output,
cmMakefile* mf)
int cmGlobalVisualStudio6Generator::Build(
const char *,
const char *bindir,
const char *projectName,
const char *targetName,
std::string *output,
const char *makeCommandCSTR,
const char *config,
bool clean)
{
// now build the test
std::string makeCommand =
m_CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
std::vector<std::string> mp;
mp.push_back("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\6.0\\Setup;VsCommonDir]/MSDev98/Bin");
cmSystemTools::ExpandRegistryValues(mp[0]);
std::string originalCommand = makeCommand;
makeCommand = cmSystemTools::FindProgram(makeCommand.c_str(), mp);
std::string originalCommand = makeCommandCSTR;
std::string makeCommand =
cmSystemTools::FindProgram(makeCommandCSTR, mp);
if(makeCommand.size() == 0)
{
std::string e = "Generator cannot find Visual Studio 6 msdev program \"";
......@@ -119,7 +121,7 @@ int cmGlobalVisualStudio6Generator::TryCompile(const char *,
makeCommand += "ALL_BUILD";
}
makeCommand += " - ";
if(const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"))
if(config)
{
makeCommand += config;
}
......@@ -127,7 +129,14 @@ int cmGlobalVisualStudio6Generator::TryCompile(const char *,
{
makeCommand += "Debug";
}
makeCommand += "\"";
if(clean)
{
makeCommand += "\" /REBUILD";
}
else
{
makeCommand += "\" /BUILD";
}
int retVal;
int timeout = cmGlobalGenerator::s_TryCompileTimeout;
if (!cmSystemTools::RunSingleCommand(makeCommand.c_str(), output,
......
......@@ -47,14 +47,18 @@ public:
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
*/
virtual void EnableLanguage(std::vector<std::string>const& languages, cmMakefile *);
virtual void EnableLanguage(std::vector<std::string>const& languages,
cmMakefile *);
/**
* Try running cmake and building a file. This is used for dynalically
* loaded commands, not as part of the usual build process.
*/
virtual int TryCompile(const char *srcdir, const char *bindir,
const char *projectName, const char *targetName,
std::string *output, cmMakefile* mf);
virtual int Build(const char *srcdir, const char *bindir,
const char *projectName, const char *targetName,
std::string *output,
const char *makeProgram,