summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorDavid Cole <david.cole@kitware.com>2009-12-04 17:09:01 (GMT)
committerDavid Cole <david.cole@kitware.com>2009-12-04 17:09:01 (GMT)
commit0b38bb4c535ae972d7f973e3e69945a6d0c14d75 (patch)
treeac80395b194b2a8ed2bcf6b1f997b62c21d151be /Source
parentaf14f1f2c3750ba3cf9b9cc1a809a88b1878a5c3 (diff)
downloadCMake-0b38bb4c535ae972d7f973e3e69945a6d0c14d75.zip
CMake-0b38bb4c535ae972d7f973e3e69945a6d0c14d75.tar.gz
CMake-0b38bb4c535ae972d7f973e3e69945a6d0c14d75.tar.bz2
Fix issue #2336 - honor the -C arg to ctest. Honor it for all stages of running -D dashboards from the command line and running ctest_configure, ctest_build and ctest_test commands in -S scripts. Also, allow a script to change it by setting the CTEST_CONFIGURATION_TYPE variable: allows for multiple configuration build/test cycles within one script. Add a new signature for the cmake command build_command that accepts CONFIGURATION as one argument. The original build_command signature is still there, but now marked as deprecated in the documentation. Of course... also add CTestConfig tests to verify that -C is honored for -D dashboards and -S scripts.
Diffstat (limited to 'Source')
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx16
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx36
-rw-r--r--Source/CTest/cmCTestBuildHandler.h3
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx35
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx11
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx2
-rw-r--r--Source/cmBuildCommand.cxx115
-rw-r--r--Source/cmBuildCommand.h49
-rw-r--r--Source/cmGlobalGenerator.h4
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h5
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx15
-rw-r--r--Source/cmGlobalXCodeGenerator.h5
12 files changed, 268 insertions, 28 deletions
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index af21e0d..7a4d877 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -53,6 +53,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
return 0;
}
this->Handler = (cmCTestBuildHandler*)handler;
+
const char* ctestBuildCommand
= this->Makefile->GetDefinition("CTEST_BUILD_COMMAND");
if ( ctestBuildCommand && *ctestBuildCommand )
@@ -67,10 +68,21 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
= (this->Values[ctb_PROJECT_NAME] && *this->Values[ctb_PROJECT_NAME])
? this->Values[ctb_PROJECT_NAME]
: this->Makefile->GetDefinition("CTEST_PROJECT_NAME");
+
+ // Build configuration is determined by: CONFIGURATION argument,
+ // or CTEST_BUILD_CONFIGURATION script variable, or
+ // CTEST_CONFIGURATION_TYPE script variable, or ctest -C command
+ // line argument... in that order.
+ //
+ const char* ctestBuildConfiguration
+ = this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
const char* cmakeBuildConfiguration
= (this->Values[ctb_CONFIGURATION] && *this->Values[ctb_CONFIGURATION])
? this->Values[ctb_CONFIGURATION]
- : this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
+ : ((ctestBuildConfiguration && *ctestBuildConfiguration)
+ ? ctestBuildConfiguration
+ : this->CTest->GetConfigType().c_str());
+
const char* cmakeBuildAdditionalFlags
= (this->Values[ctb_FLAGS] && *this->Values[ctb_FLAGS])
? this->Values[ctb_FLAGS]
@@ -117,7 +129,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
}
cmakeBuildConfiguration = config;
}
-
+
std::string buildCommand
= this->GlobalGenerator->
GenerateBuildCommand(cmakeMakeProgram,
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 0095bbc..a125459 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -265,6 +265,32 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf)
}
//----------------------------------------------------------------------
+std::string cmCTestBuildHandler::GetMakeCommand()
+{
+ std::string makeCommand
+ = this->CTest->GetCTestConfiguration("MakeCommand");
+ cmCTestLog(this->CTest,
+ HANDLER_VERBOSE_OUTPUT, "MakeCommand:" << makeCommand <<
+ "\n");
+
+ std::string configType = this->CTest->GetConfigType();
+ if (configType == "")
+ {
+ configType
+ = this->CTest->GetCTestConfiguration("DefaultCTestConfigurationType");
+ }
+ if (configType == "")
+ {
+ configType = "Release";
+ }
+
+ cmSystemTools::ReplaceString(makeCommand,
+ "${CTEST_CONFIGURATION_TYPE}", configType.c_str());
+
+ return makeCommand;
+}
+
+//----------------------------------------------------------------------
//clearly it would be nice if this were broken up into a few smaller
//functions and commented...
int cmCTestBuildHandler::ProcessHandler()
@@ -300,11 +326,7 @@ int cmCTestBuildHandler::ProcessHandler()
}
// Determine build command and build directory
- const std::string &makeCommand
- = this->CTest->GetCTestConfiguration("MakeCommand");
- cmCTestLog(this->CTest,
- HANDLER_VERBOSE_OUTPUT, "MakeCommand:" << makeCommand <<
- "\n");
+ std::string makeCommand = this->GetMakeCommand();
if ( makeCommand.size() == 0 )
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
@@ -312,6 +334,7 @@ int cmCTestBuildHandler::ProcessHandler()
<< std::endl);
return -1;
}
+
const std::string &buildDirectory
= this->CTest->GetCTestConfiguration("BuildDirectory");
if ( buildDirectory.size() == 0 )
@@ -519,8 +542,7 @@ void cmCTestBuildHandler::GenerateXMLHeader(std::ostream& os)
static_cast<unsigned int>(this->StartBuildTime)
<< "</StartBuildTime>\n"
<< "<BuildCommand>"
- << cmXMLSafe(
- this->CTest->GetCTestConfiguration("MakeCommand"))
+ << cmXMLSafe(this->GetMakeCommand())
<< "</BuildCommand>" << std::endl;
}
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 7ee50be..439efd6 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -46,7 +46,10 @@ public:
int GetTotalErrors() { return this->TotalErrors;}
int GetTotalWarnings() { return this->TotalWarnings;}
+
private:
+ std::string GetMakeCommand();
+
//! Run command specialized for make and configure. Returns process status
// and retVal is return value or exception.
int RunMakeCommand(const char* command,
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index 00d9ec5..1ad4e24 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -11,6 +11,7 @@
============================================================================*/
#include "cmCTestConfigureCommand.h"
+#include "cmGlobalGenerator.h"
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
@@ -66,6 +67,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
const char* ctestConfigureCommand
= this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
+
if ( ctestConfigureCommand && *ctestConfigureCommand )
{
this->CTest->SetCTestConfiguration("ConfigureCommand",
@@ -86,6 +88,19 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
"variable");
return 0;
}
+
+ bool multiConfig = false;
+ bool cmakeBuildTypeInOptions = false;
+
+ cmGlobalGenerator *gg =
+ this->Makefile->GetCMakeInstance()->CreateGlobalGenerator(
+ cmakeGeneratorName);
+ if(gg)
+ {
+ multiConfig = gg->IsMultiConfig();
+ delete gg;
+ }
+
std::string cmakeConfigureCommand = "\"";
cmakeConfigureCommand += this->CTest->GetCMakeExecutable();
cmakeConfigureCommand += "\"";
@@ -95,9 +110,23 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
for (it= options.begin(); it!=options.end(); ++it)
{
option = *it;
+
cmakeConfigureCommand += " \"";
cmakeConfigureCommand += option;
cmakeConfigureCommand += "\"";
+
+ if ((0 != strstr(option.c_str(), "CMAKE_BUILD_TYPE=")) ||
+ (0 != strstr(option.c_str(), "CMAKE_BUILD_TYPE:STRING=")))
+ {
+ cmakeBuildTypeInOptions = true;
+ }
+ }
+
+ if (!multiConfig && !cmakeBuildTypeInOptions)
+ {
+ cmakeConfigureCommand += " \"-DCMAKE_BUILD_TYPE:STRING=";
+ cmakeConfigureCommand += this->CTest->GetConfigType();
+ cmakeConfigureCommand += "\"";
}
cmakeConfigureCommand += " \"-G";
@@ -113,9 +142,9 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
}
else
{
- this->SetError("Configure command is not specified. If this is a CMake "
- "project, specify CTEST_CMAKE_GENERATOR, or if this is not CMake "
- "project, specify CTEST_CONFIGURE_COMMAND.");
+ this->SetError("Configure command is not specified. If this is a "
+ "\"built with CMake\" project, set CTEST_CMAKE_GENERATOR. If not, "
+ "set CTEST_CONFIGURE_COMMAND.");
return 0;
}
}
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 1c9f080..1957e04 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -59,6 +59,17 @@ bool cmCTestHandlerCommand
}
}
+ // Set the config type of this ctest to the current value of the
+ // CTEST_CONFIGURATION_TYPE script variable if it is defined.
+ // The current script value trumps the -C argument on the command
+ // line.
+ const char* ctestConfigType =
+ this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE");
+ if (ctestConfigType)
+ {
+ this->CTest->SetConfigType(ctestConfigType);
+ }
+
cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
cmCTestGenericHandler* handler = this->InitializeHandler();
if ( !handler )
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 23cc20e..b0adf22 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -33,6 +33,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
{
const char* ctestTimeout =
this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT");
+
double timeout = this->CTest->GetTimeOut();
if ( ctestTimeout )
{
@@ -104,4 +105,3 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeActualHandler()
{
return this->CTest->GetInitializedHandler("test");
}
-
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index b9ce561..3722ab6 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -14,25 +14,135 @@
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
-// cmBuildCommand
+//----------------------------------------------------------------------
bool cmBuildCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
+ // Support the legacy signature of the command:
+ //
+ if(2 == args.size())
+ {
+ return this->TwoArgsSignature(args);
+ }
+
+ return this->MainSignature(args);
+}
+
+//----------------------------------------------------------------------
+bool cmBuildCommand
+::MainSignature(std::vector<std::string> const& args)
+{
+ if(args.size() < 1)
+ {
+ this->SetError("requires at least one argument naming a CMake variable");
+ return false;
+ }
+
+ // The cmake variable in which to store the result.
+ const char* variable = args[0].c_str();
+
+ // Parse remaining arguments.
+ const char* configuration = 0;
+ const char* project_name = 0;
+ const char* target = 0;
+ enum Doing { DoingNone, DoingConfiguration, DoingProjectName, DoingTarget };
+ Doing doing = DoingNone;
+ for(unsigned int i=1; i < args.size(); ++i)
+ {
+ if(args[i] == "CONFIGURATION")
+ {
+ doing = DoingConfiguration;
+ }
+ else if(args[i] == "PROJECT_NAME")
+ {
+ doing = DoingProjectName;
+ }
+ else if(args[i] == "TARGET")
+ {
+ doing = DoingTarget;
+ }
+ else if(doing == DoingConfiguration)
+ {
+ doing = DoingNone;
+ configuration = args[i].c_str();
+ }
+ else if(doing == DoingProjectName)
+ {
+ doing = DoingNone;
+ project_name = args[i].c_str();
+ }
+ else if(doing == DoingTarget)
+ {
+ doing = DoingNone;
+ target = args[i].c_str();
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "unknown argument \"" << args[i] << "\"";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ }
+
+ const char* makeprogram
+ = this->Makefile->GetDefinition("CMAKE_MAKE_PROGRAM");
+
+ // If null/empty CONFIGURATION argument, GenerateBuildCommand uses 'Debug'
+ // in the currently implemented multi-configuration global generators...
+ // so we put this code here to end up with the same default configuration
+ // as the original 2-arg build_command signature:
+ //
+ if(!configuration || !*configuration)
+ {
+ configuration = getenv("CMAKE_CONFIG_TYPE");
+ }
+ if(!configuration || !*configuration)
+ {
+ configuration = "Release";
+ }
+
+ // If null/empty PROJECT_NAME argument, use the Makefile's project name:
+ //
+ if(!project_name || !*project_name)
+ {
+ project_name = this->Makefile->GetProjectName();
+ }
+
+ // If null/empty TARGET argument, GenerateBuildCommand omits any mention
+ // of a target name on the build command line...
+ //
+ std::string makecommand = this->Makefile->GetLocalGenerator()
+ ->GetGlobalGenerator()->GenerateBuildCommand
+ (makeprogram, project_name, 0, target, configuration, true, false);
+
+ this->Makefile->AddDefinition(variable, makecommand.c_str());
+
+ return true;
+}
+
+//----------------------------------------------------------------------
+bool cmBuildCommand
+::TwoArgsSignature(std::vector<std::string> const& args)
+{
if(args.size() < 2 )
{
- this->SetError("called with incorrect number of arguments");
+ this->SetError("called with less than two arguments");
return false;
}
+
const char* define = args[0].c_str();
const char* cacheValue
= this->Makefile->GetDefinition(define);
std::string makeprogram = args[1];
+
std::string configType = "Release";
const char* cfg = getenv("CMAKE_CONFIG_TYPE");
if ( cfg )
{
configType = cfg;
}
+
std::string makecommand = this->Makefile->GetLocalGenerator()
->GetGlobalGenerator()->GenerateBuildCommand
(makeprogram.c_str(), this->Makefile->GetProjectName(), 0,
@@ -49,4 +159,3 @@ bool cmBuildCommand
cmCacheManager::STRING);
return true;
}
-
diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h
index 9d494e7..703ff88 100644
--- a/Source/cmBuildCommand.h
+++ b/Source/cmBuildCommand.h
@@ -38,35 +38,60 @@ public:
cmExecutionStatus &status);
/**
+ * The primary command signature with optional, KEYWORD-based args.
+ */
+ virtual bool MainSignature(std::vector<std::string> const& args);
+
+ /**
+ * Legacy "exactly 2 args required" signature.
+ */
+ virtual bool TwoArgsSignature(std::vector<std::string> const& args);
+
+ /**
* The name of the command as specified in CMakeList.txt.
*/
virtual const char* GetName() {return "build_command";}
-
+
/**
* Succinct documentation.
*/
virtual const char* GetTerseDocumentation()
{
- return "Get the command line that will build this project.";
+ return "Get the command line to build this project.";
}
-
+
/**
* More documentation.
*/
virtual const char* GetFullDocumentation()
{
return
- " build_command(<variable> <makecommand>)\n"
- "Sets the given <variable> to a string containing the command that "
- "will build this project from the root of the build tree using the "
- "build tool given by <makecommand>. <makecommand> should be msdev, "
- "nmake, make or one of the end user build tools. "
- "This is useful for configuring testing systems.";
+ " build_command(<variable>\n"
+ " [CONFIGURATION <config>]\n"
+ " [PROJECT_NAME <projname>]\n"
+ " [TARGET <target>])\n"
+ "Sets the given <variable> to a string containing the command line "
+ "for building one configuration of a target in a project using the "
+ "build tool appropriate for the current CMAKE_GENERATOR.\n"
+ "If CONFIGURATION is omitted, CMake chooses a reasonable default "
+ "value for multi-configuration generators. CONFIGURATION is "
+ "ignored for single-configuration generators.\n"
+ "If PROJECT_NAME is omitted, the resulting command line will build "
+ "the top level PROJECT in the current build tree.\n"
+ "If TARGET is omitted, the resulting command line will build "
+ "everything, effectively using build target 'all' or 'ALL_BUILD'.\n"
+ " build_command(<cachevariable> <makecommand>)\n"
+ "This second signature is deprecated, but still available for "
+ "backwards compatibility. Use the first signature instead.\n"
+ "Sets the given <cachevariable> to a string containing the command "
+ "to build this project from the root of the build tree using "
+ "the build tool given by <makecommand>. <makecommand> should be "
+ "the full path to msdev, devenv, nmake, make or one of the end "
+ "user build tools."
+ ;
}
-
+
cmTypeMacro(cmBuildCommand, cmCommand);
};
-
-
#endif
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index c9d0790..b7b4324 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -258,6 +258,10 @@ public:
/** Supported systems creates a GUID for the given name */
virtual void CreateGUID(const char*) {}
+ /** Return true if the generated build tree may contain multiple builds.
+ i.e. "Can I build Debug and Release in the same tree?" */
+ virtual bool IsMultiConfig() { return false; }
+
protected:
typedef std::vector<cmLocalGenerator*> GeneratorVector;
// for a project collect all its targets by following depend
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 0c7cf7f..b0be087 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -65,6 +65,11 @@ public:
/** Get the top-level registry key for this VS version. */
std::string GetRegistryBase();
+
+ /** Return true if the generated build tree may contain multiple builds.
+ i.e. "Can I build Debug and Release in the same tree?" */
+ virtual bool IsMultiConfig() { return true; }
+
protected:
void FixUtilityDepends();
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index a409e5f..05c6848 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -3302,3 +3302,18 @@ cmGlobalXCodeGenerator::ComputeInfoPListLocation(cmTarget& target)
plist += ".dir/Info.plist";
return plist;
}
+
+//----------------------------------------------------------------------------
+// Return true if the generated build tree may contain multiple builds.
+// i.e. "Can I build Debug and Release in the same tree?"
+bool cmGlobalXCodeGenerator::IsMultiConfig()
+{
+ // Old Xcode 1.5 is single config:
+ if(this->XcodeVersion == 15)
+ {
+ return false;
+ }
+
+ // Newer Xcode versions are multi config:
+ return true;
+}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 02ac1b5..b4de805 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -80,6 +80,11 @@ public:
std::vector<std::string>&
dirs);
void SetCurrentLocalGenerator(cmLocalGenerator*);
+
+ /** Return true if the generated build tree may contain multiple builds.
+ i.e. "Can I build Debug and Release in the same tree?" */
+ virtual bool IsMultiConfig();
+
private:
cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget,
cmSourceGroup* sg);