Browse Source

cmake: Allow default generator to be set by environment variables

When there is no Generator available in the Cache, this will read
CMAKE_GENERATOR from environment before using the CMake platform default.
If CMAKE_GENERATOR is empty, use the platform default.

If a environment default generator is specified, subsequent variables
CMAKE_GENERATOR_(INSTANCE,PLATFORM,TOOLSET) are also evaluated
in the same way.
Eicke Herbertz 6 năm trước cách đây
mục cha
commit
083cf7e8a2
2 tập tin đã thay đổi với 71 bổ sung6 xóa
  1. 61 6
      Source/cmake.cxx
  2. 10 0
      Source/cmake.h

+ 61 - 6
Source/cmake.cxx

@@ -159,6 +159,9 @@ cmake::cmake(Role role, cmState::Mode mode)
 #endif
 
   this->GlobalGenerator = nullptr;
+  this->GeneratorInstanceSet = false;
+  this->GeneratorPlatformSet = false;
+  this->GeneratorToolsetSet = false;
   this->CurrentWorkingMode = NORMAL_MODE;
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
@@ -174,6 +177,10 @@ cmake::cmake(Role role, cmState::Mode mode)
     this->AddProjectCommands();
   }
 
+  if (mode == cmState::Project) {
+    this->LoadEnvironmentPresets();
+  }
+
   // Make sure we can capture the build tool output.
   cmSystemTools::EnableVSConsoleOutput();
 
@@ -612,6 +619,35 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
   return packageFound;
 }
 
+void cmake::LoadEnvironmentPresets()
+{
+  std::string envGenVar;
+  bool hasEnvironmentGenerator = false;
+  if (cmSystemTools::GetEnv("CMAKE_GENERATOR", envGenVar)) {
+    hasEnvironmentGenerator = true;
+    this->EnvironmentGenerator = envGenVar;
+  }
+
+  auto readGeneratorVar = [&](std::string name, std::string& key) {
+    std::string varValue;
+    if (cmSystemTools::GetEnv(name, varValue)) {
+      if (hasEnvironmentGenerator) {
+        key = varValue;
+      } else if (!this->GetIsInTryCompile()) {
+        std::string message = "Warning: Environment variable ";
+        message += name;
+        message += " will be ignored, because CMAKE_GENERATOR ";
+        message += "is not set.";
+        cmSystemTools::Message(message, "Warning");
+      }
+    }
+  };
+
+  readGeneratorVar("CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance);
+  readGeneratorVar("CMAKE_GENERATOR_PLATFORM", this->GeneratorPlatform);
+  readGeneratorVar("CMAKE_GENERATOR_TOOLSET", this->GeneratorToolset);
+}
+
 // Parse the args
 void cmake::SetArgs(const std::vector<std::string>& args)
 {
@@ -759,7 +795,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
         cmSystemTools::Error("Multiple -A options not allowed");
         return;
       }
-      this->GeneratorPlatform = value;
+      this->SetGeneratorPlatform(value);
       havePlatform = true;
     } else if (arg.find("-T", 0) == 0) {
       std::string value = arg.substr(2);
@@ -775,7 +811,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
         cmSystemTools::Error("Multiple -T options not allowed");
         return;
       }
-      this->GeneratorToolset = value;
+      this->SetGeneratorToolset(value);
       haveToolset = true;
     } else if (arg.find("-G", 0) == 0) {
       std::string value = arg.substr(2);
@@ -806,6 +842,16 @@ void cmake::SetArgs(const std::vector<std::string>& args)
     else {
       this->SetDirectoriesFromFile(arg.c_str());
     }
+    // Empty instance, platform and toolset if only a generator is specified
+    if (this->GlobalGenerator) {
+      this->GeneratorInstance = "";
+      if (!this->GeneratorPlatformSet) {
+        this->GeneratorPlatform = "";
+      }
+      if (!this->GeneratorToolsetSet) {
+        this->GeneratorToolset = "";
+      }
+    }
   }
 
   const bool haveSourceDir = !this->GetHomeDirectory().empty();
@@ -1419,8 +1465,7 @@ int cmake::ActualConfigure()
 
   if (const std::string* instance =
         this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
-    if (!this->GeneratorInstance.empty() &&
-        this->GeneratorInstance != *instance) {
+    if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) {
       std::string message = "Error: generator instance: ";
       message += this->GeneratorInstance;
       message += "\nDoes not match the instance used previously: ";
@@ -1438,7 +1483,7 @@ int cmake::ActualConfigure()
 
   if (const std::string* platformName =
         this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) {
-    if (!this->GeneratorPlatform.empty() &&
+    if (this->GeneratorPlatformSet &&
         this->GeneratorPlatform != *platformName) {
       std::string message = "Error: generator platform: ";
       message += this->GeneratorPlatform;
@@ -1457,7 +1502,7 @@ int cmake::ActualConfigure()
 
   if (const std::string* tsName =
         this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) {
-    if (!this->GeneratorToolset.empty() && this->GeneratorToolset != *tsName) {
+    if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) {
       std::string message = "Error: generator toolset: ";
       message += this->GeneratorToolset;
       message += "\nDoes not match the toolset used previously: ";
@@ -1535,6 +1580,16 @@ int cmake::ActualConfigure()
 
 std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator()
 {
+  if (!this->EnvironmentGenerator.empty()) {
+    cmGlobalGenerator* gen =
+      this->CreateGlobalGenerator(this->EnvironmentGenerator);
+    if (!gen) {
+      cmSystemTools::Error("CMAKE_GENERATOR was set but the specified "
+                           "generator doesn't exist. Using CMake default.");
+    } else {
+      return std::unique_ptr<cmGlobalGenerator>(gen);
+    }
+  }
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
   std::string found;
   // Try to find the newest VS installed on the computer and

+ 10 - 0
Source/cmake.h

@@ -201,18 +201,21 @@ public:
   void SetGeneratorInstance(std::string const& instance)
   {
     this->GeneratorInstance = instance;
+    this->GeneratorInstanceSet = true;
   }
 
   //! Set the name of the selected generator-specific platform.
   void SetGeneratorPlatform(std::string const& ts)
   {
     this->GeneratorPlatform = ts;
+    this->GeneratorPlatformSet = true;
   }
 
   //! Set the name of the selected generator-specific toolset.
   void SetGeneratorToolset(std::string const& ts)
   {
     this->GeneratorToolset = ts;
+    this->GeneratorToolsetSet = true;
   }
 
   const std::vector<std::string>& GetSourceExtensions() const
@@ -263,6 +266,9 @@ public:
    */
   int GetSystemInformation(std::vector<std::string>&);
 
+  //! Parse environment variables
+  void LoadEnvironmentPresets();
+
   //! Parse command line arguments
   void SetArgs(const std::vector<std::string>& args);
 
@@ -461,6 +467,9 @@ protected:
   std::string GeneratorInstance;
   std::string GeneratorPlatform;
   std::string GeneratorToolset;
+  bool GeneratorInstanceSet;
+  bool GeneratorPlatformSet;
+  bool GeneratorToolsetSet;
 
   //! read in a cmake list file to initialize the cache
   void ReadListFile(const std::vector<std::string>& args,
@@ -503,6 +512,7 @@ private:
   std::string CheckStampFile;
   std::string CheckStampList;
   std::string VSSolutionFile;
+  std::string EnvironmentGenerator;
   std::vector<std::string> SourceFileExtensions;
   std::unordered_set<std::string> SourceFileExtensionsSet;
   std::vector<std::string> HeaderFileExtensions;