diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 08b3ef168c..2b9104cc85 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -254,6 +254,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "for the respective IDE. This IDE project file generator is stored in " "CMAKE_EXTRA_GENERATOR (e.g. \"Eclipse CDT4\").",false, "Variables that Provide Information"); + cm->DefineProperty + ("CMAKE_GENERATOR_TOOLSET", cmProperty::VARIABLE, + "Native build system toolset name specified by user.", + "Some CMake generators support a toolset name to be given to the " + "native build system to choose a compiler. " + "If the user specifies a toolset name (e.g. via the cmake -T option) " + "the value will be available in this variable.",false, + "Variables that Provide Information"); cm->DefineProperty ("CMAKE_HOME_DIRECTORY", cmProperty::VARIABLE, "Path to top of source tree.", diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index d2baf535c5..d8afa533f6 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -79,6 +79,20 @@ cmGlobalGenerator::~cmGlobalGenerator() this->ClearGeneratorTargets(); } +bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts) +{ + cmOStringStream e; + e << + "Generator\n" + " " << this->GetName() << "\n" + "does not support toolset specification, but toolset\n" + " " << ts << "\n" + "was specified."; + this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), + cmListFileBacktrace()); + return false; +} + void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang, cmMakefile *mf, bool optional) diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index bb805d9b11..f8275e8ff9 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -49,6 +49,10 @@ public: ///! Get the name for this generator virtual const char *GetName() const { return "Generic"; }; + /** Set the generator-specific toolset name. Returns true if toolset + is supported and false otherwise. */ + virtual bool SetGeneratorToolset(std::string const& ts); + /** * Create LocalGenerators and process the CMakeLists files. This does not * actually produce any makefiles, DSPs, etc. diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index b432986a82..b45a61cd6b 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2973,6 +2973,7 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir, cm.SetStartDirectory(srcdir); cm.SetStartOutputDirectory(bindir); cm.SetCMakeCommand(cmakeCommand.c_str()); + cm.SetGeneratorToolset(this->GetCMakeInstance()->GetGeneratorToolset()); cm.LoadCache(); if(!gg->IsMultiConfig()) { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 2eecfbac2e..18622f3bb0 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -659,6 +659,7 @@ void cmake::SetArgs(const std::vector& args, bool directoriesSetBefore) { bool directoriesSet = directoriesSetBefore; + bool haveToolset = false; for(unsigned int i=1; i < args.size(); ++i) { std::string arg = args[i]; @@ -787,6 +788,27 @@ void cmake::SetArgs(const std::vector& args, "uninitialized variables.\n"; this->SetCheckSystemVars(true); } + else if(arg.find("-T",0) == 0) + { + std::string value = arg.substr(2); + if(value.size() == 0) + { + ++i; + if(i >= args.size()) + { + cmSystemTools::Error("No toolset specified for -T"); + return; + } + value = args[i]; + } + if(haveToolset) + { + cmSystemTools::Error("Multiple -T options not allowed"); + return; + } + this->GeneratorToolset = value; + haveToolset = true; + } else if(arg.find("-G",0) == 0) { std::string value = arg.substr(2); @@ -2282,6 +2304,39 @@ int cmake::ActualConfigure() cmCacheManager::INTERNAL); } + if(const char* tsName = + this->CacheManager->GetCacheValue("CMAKE_GENERATOR_TOOLSET")) + { + if(this->GeneratorToolset.empty()) + { + this->GeneratorToolset = tsName; + } + else if(this->GeneratorToolset != tsName) + { + std::string message = "Error: generator toolset: "; + message += this->GeneratorToolset; + message += "\nDoes not match the toolset used previously: "; + message += tsName; + message += + "\nEither remove the CMakeCache.txt file or choose a different" + " binary directory."; + cmSystemTools::Error(message.c_str()); + return -2; + } + } + else + { + this->CacheManager->AddCacheEntry("CMAKE_GENERATOR_TOOLSET", + this->GeneratorToolset.c_str(), + "Name of generator toolset.", + cmCacheManager::INTERNAL); + } + if(!this->GeneratorToolset.empty() && + !this->GlobalGenerator->SetGeneratorToolset(this->GeneratorToolset)) + { + return -2; + } + // reset any system configuration information, except for when we are // InTryCompile. With TryCompile the system info is taken from the parent's // info to save time diff --git a/Source/cmake.h b/Source/cmake.h index f6fe0d6967..7253b39a53 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -187,6 +187,14 @@ class cmake ///! Get the names of the current registered generators void GetRegisteredGenerators(std::vector& names); + ///! Set the name of the selected generator-specific toolset. + void SetGeneratorToolset(std::string const& ts) + { this->GeneratorToolset = ts; } + + ///! Get the name of the selected generator-specific toolset. + std::string const& GetGeneratorToolset() const + { return this->GeneratorToolset; } + ///! get the cmCachemManager used by this invocation of cmake cmCacheManager *GetCacheManager() { return this->CacheManager; } @@ -418,6 +426,7 @@ protected: std::string StartOutputDirectory; bool SuppressDevWarnings; bool DoSuppressDevWarnings; + std::string GeneratorToolset; ///! read in a cmake list file to initialize the cache void ReadListFile(const std::vector& args, const char *path); @@ -528,6 +537,10 @@ private: "A makefile generator is responsible for generating a particular build " \ "system. Possible generator names are specified in the Generators " \ "section."},\ + {"-T ", "Specify toolset name if supported by generator.", \ + "Some CMake generators support a toolset name to be given to the " \ + "native build system to choose a compiler. " \ + "See native build system documentation for allowed toolset names."}, \ {"-Wno-dev", "Suppress developer warnings.",\ "Suppress warnings that are meant for the author"\ " of the CMakeLists.txt files."},\ diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 9b133b2994..a90fd7bf84 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -47,6 +47,7 @@ endmacro() add_RunCMake_test(CMP0019) add_RunCMake_test(GeneratorExpression) +add_RunCMake_test(GeneratorToolset) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(ObjectLibrary) diff --git a/Tests/RunCMake/GeneratorToolset/BadToolset-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolset-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolset-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolset-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolset-stderr.txt new file mode 100644 index 0000000000..bf1f190186 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolset-stderr.txt @@ -0,0 +1,10 @@ +CMake Error: + Generator + + .* + + does not support toolset specification, but toolset + + Bad Toolset + + was specified.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolset.cmake b/Tests/RunCMake/GeneratorToolset/BadToolset.cmake new file mode 100644 index 0000000000..2fc38e5c59 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolset.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/CMakeLists.txt b/Tests/RunCMake/GeneratorToolset/CMakeLists.txt new file mode 100644 index 0000000000..e8db6b05be --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/GeneratorToolset/NoToolset-result.txt b/Tests/RunCMake/GeneratorToolset/NoToolset-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/NoToolset-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/NoToolset-stderr.txt b/Tests/RunCMake/GeneratorToolset/NoToolset-stderr.txt new file mode 100644 index 0000000000..bc6f741938 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/NoToolset-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoToolset.cmake:2 \(message\): + CMAKE_GENERATOR_TOOLSET is empty as expected. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GeneratorToolset/NoToolset.cmake b/Tests/RunCMake/GeneratorToolset/NoToolset.cmake new file mode 100644 index 0000000000..f1f1ecd265 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/NoToolset.cmake @@ -0,0 +1,7 @@ +if("x${CMAKE_GENERATOR_TOOLSET}" STREQUAL "x") + message(FATAL_ERROR "CMAKE_GENERATOR_TOOLSET is empty as expected.") +else() + message(FATAL_ERROR + "CMAKE_GENERATOR_TOOLSET is \"${CMAKE_GENERATOR_TOOLSET}\" " + "but should be empty!") +endif() diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake new file mode 100644 index 0000000000..cd63f48fce --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -0,0 +1,11 @@ +include(RunCMake) + +run_cmake(NoToolset) + +set(RunCMake_TEST_OPTIONS -T "Bad Toolset") +run_cmake(BadToolset) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS -T "Toolset 1" "-TToolset 2") +run_cmake(TwoToolsets) +unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/GeneratorToolset/TwoToolsets-result.txt b/Tests/RunCMake/GeneratorToolset/TwoToolsets-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TwoToolsets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/TwoToolsets-stderr.txt b/Tests/RunCMake/GeneratorToolset/TwoToolsets-stderr.txt new file mode 100644 index 0000000000..9fa817ff52 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TwoToolsets-stderr.txt @@ -0,0 +1 @@ +CMake Error: Multiple -T options not allowed diff --git a/Tests/RunCMake/GeneratorToolset/TwoToolsets.cmake b/Tests/RunCMake/GeneratorToolset/TwoToolsets.cmake new file mode 100644 index 0000000000..2fc38e5c59 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TwoToolsets.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index c3c161abee..a43fee0110 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -29,9 +29,13 @@ function(run_cmake test) set(RunCMake_TEST_BINARY_DIR "${top_bin}/${test}-build") file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + if(NOT DEFINED RunCMake_TEST_OPTIONS) + set(RunCMake_TEST_OPTIONS "") + endif() execute_process( COMMAND ${CMAKE_COMMAND} "${RunCMake_TEST_SOURCE_DIR}" -G "${RunCMake_GENERATOR}" -DRunCMake_TEST=${test} + ${RunCMake_TEST_OPTIONS} WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}" OUTPUT_VARIABLE actual_stdout ERROR_VARIABLE actual_stderr