CMake: Add -T option to choose a generator toolset

Reject the option by default.  It will be implemented on a per-generator
basis.  Pass the setting into try_compile project generation.  Add cache
entry CMAKE_GENERATOR_TOOLSET and associated variable documentation to
hold the value persistently.

Add a RunCMake.GeneratorToolset test to cover basic "-T" option cases.
Verify that CMAKE_GENERATOR_TOOLSET is empty without -T, that -T is
rejected when the generator doesn't support it, and that two -T options
are always rejected.
This commit is contained in:
Brad King 2012-12-10 10:42:33 -05:00
parent 118c32f8f2
commit 4fd5342956
19 changed files with 141 additions and 0 deletions

View File

@ -254,6 +254,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"for the respective IDE. This IDE project file generator is stored in " "for the respective IDE. This IDE project file generator is stored in "
"CMAKE_EXTRA_GENERATOR (e.g. \"Eclipse CDT4\").",false, "CMAKE_EXTRA_GENERATOR (e.g. \"Eclipse CDT4\").",false,
"Variables that Provide Information"); "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 cm->DefineProperty
("CMAKE_HOME_DIRECTORY", cmProperty::VARIABLE, ("CMAKE_HOME_DIRECTORY", cmProperty::VARIABLE,
"Path to top of source tree.", "Path to top of source tree.",

View File

@ -79,6 +79,20 @@ cmGlobalGenerator::~cmGlobalGenerator()
this->ClearGeneratorTargets(); 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, void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
cmMakefile *mf, cmMakefile *mf,
bool optional) bool optional)

View File

@ -49,6 +49,10 @@ public:
///! Get the name for this generator ///! Get the name for this generator
virtual const char *GetName() const { return "Generic"; }; 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 * Create LocalGenerators and process the CMakeLists files. This does not
* actually produce any makefiles, DSPs, etc. * actually produce any makefiles, DSPs, etc.

View File

@ -2973,6 +2973,7 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir,
cm.SetStartDirectory(srcdir); cm.SetStartDirectory(srcdir);
cm.SetStartOutputDirectory(bindir); cm.SetStartOutputDirectory(bindir);
cm.SetCMakeCommand(cmakeCommand.c_str()); cm.SetCMakeCommand(cmakeCommand.c_str());
cm.SetGeneratorToolset(this->GetCMakeInstance()->GetGeneratorToolset());
cm.LoadCache(); cm.LoadCache();
if(!gg->IsMultiConfig()) if(!gg->IsMultiConfig())
{ {

View File

@ -659,6 +659,7 @@ void cmake::SetArgs(const std::vector<std::string>& args,
bool directoriesSetBefore) bool directoriesSetBefore)
{ {
bool directoriesSet = directoriesSetBefore; bool directoriesSet = directoriesSetBefore;
bool haveToolset = false;
for(unsigned int i=1; i < args.size(); ++i) for(unsigned int i=1; i < args.size(); ++i)
{ {
std::string arg = args[i]; std::string arg = args[i];
@ -787,6 +788,27 @@ void cmake::SetArgs(const std::vector<std::string>& args,
"uninitialized variables.\n"; "uninitialized variables.\n";
this->SetCheckSystemVars(true); 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) else if(arg.find("-G",0) == 0)
{ {
std::string value = arg.substr(2); std::string value = arg.substr(2);
@ -2282,6 +2304,39 @@ int cmake::ActualConfigure()
cmCacheManager::INTERNAL); 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 // reset any system configuration information, except for when we are
// InTryCompile. With TryCompile the system info is taken from the parent's // InTryCompile. With TryCompile the system info is taken from the parent's
// info to save time // info to save time

View File

@ -187,6 +187,14 @@ class cmake
///! Get the names of the current registered generators ///! Get the names of the current registered generators
void GetRegisteredGenerators(std::vector<std::string>& names); void GetRegisteredGenerators(std::vector<std::string>& 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 ///! get the cmCachemManager used by this invocation of cmake
cmCacheManager *GetCacheManager() { return this->CacheManager; } cmCacheManager *GetCacheManager() { return this->CacheManager; }
@ -418,6 +426,7 @@ protected:
std::string StartOutputDirectory; std::string StartOutputDirectory;
bool SuppressDevWarnings; bool SuppressDevWarnings;
bool DoSuppressDevWarnings; bool DoSuppressDevWarnings;
std::string GeneratorToolset;
///! read in a cmake list file to initialize the cache ///! read in a cmake list file to initialize the cache
void ReadListFile(const std::vector<std::string>& args, const char *path); void ReadListFile(const std::vector<std::string>& args, const char *path);
@ -528,6 +537,10 @@ private:
"A makefile generator is responsible for generating a particular build " \ "A makefile generator is responsible for generating a particular build " \
"system. Possible generator names are specified in the Generators " \ "system. Possible generator names are specified in the Generators " \
"section."},\ "section."},\
{"-T <toolset-name>", "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.",\ {"-Wno-dev", "Suppress developer warnings.",\
"Suppress warnings that are meant for the author"\ "Suppress warnings that are meant for the author"\
" of the CMakeLists.txt files."},\ " of the CMakeLists.txt files."},\

View File

@ -47,6 +47,7 @@ endmacro()
add_RunCMake_test(CMP0019) add_RunCMake_test(CMP0019)
add_RunCMake_test(GeneratorExpression) add_RunCMake_test(GeneratorExpression)
add_RunCMake_test(GeneratorToolset)
add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(TargetPropertyGeneratorExpressions)
add_RunCMake_test(Languages) add_RunCMake_test(Languages)
add_RunCMake_test(ObjectLibrary) add_RunCMake_test(ObjectLibrary)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,10 @@
CMake Error:
Generator
.*
does not support toolset specification, but toolset
Bad Toolset
was specified.$

View File

@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1 @@
1

View File

@ -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\)

View File

@ -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()

View File

@ -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)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
CMake Error: Multiple -T options not allowed

View File

@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@ -29,9 +29,13 @@ function(run_cmake test)
set(RunCMake_TEST_BINARY_DIR "${top_bin}/${test}-build") set(RunCMake_TEST_BINARY_DIR "${top_bin}/${test}-build")
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
if(NOT DEFINED RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS "")
endif()
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} "${RunCMake_TEST_SOURCE_DIR}" COMMAND ${CMAKE_COMMAND} "${RunCMake_TEST_SOURCE_DIR}"
-G "${RunCMake_GENERATOR}" -DRunCMake_TEST=${test} -G "${RunCMake_GENERATOR}" -DRunCMake_TEST=${test}
${RunCMake_TEST_OPTIONS}
WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}" WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
OUTPUT_VARIABLE actual_stdout OUTPUT_VARIABLE actual_stdout
ERROR_VARIABLE actual_stderr ERROR_VARIABLE actual_stderr