b22e5d0ab7
Ensure that cmStandardIncludes.h is included before any platform header in cmGeneratorExpressionEvaluator.h. That file needs to change as a result of removal of the cmMakefile.h header from cmGeneratorExpressionNode.h, affecting the compilation of cmGeneratorExpressionNode.cxx. On AIX we need to include our own headers first to get large file support macros defined consistently within system headers. The old order in this header worked only because it was always included after other headers.
221 lines
7.3 KiB
C++
221 lines
7.3 KiB
C++
/*============================================================================
|
|
CMake - Cross Platform Makefile Generator
|
|
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
|
|
Distributed under the OSI-approved BSD License (the "License");
|
|
see accompanying file Copyright.txt for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
See the License for more information.
|
|
============================================================================*/
|
|
#include "cmTestGenerator.h"
|
|
|
|
#include "cmGeneratorExpression.h"
|
|
#include "cmOutputConverter.h"
|
|
#include "cmLocalGenerator.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmTest.h"
|
|
|
|
//----------------------------------------------------------------------------
|
|
cmTestGenerator
|
|
::cmTestGenerator(cmTest* test,
|
|
std::vector<std::string> const& configurations):
|
|
cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations),
|
|
Test(test)
|
|
{
|
|
this->ActionsPerConfig = !test->GetOldStyle();
|
|
this->TestGenerated = false;
|
|
this->LG = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
cmTestGenerator
|
|
::~cmTestGenerator()
|
|
{
|
|
}
|
|
|
|
void cmTestGenerator::Compute(cmLocalGenerator* lg)
|
|
{
|
|
this->LG = lg;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmTestGenerator::GenerateScriptConfigs(std::ostream& os,
|
|
Indent const& indent)
|
|
{
|
|
// Create the tests.
|
|
this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmTestGenerator::GenerateScriptActions(std::ostream& os,
|
|
Indent const& indent)
|
|
{
|
|
if(this->ActionsPerConfig)
|
|
{
|
|
// This is the per-config generation in a single-configuration
|
|
// build generator case. The superclass will call our per-config
|
|
// method.
|
|
this->cmScriptGenerator::GenerateScriptActions(os, indent);
|
|
}
|
|
else
|
|
{
|
|
// This is an old-style test, so there is only one config.
|
|
//assert(this->Test->GetOldStyle());
|
|
this->GenerateOldStyle(os, indent);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
|
|
const std::string& config,
|
|
Indent const& indent)
|
|
{
|
|
this->TestGenerated = true;
|
|
|
|
// Set up generator expression evaluation context.
|
|
cmGeneratorExpression ge(this->Test->GetBacktrace());
|
|
|
|
// Start the test command.
|
|
os << indent << "add_test(" << this->Test->GetName() << " ";
|
|
|
|
// Get the test command line to be executed.
|
|
std::vector<std::string> const& command = this->Test->GetCommand();
|
|
|
|
// Check whether the command executable is a target whose name is to
|
|
// be translated.
|
|
std::string exe = command[0];
|
|
cmGeneratorTarget* target =
|
|
this->LG->FindGeneratorTargetToUse(exe);
|
|
if(target && target->GetType() == cmState::EXECUTABLE)
|
|
{
|
|
// Use the target file on disk.
|
|
exe = target->GetFullPath(config);
|
|
|
|
// Prepend with the emulator when cross compiling if required.
|
|
const char * emulator =
|
|
target->GetProperty("CROSSCOMPILING_EMULATOR");
|
|
if (emulator != 0)
|
|
{
|
|
std::vector<std::string> emulatorWithArgs;
|
|
cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
|
|
std::string emulatorExe(emulatorWithArgs[0]);
|
|
cmSystemTools::ConvertToUnixSlashes(emulatorExe);
|
|
os << cmOutputConverter::EscapeForCMake(emulatorExe) << " ";
|
|
for(std::vector<std::string>::const_iterator ei =
|
|
emulatorWithArgs.begin()+1;
|
|
ei != emulatorWithArgs.end();
|
|
++ei)
|
|
{
|
|
os << cmOutputConverter::EscapeForCMake(*ei) << " ";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Use the command name given.
|
|
exe = ge.Parse(exe.c_str())->Evaluate(this->LG, config);
|
|
cmSystemTools::ConvertToUnixSlashes(exe);
|
|
}
|
|
|
|
// Generate the command line with full escapes.
|
|
os << cmOutputConverter::EscapeForCMake(exe);
|
|
for(std::vector<std::string>::const_iterator ci = command.begin()+1;
|
|
ci != command.end(); ++ci)
|
|
{
|
|
os << " " << cmOutputConverter::EscapeForCMake(
|
|
ge.Parse(*ci)->Evaluate(
|
|
this->LG, config));
|
|
}
|
|
|
|
// Finish the test command.
|
|
os << ")\n";
|
|
|
|
// Output properties for the test.
|
|
cmPropertyMap& pm = this->Test->GetProperties();
|
|
if(!pm.empty())
|
|
{
|
|
os << indent << "set_tests_properties(" << this->Test->GetName()
|
|
<< " PROPERTIES ";
|
|
for(cmPropertyMap::const_iterator i = pm.begin();
|
|
i != pm.end(); ++i)
|
|
{
|
|
os << " " << i->first
|
|
<< " " << cmOutputConverter::EscapeForCMake(
|
|
ge.Parse(i->second.GetValue())->Evaluate(this->LG,
|
|
config));
|
|
}
|
|
os << ")" << std::endl;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os,
|
|
Indent const& indent)
|
|
{
|
|
os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmTestGenerator::NeedsScriptNoConfig() const
|
|
{
|
|
return (this->TestGenerated && // test generated for at least one config
|
|
this->ActionsPerConfig && // test is config-aware
|
|
this->Configurations.empty() && // test runs in all configs
|
|
!this->ConfigurationTypes->empty()); // config-dependent command
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
|
|
Indent const& indent)
|
|
{
|
|
this->TestGenerated = true;
|
|
|
|
// Get the test command line to be executed.
|
|
std::vector<std::string> const& command = this->Test->GetCommand();
|
|
|
|
std::string exe = command[0];
|
|
cmSystemTools::ConvertToUnixSlashes(exe);
|
|
fout << indent;
|
|
fout << "add_test(";
|
|
fout << this->Test->GetName() << " \"" << exe << "\"";
|
|
|
|
for(std::vector<std::string>::const_iterator argit = command.begin()+1;
|
|
argit != command.end(); ++argit)
|
|
{
|
|
// Just double-quote all arguments so they are re-parsed
|
|
// correctly by the test system.
|
|
fout << " \"";
|
|
for(std::string::const_iterator c = argit->begin();
|
|
c != argit->end(); ++c)
|
|
{
|
|
// Escape quotes within arguments. We should escape
|
|
// backslashes too but we cannot because it makes the result
|
|
// inconsistent with previous behavior of this command.
|
|
if((*c == '"'))
|
|
{
|
|
fout << '\\';
|
|
}
|
|
fout << *c;
|
|
}
|
|
fout << "\"";
|
|
}
|
|
fout << ")" << std::endl;
|
|
|
|
// Output properties for the test.
|
|
cmPropertyMap& pm = this->Test->GetProperties();
|
|
if(!pm.empty())
|
|
{
|
|
fout << indent << "set_tests_properties(" << this->Test->GetName()
|
|
<< " PROPERTIES ";
|
|
for(cmPropertyMap::const_iterator i = pm.begin();
|
|
i != pm.end(); ++i)
|
|
{
|
|
fout << " " << i->first
|
|
<< " " << cmOutputConverter::EscapeForCMake(i->second.GetValue());
|
|
}
|
|
fout << ")" << std::endl;
|
|
}
|
|
}
|