diff options
author | David Cole <david.cole@kitware.com> | 2009-12-04 17:09:01 (GMT) |
---|---|---|
committer | David Cole <david.cole@kitware.com> | 2009-12-04 17:09:01 (GMT) |
commit | 0b38bb4c535ae972d7f973e3e69945a6d0c14d75 (patch) | |
tree | ac80395b194b2a8ed2bcf6b1f997b62c21d151be /Source | |
parent | af14f1f2c3750ba3cf9b9cc1a809a88b1878a5c3 (diff) | |
download | CMake-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.cxx | 16 | ||||
-rw-r--r-- | Source/CTest/cmCTestBuildHandler.cxx | 36 | ||||
-rw-r--r-- | Source/CTest/cmCTestBuildHandler.h | 3 | ||||
-rw-r--r-- | Source/CTest/cmCTestConfigureCommand.cxx | 35 | ||||
-rw-r--r-- | Source/CTest/cmCTestHandlerCommand.cxx | 11 | ||||
-rw-r--r-- | Source/CTest/cmCTestTestCommand.cxx | 2 | ||||
-rw-r--r-- | Source/cmBuildCommand.cxx | 115 | ||||
-rw-r--r-- | Source/cmBuildCommand.h | 49 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.h | 4 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudioGenerator.h | 5 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 15 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.h | 5 |
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); |