Przeglądaj źródła

Allow a toolchain file to specify a generator toolset

Delay use of CMAKE_GENERATOR_TOOLSET until the CMakeSystem.cmake
file has been configured and loaded during the first project() or
enable_language() command.  This gives the toolchain file named by
CMAKE_TOOLCHAIN_FILE a chance to set CMAKE_GENERATOR_TOOLSET.  This
point is still early enough to set the generator toolset prior to
the initialization of any languages that might use the toolset.

The cmake::GeneratorToolset member variable remains an indication
of what was specified by the -T option or loaded from the cache.
It does not need to be updated based on the toolchain file setting.
The cmMakefile::TryCompile can still pass cmake::GeneratorToolset
into the inner instance because the try-compiled project will do
platform and language initialization using the CMakeSystem module
configured for the outer project.

Extend the RunCMake.GeneratorToolset test with cases that use a
toolchain file to set CMAKE_GENERATOR_TOOLSET.
Brad King 11 lat temu
rodzic
commit
528e8af19f

+ 8 - 0
Help/release/dev/delay-generator-toolset.rst

@@ -0,0 +1,8 @@
+delay-generator-toolset
+-----------------------
+
+* The :variable:`CMAKE_GENERATOR_TOOLSET` variable may now be
+  initialized in a toolchain file specified by the
+  :variable:`CMAKE_TOOLCHAIN_FILE` variable.  This is useful
+  when cross-compiling with the Xcode or Visual Studio
+  generators.

+ 6 - 0
Help/variable/CMAKE_GENERATOR_TOOLSET.rst

@@ -7,3 +7,9 @@ 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.
+
+The value of this variable should never be modified by project code.
+A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE`
+variable may initialize ``CMAKE_GENERATOR_TOOLSET``.  Once a given
+build tree has been initialized with a particular value for this
+variable, changing the value has undefined behavior.

+ 12 - 3
Source/cmGlobalGenerator.cxx

@@ -76,7 +76,8 @@ cmGlobalGenerator::~cmGlobalGenerator()
     }
 }
 
-bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts)
+bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts,
+                                            cmMakefile* mf)
 {
   cmOStringStream e;
   e <<
@@ -85,8 +86,7 @@ bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts)
     "does not support toolset specification, but toolset\n"
     "  " << ts << "\n"
     "was specified.";
-  this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
-                                    cmListFileBacktrace());
+  mf->IssueMessage(cmake::FATAL_ERROR, e.str());
   return false;
 }
 
@@ -448,6 +448,15 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
     mf->ReadListFile(0,fpath.c_str());
     }
 
+  // Tell the generator about the toolset, if any.
+  std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET");
+  if(!toolset.empty() &&
+     !this->SetGeneratorToolset(toolset, mf))
+    {
+    cmSystemTools::SetFatalErrorOccured();
+    return;
+    }
+
   // **** Load the system specific initialization if not yet loaded
   if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INITIALIZE_LOADED"))
     {

+ 1 - 1
Source/cmGlobalGenerator.h

@@ -63,7 +63,7 @@ public:
 
   /** Set the generator-specific toolset name.  Returns true if toolset
       is supported and false otherwise.  */
-  virtual bool SetGeneratorToolset(std::string const& ts);
+  virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
 
   /**
    * Create LocalGenerators and process the CMakeLists files. This does not

+ 3 - 1
Source/cmGlobalVisualStudio10Generator.cxx

@@ -116,9 +116,11 @@ cmGlobalVisualStudio10Generator::MatchesGeneratorName(
 
 //----------------------------------------------------------------------------
 bool
-cmGlobalVisualStudio10Generator::SetGeneratorToolset(std::string const& ts)
+cmGlobalVisualStudio10Generator::SetGeneratorToolset(std::string const& ts,
+                                                     cmMakefile* mf)
 {
   this->GeneratorToolset = ts;
+  this->AddVSPlatformToolsetDefinition(mf);
   return true;
 }
 

+ 1 - 1
Source/cmGlobalVisualStudio10Generator.h

@@ -31,7 +31,7 @@ public:
 
   virtual bool MatchesGeneratorName(const std::string& name) const;
 
-  virtual bool SetGeneratorToolset(std::string const& ts);
+  virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
 
   virtual void GenerateBuildCommand(
     std::vector<std::string>& makeCommand,

+ 5 - 7
Source/cmGlobalXCodeGenerator.cxx

@@ -202,16 +202,19 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory
 }
 
 //----------------------------------------------------------------------------
-bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts)
+bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
+                                                 cmMakefile* mf)
 {
   if(this->XcodeVersion >= 30)
     {
     this->GeneratorToolset = ts;
+    mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
+                      this->GeneratorToolset.c_str());
     return true;
     }
   else
     {
-    return cmGlobalGenerator::SetGeneratorToolset(ts);
+    return cmGlobalGenerator::SetGeneratorToolset(ts, mf);
     }
 }
 
@@ -239,11 +242,6 @@ void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const&
       }
     }
   mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
-  if(!this->GeneratorToolset.empty())
-    {
-    mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
-                      this->GeneratorToolset.c_str());
-    }
   this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
     const char* osxArch =
       mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");

+ 1 - 1
Source/cmGlobalXCodeGenerator.h

@@ -89,7 +89,7 @@ public:
       i.e. "Can I build Debug and Release in the same tree?" */
   virtual bool IsMultiConfig();
 
-  virtual bool SetGeneratorToolset(std::string const& ts);
+  virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
   void AppendFlag(std::string& flags, std::string const& flag);
 private:
   cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget,

+ 0 - 5
Source/cmake.cxx

@@ -1462,11 +1462,6 @@ int cmake::ActualConfigure()
                                       "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

+ 1 - 1
Tests/RunCMake/GeneratorToolset/BadToolset-stderr.txt

@@ -1,4 +1,4 @@
-CMake Error:
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
   Generator
 
     .*

+ 1 - 0
Tests/RunCMake/GeneratorToolset/BadToolset-toolchain.cmake

@@ -0,0 +1 @@
+set(CMAKE_GENERATOR_TOOLSET "Bad Toolset")

+ 1 - 0
Tests/RunCMake/GeneratorToolset/BadToolsetToolchain-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/GeneratorToolset/BadToolsetToolchain-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    .*
+
+  does not support toolset specification, but toolset
+
+    Bad Toolset
+
+  was specified.$

+ 1 - 0
Tests/RunCMake/GeneratorToolset/BadToolsetToolchain.cmake

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

+ 11 - 0
Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake

@@ -12,6 +12,17 @@ else()
 endif()
 
 set(RunCMake_GENERATOR_TOOLSET "")
+
 set(RunCMake_TEST_OPTIONS -T "Extra Toolset")
 run_cmake(TwoToolsets)
 unset(RunCMake_TEST_OPTIONS)
+
+if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012]|Xcode" AND NOT XCODE_BELOW_3)
+  set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestToolset-toolchain.cmake)
+  run_cmake(TestToolsetToolchain)
+  unset(RunCMake_TEST_OPTIONS)
+else()
+  set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/BadToolset-toolchain.cmake)
+  run_cmake(BadToolsetToolchain)
+  unset(RunCMake_TEST_OPTIONS)
+endif()

+ 1 - 0
Tests/RunCMake/GeneratorToolset/TestToolset-toolchain.cmake

@@ -0,0 +1 @@
+set(CMAKE_GENERATOR_TOOLSET "Test Toolset")

+ 1 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetToolchain-result.txt

@@ -0,0 +1 @@
+1

+ 9 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetToolchain-stderr.txt

@@ -0,0 +1,9 @@
+CMake Error at TestToolsetToolchain.cmake:[0-9]+ \(message\):
+  CMAKE_GENERATOR_TOOLSET is "Test Toolset" as expected.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at TestToolsetToolchain.cmake:[0-9]+ \(message\):
+  CMAKE_(VS|XCODE)_PLATFORM_TOOLSET is "Test Toolset" as expected.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 25 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetToolchain.cmake

@@ -0,0 +1,25 @@
+if("x${CMAKE_GENERATOR_TOOLSET}" STREQUAL "xTest Toolset")
+  message(SEND_ERROR "CMAKE_GENERATOR_TOOLSET is \"Test Toolset\" as expected.")
+else()
+  message(FATAL_ERROR
+    "CMAKE_GENERATOR_TOOLSET is \"${CMAKE_GENERATOR_TOOLSET}\" "
+    "but should be \"Test Toolset\"!")
+endif()
+if(CMAKE_GENERATOR MATCHES "Visual Studio")
+  if("x${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "xTest Toolset")
+    message(SEND_ERROR "CMAKE_VS_PLATFORM_TOOLSET is \"Test Toolset\" as expected.")
+  else()
+    message(FATAL_ERROR
+      "CMAKE_VS_PLATFORM_TOOLSET is \"${CMAKE_VS_PLATFORM_TOOLSET}\" "
+      "but should be \"Test Toolset\"!")
+  endif()
+endif()
+if(CMAKE_GENERATOR MATCHES "Xcode")
+  if("x${CMAKE_XCODE_PLATFORM_TOOLSET}" STREQUAL "xTest Toolset")
+    message(SEND_ERROR "CMAKE_XCODE_PLATFORM_TOOLSET is \"Test Toolset\" as expected.")
+  else()
+    message(FATAL_ERROR
+      "CMAKE_XCODE_PLATFORM_TOOLSET is \"${CMAKE_XCODE_PLATFORM_TOOLSET}\" "
+      "but should be \"Test Toolset\"!")
+  endif()
+endif()