Browse Source

Merge topic 'autogen-improve-multi-config'

a8ee7406 Autogen: Improved multi-config include scheme

Acked-by: Kitware Robot <[email protected]>
Merge-request: !1735
Brad King 7 years ago
parent
commit
213ecf05d6

+ 0 - 7
Modules/AutoRccInfo.cmake.in

@@ -1,7 +0,0 @@
-# Meta
-set(ARCC_MULTI_CONFIG @_multi_config@)
-# Directories and files
-set(ARCC_BUILD_DIR @_build_dir@)
-# Qt environment
-set(ARCC_RCC_EXECUTABLE @_qt_rcc_executable@)
-set(ARCC_RCC_LIST_OPTIONS @_qt_rcc_list_options@)

+ 0 - 32
Modules/AutogenInfo.cmake.in

@@ -1,32 +0,0 @@
-# Meta
-set(AM_MULTI_CONFIG @_multi_config@)
-set(AM_PARALLEL @_parallel@)
-# Directories and files
-set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
-set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
-set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
-set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
-set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@")
-set(AM_BUILD_DIR @_build_dir@)
-set(AM_SOURCES @_sources@)
-set(AM_HEADERS @_headers@)
-set(AM_SETTINGS_FILE @_settings_file@)
-# Qt environment
-set(AM_QT_VERSION_MAJOR @_qt_version_major@)
-set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@)
-set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@)
-# MOC settings
-set(AM_MOC_SKIP @_moc_skip@)
-set(AM_MOC_DEFINITIONS @_moc_compile_defs@)
-set(AM_MOC_INCLUDES @_moc_include_dirs@)
-set(AM_MOC_OPTIONS @_moc_options@)
-set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@)
-set(AM_MOC_MACRO_NAMES @_moc_macro_names@)
-set(AM_MOC_DEPEND_FILTERS @_moc_depend_filters@)
-set(AM_MOC_PREDEFS_CMD @_moc_predefs_cmd@)
-# UIC settings
-set(AM_UIC_SKIP @_uic_skip@)
-set(AM_UIC_TARGET_OPTIONS @_uic_target_options@)
-set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@)
-set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@)
-set(AM_UIC_SEARCH_PATHS @_uic_search_paths@)

+ 0 - 28
Source/cmQtAutoGen.cxx

@@ -17,10 +17,6 @@ std::string const genNameMoc = "AutoMoc";
 std::string const genNameUic = "AutoUic";
 std::string const genNameRcc = "AutoRcc";
 
-std::string const mcNameSingle = "SINGLE";
-std::string const mcNameWrapper = "WRAPPER";
-std::string const mcNameMulti = "MULTI";
-
 // - Static functions
 
 /// @brief Merges newOpts into baseOpts
@@ -102,30 +98,6 @@ std::string cmQtAutoGen::GeneratorNameUpper(GeneratorT genType)
   return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType));
 }
 
-std::string const& cmQtAutoGen::MultiConfigName(MultiConfigT config)
-{
-  switch (config) {
-    case MultiConfigT::SINGLE:
-      return mcNameSingle;
-    case MultiConfigT::WRAPPER:
-      return mcNameWrapper;
-    case MultiConfigT::MULTI:
-      return mcNameMulti;
-  }
-  return mcNameWrapper;
-}
-
-cmQtAutoGen::MultiConfigT cmQtAutoGen::MultiConfigType(std::string const& name)
-{
-  if (name == mcNameSingle) {
-    return MultiConfigT::SINGLE;
-  }
-  if (name == mcNameMulti) {
-    return MultiConfigT::MULTI;
-  }
-  return MultiConfigT::WRAPPER;
-}
-
 std::string cmQtAutoGen::Quoted(std::string const& text)
 {
   static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",

+ 0 - 13
Source/cmQtAutoGen.h

@@ -28,25 +28,12 @@ public:
     RCC
   };
 
-  /// @brief Multiconfiguration type
-  enum class MultiConfigT
-  {
-    SINGLE,  // Single configuration
-    WRAPPER, // Multi configuration using wrapper files
-    MULTI    // Multi configuration using per config sources
-  };
-
 public:
   /// @brief Returns the generator name
   static std::string const& GeneratorName(GeneratorT genType);
   /// @brief Returns the generator name in upper case
   static std::string GeneratorNameUpper(GeneratorT genType);
 
-  /// @brief Returns the multi configuration name string
-  static std::string const& MultiConfigName(MultiConfigT config);
-  /// @brief Returns the multi configuration type
-  static MultiConfigT MultiConfigType(std::string const& name);
-
   /// @brief Returns a the string escaped and enclosed in quotes
   static std::string Quoted(std::string const& text);
 

+ 249 - 296
Source/cmQtAutoGenInitializer.cxx

@@ -68,43 +68,6 @@ static std::size_t GetParallelCPUCount()
   return count;
 }
 
-static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
-                                 std::string const& value)
-{
-  makefile->AddDefinition(key,
-                          cmOutputConverter::EscapeForCMake(value).c_str());
-}
-
-static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
-                                 const std::vector<std::string>& values)
-{
-  makefile->AddDefinition(
-    key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
-}
-
-static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
-                                 const std::set<std::string>& values)
-{
-  makefile->AddDefinition(
-    key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
-}
-
-static void AddDefinitionEscaped(
-  cmMakefile* makefile, const char* key,
-  const std::vector<std::vector<std::string>>& lists)
-{
-  std::vector<std::string> seplist;
-  for (const std::vector<std::string>& list : lists) {
-    std::string blist = "{";
-    blist += cmJoin(list, ";");
-    blist += "}";
-    seplist.push_back(std::move(blist));
-  }
-  makefile->AddDefinition(key, cmOutputConverter::EscapeForCMake(
-                                 cmJoin(seplist, cmQtAutoGen::ListSep))
-                                 .c_str());
-}
-
 static bool AddToSourceGroup(cmMakefile* makefile, std::string const& fileName,
                              cmQtAutoGen::GeneratorT genType)
 {
@@ -234,8 +197,8 @@ cmQtAutoGenInitializer::cmQtAutoGenInitializer(
   , MocEnabled(mocEnabled)
   , UicEnabled(uicEnabled)
   , RccEnabled(rccEnabled)
+  , MultiConfig(false)
   , QtVersionMajor(qtVersionMajor)
-  , MultiConfig(MultiConfigT::WRAPPER)
 {
   this->QtVersionMinor =
     cmQtAutoGenInitializer::GetQtMinorVersion(target, this->QtVersionMajor);
@@ -248,30 +211,12 @@ void cmQtAutoGenInitializer::InitCustomTargets()
   cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
 
   // Configurations
+  this->MultiConfig = globalGen->IsMultiConfig();
   this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);
   if (this->ConfigsList.empty()) {
     this->ConfigsList.push_back(this->ConfigDefault);
   }
 
-  // Multi configuration
-  {
-    if (!globalGen->IsMultiConfig()) {
-      this->MultiConfig = MultiConfigT::SINGLE;
-    }
-
-    // FIXME: Xcode does not support per-config sources, yet.
-    //        (EXCLUDED_SOURCE_FILE_NAMES)
-    // if (globalGen->GetName().find("Xcode") != std::string::npos) {
-    //  return MultiConfigT::MULTI;
-    //}
-
-    // FIXME: Visual Studio does not support per-config sources, yet.
-    //        (EXCLUDED_SOURCE_FILE_NAMES)
-    // if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
-    //  return MultiConfigT::MULTI;
-    //}
-  }
-
   // Autogen target name
   this->AutogenTargetName = this->Target->GetName();
   this->AutogenTargetName += "_autogen";
@@ -285,7 +230,7 @@ void cmQtAutoGenInitializer::InitCustomTargets()
     // Autogen info dir
     this->DirInfo = cbd;
     this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
-    this->DirInfo += "/";
+    this->DirInfo += '/';
     this->DirInfo += this->AutogenTargetName;
     this->DirInfo += ".dir";
     cmSystemTools::ConvertToUnixSlashes(this->DirInfo);
@@ -294,7 +239,7 @@ void cmQtAutoGenInitializer::InitCustomTargets()
     this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR");
     if (this->DirBuild.empty()) {
       this->DirBuild = cbd;
-      this->DirBuild += "/";
+      this->DirBuild += '/';
       this->DirBuild += this->AutogenTargetName;
     }
     cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
@@ -340,32 +285,32 @@ void cmQtAutoGenInitializer::InitCustomTargets()
   {
     std::string base = this->DirInfo;
     base += "/AutogenOldSettings";
-    if (this->MultiConfig == MultiConfigT::SINGLE) {
-      AddCleanFile(makefile, base.append(".cmake"));
-    } else {
+    if (this->MultiConfig) {
       for (std::string const& cfg : this->ConfigsList) {
         std::string filename = base;
-        filename += "_";
+        filename += '_';
         filename += cfg;
         filename += ".cmake";
         AddCleanFile(makefile, filename);
       }
+    } else {
+      AddCleanFile(makefile, base.append(".cmake"));
     }
   }
 
   // Add moc compilation to generated files list
   if (this->MocEnabled) {
-    std::string const mocsComp = this->DirBuild + "/mocs_compilation.cpp";
-    auto files = this->AddGeneratedSource(mocsComp, GeneratorT::MOC);
-    for (std::string& file : files) {
-      autogenProvides.push_back(std::move(file));
-    }
+    std::string mocsComp = this->DirBuild + "/mocs_compilation.cpp";
+    this->AddGeneratedSource(mocsComp, GeneratorT::MOC);
+    autogenProvides.push_back(std::move(mocsComp));
   }
 
   // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
-  if (this->MocEnabled || this->UicEnabled) {
-    std::string includeDir = this->DirBuild + "/include";
-    if (this->MultiConfig != MultiConfigT::SINGLE) {
+  if (this->MocEnabled || this->UicEnabled ||
+      (this->RccEnabled && this->MultiConfig)) {
+    std::string includeDir = this->DirBuild;
+    includeDir += "/include";
+    if (this->MultiConfig) {
       includeDir += "_$<CONFIG>";
     }
     this->Target->AddIncludeDirectory(includeDir, true);
@@ -674,9 +619,10 @@ void cmQtAutoGenInitializer::InitCustomTargets()
     }
     for (Qrc& qrc : this->Qrcs) {
       // Register file at target
-      std::vector<std::string> const ccOutput =
-        this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);
+      this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);
 
+      std::vector<std::string> ccOutput;
+      ccOutput.push_back(qrc.RccFile);
       cmCustomCommandLines commandLines;
       {
         cmCustomCommandLine currentLine;
@@ -905,51 +851,6 @@ void cmQtAutoGenInitializer::SetupCustomTargets()
 {
   cmMakefile* makefile = this->Target->Target->GetMakefile();
 
-  // forget the variables added here afterwards again:
-  cmMakefile::ScopePushPop varScope(makefile);
-  static_cast<void>(varScope);
-
-  // Configuration suffixes
-  std::map<std::string, std::string> configSuffixes;
-  for (std::string const& cfg : this->ConfigsList) {
-    std::string& suffix = configSuffixes[cfg];
-    suffix = "_";
-    suffix += cfg;
-  }
-
-  // Basic setup
-  AddDefinitionEscaped(makefile, "_multi_config",
-                       MultiConfigName(this->MultiConfig));
-  AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild);
-  {
-    std::string parallel = GetSafeProperty(this->Target, "AUTOGEN_PARALLEL");
-    // Autodetect number of CPUs
-    if (parallel.empty() || (parallel == "AUTO")) {
-      parallel = std::to_string(GetParallelCPUCount());
-    }
-    AddDefinitionEscaped(makefile, "_parallel", parallel);
-  }
-
-  if (this->MocEnabled || this->UicEnabled) {
-    AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
-    AddDefinitionEscaped(makefile, "_settings_file",
-                         this->AutogenSettingsFile);
-    AddDefinitionEscaped(makefile, "_sources", this->Sources);
-    AddDefinitionEscaped(makefile, "_headers", this->Headers);
-
-    if (this->MocEnabled) {
-      this->SetupCustomTargetsMoc();
-    }
-    if (this->UicEnabled) {
-      this->SetupCustomTargetsUic();
-    }
-  }
-  if (this->RccEnabled) {
-    AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable);
-    AddDefinitionEscaped(makefile, "_qt_rcc_list_options",
-                         this->RccListOptions);
-  }
-
   // Create info directory on demand
   if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
     std::string emsg = ("Could not create directory: ");
@@ -957,21 +858,33 @@ void cmQtAutoGenInitializer::SetupCustomTargets()
     cmSystemTools::Error(emsg.c_str());
   }
 
-  auto ReOpenInfoFile = [](cmsys::ofstream& ofs,
-                           std::string const& fileName) -> bool {
+  // Configuration include directories
+  std::string includeDir = "include";
+  std::map<std::string, std::string> includeDirs;
+  for (std::string const& cfg : this->ConfigsList) {
+    std::string& dir = includeDirs[cfg];
+    dir = "include_";
+    dir += cfg;
+  }
+
+  auto OpenInfoFile = [](cmsys::ofstream& ofs,
+                         std::string const& fileName) -> bool {
     // Ensure we have write permission
-    mode_t perm = 0;
+    if (cmSystemTools::FileExists(fileName)) {
+      mode_t perm = 0;
 #if defined(_WIN32) && !defined(__CYGWIN__)
-    mode_t mode_write = S_IWRITE;
+      mode_t mode_write = S_IWRITE;
 #else
-    mode_t mode_write = S_IWUSR;
+      mode_t mode_write = S_IWUSR;
 #endif
-    cmSystemTools::GetPermissions(fileName, perm);
-    if (!(perm & mode_write)) {
-      cmSystemTools::SetPermissions(fileName, perm | mode_write);
+      cmSystemTools::GetPermissions(fileName, perm);
+      if (!(perm & mode_write)) {
+        cmSystemTools::SetPermissions(fileName, perm | mode_write);
+      }
     }
 
-    ofs.open(fileName.c_str(), std::ios::app);
+    ofs.open(fileName.c_str(),
+             (std::ios::out | std::ios::binary | std::ios::trunc));
     if (!ofs) {
       // File open error
       std::string error = "Internal CMake error when trying to open file: ";
@@ -984,88 +897,177 @@ void cmQtAutoGenInitializer::SetupCustomTargets()
 
   // Generate autogen target info file
   if (this->MocEnabled || this->UicEnabled) {
-    {
-      std::string infoFileIn = cmSystemTools::GetCMakeRoot();
-      infoFileIn += "/Modules/AutogenInfo.cmake.in";
-      makefile->ConfigureFile(
-        infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false);
+    if (this->MocEnabled) {
+      this->SetupCustomTargetsMoc();
+    }
+    if (this->UicEnabled) {
+      this->SetupCustomTargetsUic();
+    }
+
+    // Parallel processing
+    this->Parallel = GetSafeProperty(this->Target, "AUTOGEN_PARALLEL");
+    if (this->Parallel.empty() || (this->Parallel == "AUTO")) {
+      // Autodetect number of CPUs
+      this->Parallel = std::to_string(GetParallelCPUCount());
     }
 
-    // Append custom definitions to info file
-    // --------------------------------------
     cmsys::ofstream ofs;
-    if (ReOpenInfoFile(ofs, this->AutogenInfoFile)) {
-      auto OfsWriteMap = [&ofs](
-        const char* key, std::map<std::string, std::string> const& map) {
+    if (OpenInfoFile(ofs, this->AutogenInfoFile)) {
+      // Utility lambdas
+      auto CWrite = [&ofs](const char* key, std::string const& value) {
+        ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
+            << ")\n";
+      };
+      auto CWriteList = [&CWrite](const char* key,
+                                  std::vector<std::string> const& list) {
+        CWrite(key, cmJoin(list, ";"));
+      };
+      auto CWriteNestedLists = [&CWrite](
+        const char* key, std::vector<std::vector<std::string>> const& lists) {
+        std::vector<std::string> seplist;
+        for (const std::vector<std::string>& list : lists) {
+          std::string blist = "{";
+          blist += cmJoin(list, ";");
+          blist += "}";
+          seplist.push_back(std::move(blist));
+        }
+        CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
+      };
+      auto CWriteSet = [&CWrite](const char* key,
+                                 std::set<std::string> const& list) {
+        CWrite(key, cmJoin(list, ";"));
+      };
+      auto CWriteMap = [&ofs](const char* key,
+                              std::map<std::string, std::string> const& map) {
         for (auto const& item : map) {
           ofs << "set(" << key << "_" << item.first << " "
               << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
         }
       };
-      ofs << "# Configurations options\n";
-      OfsWriteMap("AM_CONFIG_SUFFIX", configSuffixes);
-      OfsWriteMap("AM_MOC_DEFINITIONS", this->ConfigMocDefines);
-      OfsWriteMap("AM_MOC_INCLUDES", this->ConfigMocIncludes);
-      OfsWriteMap("AM_UIC_TARGET_OPTIONS", this->ConfigUicOptions);
-      // Settings files (only require for multi configuration generators)
-      if (this->MultiConfig != MultiConfigT::SINGLE) {
+      auto MfDef = [makefile](const char* key) {
+        return std::string(makefile->GetSafeDefinition(key));
+      };
+
+      // Write
+      ofs << "# Meta\n";
+      CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
+      CWrite("AM_PARALLEL", this->Parallel);
+
+      ofs << "# Directories\n";
+      CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+      CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+      CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+      CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+      CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
+             MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
+      CWrite("AM_BUILD_DIR", this->DirBuild);
+      if (this->MultiConfig) {
+        CWriteMap("AM_INCLUDE_DIR", includeDirs);
+      } else {
+        CWrite("AM_INCLUDE_DIR", includeDir);
+      }
+
+      ofs << "# Files\n";
+      CWriteList("AM_SOURCES", this->Sources);
+      CWriteList("AM_HEADERS", this->Headers);
+      if (this->MultiConfig) {
         std::map<std::string, std::string> settingsFiles;
         for (std::string const& cfg : this->ConfigsList) {
           settingsFiles[cfg] =
             AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg);
         }
-        OfsWriteMap("AM_SETTINGS_FILE", settingsFiles);
+        CWriteMap("AM_SETTINGS_FILE", settingsFiles);
+      } else {
+        CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile);
+      }
+
+      ofs << "# Qt\n";
+      CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor);
+      CWrite("AM_QT_MOC_EXECUTABLE", this->MocExecutable);
+      CWrite("AM_QT_UIC_EXECUTABLE", this->UicExecutable);
+
+      if (this->MocEnabled) {
+        ofs << "# MOC settings\n";
+        CWriteSet("AM_MOC_SKIP", this->MocSkip);
+        CWrite("AM_MOC_DEFINITIONS", this->MocDefines);
+        CWriteMap("AM_MOC_DEFINITIONS", this->MocDefinesConfig);
+        CWrite("AM_MOC_INCLUDES", this->MocIncludes);
+        CWriteMap("AM_MOC_INCLUDES", this->MocIncludesConfig);
+        CWrite("AM_MOC_OPTIONS",
+               GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
+        CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
+        CWrite("AM_MOC_MACRO_NAMES",
+               GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
+        CWrite("AM_MOC_DEPEND_FILTERS",
+               GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
+        CWrite("AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
+      }
+
+      if (this->UicEnabled) {
+        ofs << "# UIC settings\n";
+        CWriteSet("AM_UIC_SKIP", this->UicSkip);
+        CWrite("AM_UIC_TARGET_OPTIONS", this->UicOptions);
+        CWriteMap("AM_UIC_TARGET_OPTIONS", this->UicOptionsConfig);
+        CWriteList("AM_UIC_OPTIONS_FILES", this->UicFileFiles);
+        CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->UicFileOptions);
+        CWriteList("AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
       }
     }
   }
 
   // Generate auto RCC info files
   if (this->RccEnabled) {
-    std::string infoFileIn = cmSystemTools::GetCMakeRoot();
-    infoFileIn += "/Modules/AutoRccInfo.cmake.in";
     for (Qrc const& qrc : this->Qrcs) {
-      // Configure info file
-      makefile->ConfigureFile(infoFileIn.c_str(), qrc.InfoFile.c_str(), false,
-                              true, false);
-
-      // Append custom definitions to info file
-      // --------------------------------------
       cmsys::ofstream ofs;
-      if (ReOpenInfoFile(ofs, qrc.InfoFile)) {
-        {
-          ofs << "# Job\n";
-          auto OfsWrite = [&ofs](const char* key, std::string const& value) {
-            ofs << "set(" << key << " "
-                << cmOutputConverter::EscapeForCMake(value) << ")\n";
-
-          };
-          OfsWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
-          OfsWrite("ARCC_SOURCE", qrc.QrcFile);
-          OfsWrite("ARCC_OUTPUT", qrc.RccFile);
-          OfsWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
-          OfsWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
-        }
-        {
-          ofs << "# Configurations options\n";
-          auto OfsWriteMap = [&ofs](
-            const char* key, std::map<std::string, std::string> const& map) {
-            for (auto const& item : map) {
-              ofs << "set(" << key << "_" << item.first << " "
-                  << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
-            }
-          };
-          OfsWriteMap("ARCC_CONFIG_SUFFIX", configSuffixes);
-
-          // Settings files (only require for multi configuration generators)
-          if (this->MultiConfig != MultiConfigT::SINGLE) {
-            std::map<std::string, std::string> settingsFiles;
-            for (std::string const& cfg : this->ConfigsList) {
-              settingsFiles[cfg] =
-                AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
-            }
-            OfsWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
+      if (OpenInfoFile(ofs, qrc.InfoFile)) {
+        // Utility lambdas
+        auto CWrite = [&ofs](const char* key, std::string const& value) {
+          ofs << "set(" << key << " "
+              << cmOutputConverter::EscapeForCMake(value) << ")\n";
+        };
+        auto CWriteMap = [&ofs](
+          const char* key, std::map<std::string, std::string> const& map) {
+          for (auto const& item : map) {
+            ofs << "set(" << key << "_" << item.first << " "
+                << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
+          }
+        };
+
+        // Write
+        ofs << "# Configurations\n";
+        CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
+
+        ofs << "# Settings file\n";
+        if (this->MultiConfig) {
+          std::map<std::string, std::string> settingsFiles;
+          for (std::string const& cfg : this->ConfigsList) {
+            settingsFiles[cfg] =
+              AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
           }
+          CWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
+        } else {
+          CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
         }
+
+        ofs << "# Directories\n";
+        CWrite("ARCC_BUILD_DIR", this->DirBuild);
+        if (this->MultiConfig) {
+          CWriteMap("ARCC_INCLUDE_DIR", includeDirs);
+        } else {
+          CWrite("ARCC_INCLUDE_DIR", includeDir);
+        }
+
+        ofs << "# Rcc executable\n";
+        CWrite("ARCC_RCC_EXECUTABLE", this->RccExecutable);
+        CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->RccListOptions, ";"));
+
+        ofs << "# Rcc job\n";
+        CWrite("ARCC_SOURCE", qrc.QrcFile);
+        CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
+        CWrite("ARCC_OUTPUT_NAME",
+               cmSystemTools::GetFilenameName(qrc.RccFile));
+        CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
+        CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
       } else {
         break;
       }
@@ -1078,25 +1080,13 @@ void cmQtAutoGenInitializer::SetupCustomTargetsMoc()
   cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
   cmMakefile* makefile = this->Target->Target->GetMakefile();
 
-  AddDefinitionEscaped(makefile, "_moc_skip", this->MocSkip);
-  AddDefinitionEscaped(makefile, "_moc_options",
-                       GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
-  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
-                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
-                                                                    : "FALSE");
-  AddDefinitionEscaped(makefile, "_moc_macro_names",
-                       GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
-  AddDefinitionEscaped(
-    makefile, "_moc_depend_filters",
-    GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
-
-  // Compiler predefines
+  // Moc predefs command
   if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
       this->QtVersionGreaterOrEqual(5, 8)) {
-    AddDefinitionEscaped(
-      makefile, "_moc_predefs_cmd",
-      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
+    this->MocPredefsCmd =
+      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");
   }
+
   // Moc includes and compile definitions
   {
     auto GetIncludeDirs = [this,
@@ -1117,25 +1107,23 @@ void cmQtAutoGenInitializer::SetupCustomTargetsMoc()
     };
 
     // Default configuration settings
-    std::string const includeDirs = GetIncludeDirs(this->ConfigDefault);
-    std::string const compileDefs = GetCompileDefinitions(this->ConfigDefault);
+    this->MocIncludes = GetIncludeDirs(this->ConfigDefault);
+    this->MocDefines = GetCompileDefinitions(this->ConfigDefault);
     // Other configuration settings
     for (std::string const& cfg : this->ConfigsList) {
       {
         std::string const configIncludeDirs = GetIncludeDirs(cfg);
-        if (configIncludeDirs != includeDirs) {
-          this->ConfigMocIncludes[cfg] = configIncludeDirs;
+        if (configIncludeDirs != this->MocIncludes) {
+          this->MocIncludesConfig[cfg] = configIncludeDirs;
         }
       }
       {
         std::string const configCompileDefs = GetCompileDefinitions(cfg);
-        if (configCompileDefs != compileDefs) {
-          this->ConfigMocDefines[cfg] = configCompileDefs;
+        if (configCompileDefs != this->MocDefines) {
+          this->MocDefinesConfig[cfg] = configCompileDefs;
         }
       }
     }
-    AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
-    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
   }
 
   // Moc executable
@@ -1162,7 +1150,7 @@ void cmQtAutoGenInitializer::SetupCustomTargetsMoc()
     }
 
     if (err.empty()) {
-      AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
+      this->MocExecutable = mocExec;
     } else {
       err += " (";
       err += this->Target->GetName();
@@ -1178,19 +1166,15 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic()
 
   // Uic search paths
   {
-    std::vector<std::string> uicSearchPaths;
-    {
-      std::string const usp =
-        GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
-      if (!usp.empty()) {
-        cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
-        std::string const srcDir = makefile->GetCurrentSourceDirectory();
-        for (std::string& path : uicSearchPaths) {
-          path = cmSystemTools::CollapseFullPath(path, srcDir);
-        }
+    std::string const usp =
+      GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
+    if (!usp.empty()) {
+      cmSystemTools::ExpandListArgument(usp, this->UicSearchPaths);
+      std::string const srcDir = makefile->GetCurrentSourceDirectory();
+      for (std::string& path : this->UicSearchPaths) {
+        path = cmSystemTools::CollapseFullPath(path, srcDir);
       }
     }
-    AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
   }
   // Uic target options
   {
@@ -1201,60 +1185,51 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic()
     };
 
     // Default settings
-    std::string const uicOpts = UicGetOpts(this->ConfigDefault);
-    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
+    this->UicOptions = UicGetOpts(this->ConfigDefault);
 
     // Configuration specific settings
     for (std::string const& cfg : this->ConfigsList) {
       std::string const configUicOpts = UicGetOpts(cfg);
-      if (configUicOpts != uicOpts) {
-        this->ConfigUicOptions[cfg] = configUicOpts;
+      if (configUicOpts != this->UicOptions) {
+        this->UicOptionsConfig[cfg] = configUicOpts;
       }
     }
   }
   // .ui files skip and options
   {
-    std::vector<std::string> uiFileFiles;
-    std::vector<std::vector<std::string>> uiFileOptions;
-    {
-      std::string const uiExt = "ui";
-      std::string pathError;
-      for (cmSourceFile* sf : makefile->GetSourceFiles()) {
-        // sf->GetExtension() is only valid after sf->GetFullPath() ...
-        // Since we're iterating over source files that might be not in the
-        // target we need to check for path errors (not existing files).
-        std::string const& fPath = sf->GetFullPath(&pathError);
-        if (!pathError.empty()) {
-          pathError.clear();
-          continue;
+    std::string const uiExt = "ui";
+    std::string pathError;
+    for (cmSourceFile* sf : makefile->GetSourceFiles()) {
+      // sf->GetExtension() is only valid after sf->GetFullPath() ...
+      // Since we're iterating over source files that might be not in the
+      // target we need to check for path errors (not existing files).
+      std::string const& fPath = sf->GetFullPath(&pathError);
+      if (!pathError.empty()) {
+        pathError.clear();
+        continue;
+      }
+      if (sf->GetExtension() == uiExt) {
+        std::string const absFile = cmSystemTools::GetRealPath(fPath);
+        // Check if the .ui file should be skipped
+        if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
+            sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
+          this->UicSkip.insert(absFile);
         }
-        if (sf->GetExtension() == uiExt) {
-          std::string const absFile = cmSystemTools::GetRealPath(fPath);
-          // Check if the .ui file should be skipped
-          if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
-              sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
-            this->UicSkip.insert(absFile);
-          }
-          // Check if the .ui file has uic options
-          std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
-          if (!uicOpts.empty()) {
-            // Check if file isn't skipped
-            if (this->UicSkip.count(absFile) == 0) {
-              uiFileFiles.push_back(absFile);
-              std::vector<std::string> optsVec;
-              cmSystemTools::ExpandListArgument(uicOpts, optsVec);
-              uiFileOptions.push_back(std::move(optsVec));
-            }
+        // Check if the .ui file has uic options
+        std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
+        if (!uicOpts.empty()) {
+          // Check if file isn't skipped
+          if (this->UicSkip.count(absFile) == 0) {
+            this->UicFileFiles.push_back(absFile);
+            std::vector<std::string> optsVec;
+            cmSystemTools::ExpandListArgument(uicOpts, optsVec);
+            this->UicFileOptions.push_back(std::move(optsVec));
           }
         }
       }
     }
-    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
-    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
   }
 
-  AddDefinitionEscaped(makefile, "_uic_skip", this->UicSkip);
-
   // Uic executable
   {
     std::string err;
@@ -1280,7 +1255,7 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic()
     }
 
     if (err.empty()) {
-      AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
+      this->UicExecutable = uicExec;
     } else {
       err += " (";
       err += this->Target->GetName();
@@ -1290,45 +1265,22 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic()
   }
 }
 
-std::vector<std::string> cmQtAutoGenInitializer::AddGeneratedSource(
-  std::string const& filename, GeneratorT genType)
+void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,
+                                                GeneratorT genType)
 {
-  std::vector<std::string> genFiles;
-  // Register source file in makefile and source group
-  if (this->MultiConfig != MultiConfigT::MULTI) {
-    genFiles.push_back(filename);
-  } else {
-    for (std::string const& cfg : this->ConfigsList) {
-      genFiles.push_back(AppendFilenameSuffix(filename, "_" + cfg));
-    }
-  }
+  // Register source file in makefile
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
   {
-    cmMakefile* makefile = this->Target->Target->GetMakefile();
-    for (std::string const& genFile : genFiles) {
-      {
-        cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
-        gFile->SetProperty("GENERATED", "1");
-        gFile->SetProperty("SKIP_AUTOGEN", "On");
-      }
-      AddToSourceGroup(makefile, genFile, genType);
-    }
+    cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
+    gFile->SetProperty("GENERATED", "1");
+    gFile->SetProperty("SKIP_AUTOGEN", "On");
   }
 
-  // Add source file to target
-  if (this->MultiConfig != MultiConfigT::MULTI) {
-    this->Target->AddSource(filename);
-  } else {
-    for (std::string const& cfg : this->ConfigsList) {
-      std::string src = "$<$<CONFIG:";
-      src += cfg;
-      src += ">:";
-      src += AppendFilenameSuffix(filename, "_" + cfg);
-      src += ">";
-      this->Target->AddSource(src);
-    }
-  }
+  // Add source file to source group
+  AddToSourceGroup(makefile, filename, genType);
 
-  return genFiles;
+  // Add source file to target
+  this->Target->AddSource(filename);
 }
 
 std::string cmQtAutoGenInitializer::GetQtMajorVersion(
@@ -1400,7 +1352,8 @@ bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName,
       return false;
     }
 
-    // Run rcc list command in the directory of the qrc file with the pathless
+    // Run rcc list command in the directory of the qrc file with the
+    // pathless
     // qrc file name argument. This way rcc prints relative paths.
     // This avoids issues on Windows when the qrc file is in a path that
     // contains non-ASCII characters.

+ 19 - 6
Source/cmQtAutoGenInitializer.h

@@ -21,6 +21,7 @@ public:
   static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
                                        std::string const& qtVersionMajor);
 
+  /// @brief Rcc job information
   class Qrc
   {
   public:
@@ -55,8 +56,7 @@ private:
   void SetupCustomTargetsMoc();
   void SetupCustomTargetsUic();
 
-  std::vector<std::string> AddGeneratedSource(std::string const& filename,
-                                              GeneratorT genType);
+  void AddGeneratedSource(std::string const& filename, GeneratorT genType);
 
   bool QtVersionGreaterOrEqual(unsigned long requestMajor,
                                unsigned long requestMinor) const;
@@ -70,15 +70,18 @@ private:
   bool MocEnabled;
   bool UicEnabled;
   bool RccEnabled;
+  bool MultiConfig;
   // Qt
   std::string QtVersionMajor;
   std::string QtVersionMinor;
+  std::string MocExecutable;
+  std::string UicExecutable;
   std::string RccExecutable;
   std::vector<std::string> RccListOptions;
   // Configurations
   std::string ConfigDefault;
   std::vector<std::string> ConfigsList;
-  MultiConfigT MultiConfig;
+  std::string Parallel;
   // Names
   std::string AutogenTargetName;
   std::string AutogenFolder;
@@ -91,11 +94,21 @@ private:
   // Sources
   std::vector<std::string> Headers;
   std::vector<std::string> Sources;
+  // Moc
+  std::string MocPredefsCmd;
   std::set<std::string> MocSkip;
+  std::string MocIncludes;
+  std::map<std::string, std::string> MocIncludesConfig;
+  std::string MocDefines;
+  std::map<std::string, std::string> MocDefinesConfig;
+  // Uic
   std::set<std::string> UicSkip;
-  std::map<std::string, std::string> ConfigMocIncludes;
-  std::map<std::string, std::string> ConfigMocDefines;
-  std::map<std::string, std::string> ConfigUicOptions;
+  std::vector<std::string> UicSearchPaths;
+  std::string UicOptions;
+  std::map<std::string, std::string> UicOptionsConfig;
+  std::vector<std::string> UicFileFiles;
+  std::vector<std::vector<std::string>> UicFileOptions;
+  // Rcc
   std::vector<Qrc> Qrcs;
 };
 

+ 54 - 50
Source/cmQtAutoGeneratorMocUic.cxx

@@ -672,19 +672,24 @@ void cmQtAutoGeneratorMocUic::JobMocT::Process(WorkerT& wrk)
 {
   // Compute build file name
   if (!IncludeString.empty()) {
-    BuildFile = wrk.Base().AutogenIncludeDirAbs;
+    BuildFile = wrk.Base().AutogenIncludeDir;
+    BuildFile += '/';
     BuildFile += IncludeString;
   } else {
-    std::string buildRel = wrk.Base().FilePathChecksum.getPart(SourceFile);
-    buildRel += '/';
-    buildRel += "moc_";
-    buildRel += cmSystemTools::GetFilenameWithoutLastExtension(SourceFile);
-    if (wrk.Base().MultiConfig != MultiConfigT::SINGLE) {
-      buildRel += wrk.Base().ConfigSuffix;
+    std::string rel = wrk.Base().FilePathChecksum.getPart(SourceFile);
+    rel += "/moc_";
+    rel += cmSystemTools::GetFilenameWithoutLastExtension(SourceFile);
+    rel += ".cpp";
+    // Register relative file path
+    wrk.Gen().ParallelMocAutoRegister(rel);
+    // Absolute build path
+    if (wrk.Base().MultiConfig) {
+      BuildFile = wrk.Base().AutogenIncludeDir;
+      BuildFile += '/';
+      BuildFile += rel;
+    } else {
+      BuildFile = wrk.Base().AbsoluteBuildPath(rel);
     }
-    buildRel += ".cpp";
-    wrk.Gen().ParallelMocAutoRegister(buildRel);
-    BuildFile = wrk.Base().AbsoluteBuildPath(buildRel);
   }
 
   if (UpdateRequired(wrk)) {
@@ -871,7 +876,8 @@ void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk)
 void cmQtAutoGeneratorMocUic::JobUicT::Process(WorkerT& wrk)
 {
   // Compute build file name
-  BuildFile = wrk.Base().AutogenIncludeDirAbs;
+  BuildFile = wrk.Base().AutogenIncludeDir;
+  BuildFile += '/';
   BuildFile += IncludeString;
 
   if (UpdateRequired(wrk)) {
@@ -1208,20 +1214,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
   }
 
   // -- Meta
-  Base_.MultiConfig = MultiConfigType(InfoGet("AM_MULTI_CONFIG"));
-
-  Base_.ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX");
-  if (Base_.ConfigSuffix.empty()) {
-    Base_.ConfigSuffix = "_";
-    Base_.ConfigSuffix += InfoConfig();
-  }
-
-  SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
-  if (SettingsFile_.empty()) {
-    Log().ErrorFile(GeneratorT::GEN, InfoFile(), "Settings file name missing");
-    return false;
-  }
-
+  Base_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
   {
     unsigned long num = Base_.NumThreads;
     if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL"), &num)) {
@@ -1244,6 +1237,23 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
                     "Autogen build directory missing");
     return false;
   }
+  // include directory
+  {
+    std::string dirRel = InfoGetConfig("AM_INCLUDE_DIR");
+    if (dirRel.empty()) {
+      Log().ErrorFile(GeneratorT::GEN, InfoFile(),
+                      "Autogen include directory missing");
+      return false;
+    }
+    Base_.AutogenIncludeDir = Base_.AbsoluteBuildPath(dirRel);
+  }
+
+  // - Files
+  SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
+  if (SettingsFile_.empty()) {
+    Log().ErrorFile(GeneratorT::GEN, InfoFile(), "Settings file name missing");
+    return false;
+  }
 
   // - Qt environment
   {
@@ -1438,30 +1448,17 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
     Base().CurrentSourceDir, Base().CurrentBinaryDir, Base().ProjectSourceDir,
     Base().ProjectBinaryDir);
 
-  // include directory
-  Base_.AutogenIncludeDirRel = "include";
-  if (Base().MultiConfig != MultiConfigT::SINGLE) {
-    Base_.AutogenIncludeDirRel += Base().ConfigSuffix;
-  }
-  Base_.AutogenIncludeDirRel += "/";
-  Base_.AutogenIncludeDirAbs =
-    Base_.AbsoluteBuildPath(Base().AutogenIncludeDirRel);
-
   // Moc variables
   if (Moc().Enabled) {
     // Mocs compilation file
-    Moc_.CompFileRel = "mocs_compilation";
-    if (Base_.MultiConfig == MultiConfigT::MULTI) {
-      Moc_.CompFileRel += Base().ConfigSuffix;
-    }
-    Moc_.CompFileRel += ".cpp";
-    Moc_.CompFileAbs = Base_.AbsoluteBuildPath(Moc().CompFileRel);
+    Moc_.CompFileAbs = Base().AbsoluteBuildPath("mocs_compilation.cpp");
 
     // Moc predefs file
     if (!Moc_.PredefsCmd.empty()) {
       Moc_.PredefsFileRel = "moc_predefs";
-      if (Base_.MultiConfig != MultiConfigT::SINGLE) {
-        Moc_.PredefsFileRel += Base().ConfigSuffix;
+      if (Base_.MultiConfig) {
+        Moc_.PredefsFileRel += '_';
+        Moc_.PredefsFileRel += InfoConfig();
       }
       Moc_.PredefsFileRel += ".h";
       Moc_.PredefsFileAbs = Base_.AbsoluteBuildPath(Moc().PredefsFileRel);
@@ -1731,7 +1728,7 @@ void cmQtAutoGeneratorMocUic::SettingsFileWrite()
 void cmQtAutoGeneratorMocUic::CreateDirectories()
 {
   // Create AUTOGEN include directory
-  if (!FileSys().MakeDirectory(GeneratorT::GEN, Base().AutogenIncludeDirAbs)) {
+  if (!FileSys().MakeDirectory(GeneratorT::GEN, Base().AutogenIncludeDir)) {
     RegisterJobError();
   }
 }
@@ -1980,9 +1977,10 @@ void cmQtAutoGeneratorMocUic::ParallelMocAutoUpdated()
 void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
 {
   std::lock_guard<std::mutex> mocLock(JobsMutex_);
-  if (!JobThreadsAbort_ && Moc().Enabled) {
-    // Compose mocs compilation file content
+  if (!JobError_ && Moc().Enabled) {
+    // Write mocs compilation build file
     {
+      // Compose mocs compilation file content
       std::string content =
         "// This file is autogenerated. Changes will be overwritten.\n";
       if (MocAutoFiles_.empty()) {
@@ -1992,19 +1990,22 @@ void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
         content += "enum some_compilers { need_more_than_nothing };\n";
       } else {
         // Valid content
+        char const sbeg = Base().MultiConfig ? '<' : '"';
+        char const send = Base().MultiConfig ? '>' : '"';
         for (std::string const& mocfile : MocAutoFiles_) {
-          content += "#include \"";
+          content += "#include ";
+          content += sbeg;
           content += mocfile;
-          content += "\"\n";
+          content += send;
+          content += '\n';
         }
       }
 
-      std::string const& compRel = Moc().CompFileRel;
       std::string const& compAbs = Moc().CompFileAbs;
       if (FileSys().FileDiffers(compAbs, content)) {
         // Actually write mocs compilation file
         if (Log().Verbose()) {
-          Log().Info(GeneratorT::MOC, "Generating MOC compilation " + compRel);
+          Log().Info(GeneratorT::MOC, "Generating MOC compilation " + compAbs);
         }
         if (!FileSys().FileWrite(GeneratorT::MOC, compAbs, content)) {
           Log().ErrorFile(GeneratorT::MOC, compAbs,
@@ -2015,10 +2016,13 @@ void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
       } else if (MocAutoFileUpdated_) {
         // Only touch mocs compilation file
         if (Log().Verbose()) {
-          Log().Info(GeneratorT::MOC, "Touching mocs compilation " + compRel);
+          Log().Info(GeneratorT::MOC, "Touching mocs compilation " + compAbs);
         }
         FileSys().Touch(compAbs);
       }
     }
+    // Write mocs compilation wrapper file
+    if (Base().MultiConfig) {
+    }
   }
 }

+ 3 - 6
Source/cmQtAutoGeneratorMocUic.h

@@ -68,7 +68,7 @@ public:
   public:
     // -- Volatile methods
     BaseSettingsT(FileSystem* fileSystem)
-      : MultiConfig(MultiConfigT::WRAPPER)
+      : MultiConfig(false)
       , IncludeProjectDirsBefore(false)
       , QtVersionMajor(4)
       , NumThreads(1)
@@ -83,8 +83,7 @@ public:
 
     // -- Attributes
     // - Config
-    std::string ConfigSuffix;
-    MultiConfigT MultiConfig;
+    bool MultiConfig;
     bool IncludeProjectDirsBefore;
     unsigned int QtVersionMajor;
     unsigned int NumThreads;
@@ -94,8 +93,7 @@ public:
     std::string CurrentSourceDir;
     std::string CurrentBinaryDir;
     std::string AutogenBuildDir;
-    std::string AutogenIncludeDirRel;
-    std::string AutogenIncludeDirAbs;
+    std::string AutogenIncludeDir;
     // - Files
     cmFilePathChecksum FilePathChecksum;
     std::vector<std::string> HeaderExtensions;
@@ -128,7 +126,6 @@ public:
     bool SettingsChanged = false;
     bool RelaxedMode = false;
     std::string Executable;
-    std::string CompFileRel;
     std::string CompFileAbs;
     std::string PredefsFileRel;
     std::string PredefsFileAbs;

+ 86 - 64
Source/cmQtAutoGeneratorRcc.cxx

@@ -14,8 +14,8 @@
 // -- Class methods
 
 cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
-  : SettingsChanged_(false)
-  , MultiConfig_(MultiConfigT::WRAPPER)
+  : MultiConfig_(false)
+  , SettingsChanged_(false)
   , Stage_(StageT::SETTINGS_READ)
   , Error_(false)
   , Generate_(false)
@@ -31,16 +31,18 @@ cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc()
 
 bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
 {
-  // Utility lambdas
-  auto InfoGet = [makefile](const char* key) {
+  // -- Utility lambdas
+  auto InfoGet = [makefile](std::string const& key) {
     return makefile->GetSafeDefinition(key);
   };
-  auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
+  auto InfoGetList =
+    [makefile](std::string const& key) -> std::vector<std::string> {
     std::vector<std::string> list;
     cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
     return list;
   };
-  auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
+  auto InfoGetConfig = [makefile,
+                        this](std::string const& key) -> std::string {
     const char* valueConf = nullptr;
     {
       std::string keyConf = key;
@@ -54,7 +56,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
     return std::string(valueConf);
   };
   auto InfoGetConfigList =
-    [&InfoGetConfig](const char* key) -> std::vector<std::string> {
+    [&InfoGetConfig](std::string const& key) -> std::vector<std::string> {
     std::vector<std::string> list;
     cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
     return list;
@@ -66,20 +68,23 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
     return false;
   }
 
-  // -- Meta
-  MultiConfig_ = MultiConfigType(InfoGet("ARCC_MULTI_CONFIG"));
-  ConfigSuffix_ = InfoGetConfig("ARCC_CONFIG_SUFFIX");
-  if (ConfigSuffix_.empty()) {
-    ConfigSuffix_ = "_";
-    ConfigSuffix_ += InfoConfig();
-  }
-
-  SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
+  // - Configurations
+  MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
 
-  // - Files and directories
+  // - Directories
   AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
+  if (AutogenBuildDir_.empty()) {
+    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Build directory empty");
+    return false;
+  }
 
-  // - Qt environment
+  IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
+  if (IncludeDir_.empty()) {
+    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Include directory empty");
+    return false;
+  }
+
+  // - Rcc executable
   RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
   RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
 
@@ -87,10 +92,14 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
   QrcFile_ = InfoGet("ARCC_SOURCE");
   QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
   QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
-  RccFile_ = InfoGet("ARCC_OUTPUT");
+  RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
+  RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
   Options_ = InfoGetConfigList("ARCC_OPTIONS");
   Inputs_ = InfoGetList("ARCC_INPUTS");
 
+  // - Settings file
+  SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
+
   // - Validity checks
   if (SettingsFile_.empty()) {
     Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Settings file name missing");
@@ -109,7 +118,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
     Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc input file missing");
     return false;
   }
-  if (RccFile_.empty()) {
+  if (RccFileName_.empty()) {
     Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc output file missing");
     return false;
   }
@@ -117,22 +126,21 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
   // Init derived information
   // ------------------------
 
+  RccFilePublic_ = AutogenBuildDir_;
+  RccFilePublic_ += '/';
+  RccFilePublic_ += RccPathChecksum_;
+  RccFilePublic_ += '/';
+  RccFilePublic_ += RccFileName_;
+
   // Compute rcc output file name
-  {
-    std::string suffix;
-    switch (MultiConfig_) {
-      case MultiConfigT::SINGLE:
-        break;
-      case MultiConfigT::WRAPPER:
-        suffix = "_CMAKE";
-        suffix += ConfigSuffix_;
-        suffix += "_";
-        break;
-      case MultiConfigT::MULTI:
-        suffix = ConfigSuffix_;
-        break;
-    }
-    RccFileBuild_ = AppendFilenameSuffix(RccFile_, suffix);
+  if (IsMultiConfig()) {
+    RccFileOutput_ = AutogenBuildDir_;
+    RccFileOutput_ += '/';
+    RccFileOutput_ += IncludeDir_;
+    RccFileOutput_ += '/';
+    RccFileOutput_ += MultiConfigOutput();
+  } else {
+    RccFileOutput_ = RccFilePublic_;
   }
 
   return true;
@@ -234,6 +242,16 @@ void cmQtAutoGeneratorRcc::SetStage(StageT stage)
   }
 }
 
+std::string cmQtAutoGeneratorRcc::MultiConfigOutput() const
+{
+  static std::string const suffix = "_CMAKE_";
+  std::string res;
+  res += RccPathChecksum_;
+  res += '/';
+  res += AppendFilenameSuffix(RccFileName_, suffix);
+  return res;
+}
+
 void cmQtAutoGeneratorRcc::SettingsFileRead()
 {
   // Compose current settings strings
@@ -248,7 +266,9 @@ void cmQtAutoGeneratorRcc::SettingsFileRead()
       str += sep;
       str += QrcFile_;
       str += sep;
-      str += RccFile_;
+      str += RccPathChecksum_;
+      str += sep;
+      str += RccFileName_;
       str += sep;
       str += cmJoin(Options_, ";");
       str += sep;
@@ -302,10 +322,10 @@ bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
   // Do basic checks if rcc generation is required
 
   // Test if the rcc output file exists
-  if (!FileSys().FileExists(RccFileBuild_)) {
+  if (!FileSys().FileExists(RccFileOutput_)) {
     if (Log().Verbose()) {
       std::string reason = "Generating ";
-      reason += Quoted(RccFileBuild_);
+      reason += Quoted(RccFileOutput_);
       reason += " from its source file ";
       reason += Quoted(QrcFile_);
       reason += " because it doesn't exist";
@@ -319,7 +339,7 @@ bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
   if (SettingsChanged_) {
     if (Log().Verbose()) {
       std::string reason = "Generating ";
-      reason += Quoted(RccFileBuild_);
+      reason += Quoted(RccFileOutput_);
       reason += " from ";
       reason += Quoted(QrcFile_);
       reason += " because the RCC settings changed";
@@ -334,7 +354,7 @@ bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
     bool isOlder = false;
     {
       std::string error;
-      isOlder = FileSys().FileIsOlderThan(RccFileBuild_, QrcFile_, &error);
+      isOlder = FileSys().FileIsOlderThan(RccFileOutput_, QrcFile_, &error);
       if (!error.empty()) {
         Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
         Error_ = true;
@@ -343,7 +363,7 @@ bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
     if (isOlder) {
       if (Log().Verbose()) {
         std::string reason = "Generating ";
-        reason += Quoted(RccFileBuild_);
+        reason += Quoted(RccFileOutput_);
         reason += " because it is older than ";
         reason += Quoted(QrcFile_);
         Log().Info(GeneratorT::RCC, reason);
@@ -437,10 +457,10 @@ bool cmQtAutoGeneratorRcc::TestResources()
         break;
       }
       // Check if the resource file is newer than the build file
-      if (FileSys().FileIsOlderThan(RccFileBuild_, resFile, &error)) {
+      if (FileSys().FileIsOlderThan(RccFileOutput_, resFile, &error)) {
         if (Log().Verbose()) {
           std::string reason = "Generating ";
-          reason += Quoted(RccFileBuild_);
+          reason += Quoted(RccFileOutput_);
           reason += " from ";
           reason += Quoted(QrcFile_);
           reason += " because it is older than ";
@@ -469,7 +489,7 @@ void cmQtAutoGeneratorRcc::TestInfoFile()
     bool isOlder = false;
     {
       std::string error;
-      isOlder = FileSys().FileIsOlderThan(RccFileBuild_, InfoFile(), &error);
+      isOlder = FileSys().FileIsOlderThan(RccFileOutput_, InfoFile(), &error);
       if (!error.empty()) {
         Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
         Error_ = true;
@@ -478,13 +498,13 @@ void cmQtAutoGeneratorRcc::TestInfoFile()
     if (isOlder) {
       if (Log().Verbose()) {
         std::string reason = "Touching ";
-        reason += Quoted(RccFileBuild_);
+        reason += Quoted(RccFileOutput_);
         reason += " because it is older than ";
         reason += Quoted(InfoFile());
         Log().Info(GeneratorT::RCC, reason);
       }
       // Touch build file
-      FileSys().Touch(RccFileBuild_);
+      FileSys().Touch(RccFileOutput_);
       BuildFileChanged_ = true;
     }
   }
@@ -493,7 +513,7 @@ void cmQtAutoGeneratorRcc::TestInfoFile()
 void cmQtAutoGeneratorRcc::GenerateParentDir()
 {
   // Make sure the parent directory exists
-  if (!FileSys().MakeParentDirectory(GeneratorT::RCC, RccFileBuild_)) {
+  if (!FileSys().MakeParentDirectory(GeneratorT::RCC, RccFileOutput_)) {
     Error_ = true;
   }
 }
@@ -521,7 +541,7 @@ bool cmQtAutoGeneratorRcc::GenerateRcc()
           std::string emsg = "The rcc process failed to compile\n  ";
           emsg += Quoted(QrcFile_);
           emsg += "\ninto\n  ";
-          emsg += Quoted(RccFileBuild_);
+          emsg += Quoted(RccFileOutput_);
           if (ProcessResult_.error()) {
             emsg += "\n";
             emsg += ProcessResult_.ErrorMessage;
@@ -529,7 +549,7 @@ bool cmQtAutoGeneratorRcc::GenerateRcc()
           Log().ErrorCommand(GeneratorT::RCC, emsg, Process_->Setup().Command,
                              ProcessResult_.StdOut);
         }
-        FileSys().FileRemove(RccFileBuild_);
+        FileSys().FileRemove(RccFileOutput_);
         Error_ = true;
       }
       // Clean up
@@ -545,7 +565,7 @@ bool cmQtAutoGeneratorRcc::GenerateRcc()
     cmd.push_back(RccExecutable_);
     cmd.insert(cmd.end(), Options_.begin(), Options_.end());
     cmd.push_back("-o");
-    cmd.push_back(RccFileBuild_);
+    cmd.push_back(RccFileOutput_);
     cmd.push_back(QrcFile_);
     // We're done here if the process fails to start
     return !StartProcess(AutogenBuildDir_, cmd, true);
@@ -557,32 +577,34 @@ bool cmQtAutoGeneratorRcc::GenerateRcc()
 void cmQtAutoGeneratorRcc::GenerateWrapper()
 {
   // Generate a wrapper source file on demand
-  if (MultiConfig_ == MultiConfigT::WRAPPER) {
-    // Wrapper file name
-    std::string const& wrapperAbs = RccFile_;
+  if (IsMultiConfig()) {
     // Wrapper file content
-    std::string content = "// This is an autogenerated configuration "
-                          "wrapper file. Changes will be overwritten.\n"
-                          "#include \"";
-    content += cmSystemTools::GetFilenameName(RccFileBuild_);
-    content += "\"\n";
+    std::string content;
+    content += "// This is an autogenerated configuration wrapper file.\n";
+    content += "// Changes will be overwritten.\n";
+    content += "#include <";
+    content += MultiConfigOutput();
+    content += ">\n";
+
     // Write content to file
-    if (FileSys().FileDiffers(wrapperAbs, content)) {
+    if (FileSys().FileDiffers(RccFilePublic_, content)) {
       // Write new wrapper file
       if (Log().Verbose()) {
-        Log().Info(GeneratorT::RCC, "Generating RCC wrapper " + wrapperAbs);
+        Log().Info(GeneratorT::RCC,
+                   "Generating RCC wrapper file " + RccFilePublic_);
       }
-      if (!FileSys().FileWrite(GeneratorT::RCC, wrapperAbs, content)) {
-        Log().ErrorFile(GeneratorT::RCC, wrapperAbs,
+      if (!FileSys().FileWrite(GeneratorT::RCC, RccFilePublic_, content)) {
+        Log().ErrorFile(GeneratorT::RCC, RccFilePublic_,
                         "RCC wrapper file writing failed");
         Error_ = true;
       }
     } else if (BuildFileChanged_) {
       // Just touch the wrapper file
       if (Log().Verbose()) {
-        Log().Info(GeneratorT::RCC, "Touching RCC wrapper " + wrapperAbs);
+        Log().Info(GeneratorT::RCC,
+                   "Touching RCC wrapper file " + RccFilePublic_);
       }
-      FileSys().Touch(wrapperAbs);
+      FileSys().Touch(RccFilePublic_);
     }
   }
 }

+ 10 - 8
Source/cmQtAutoGeneratorRcc.h

@@ -5,7 +5,6 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include "cmQtAutoGen.h"
 #include "cmQtAutoGenerator.h"
 #include "cm_uv.h"
 
@@ -26,7 +25,7 @@ private:
   // -- Types
 
   /// @brief Processing stage
-  enum class StageT
+  enum class StageT : unsigned char
   {
     SETTINGS_READ,
     TEST_QRC_RCC_FILES,
@@ -62,17 +61,18 @@ private:
   void GenerateWrapper();
 
   // -- Utility
+  bool IsMultiConfig() const { return MultiConfig_; }
+  std::string MultiConfigOutput() const;
   bool StartProcess(std::string const& workingDirectory,
                     std::vector<std::string> const& command,
                     bool mergedOutput);
 
 private:
   // -- Config settings
-  bool SettingsChanged_;
-  std::string ConfigSuffix_;
-  MultiConfigT MultiConfig_;
+  bool MultiConfig_;
   // -- Directories
   std::string AutogenBuildDir_;
+  std::string IncludeDir_;
   // -- Qt environment
   std::string RccExecutable_;
   std::vector<std::string> RccListOptions_;
@@ -80,9 +80,10 @@ private:
   std::string QrcFile_;
   std::string QrcFileName_;
   std::string QrcFileDir_;
-  std::string RccFile_;
-  std::string RccFileWrapper_;
-  std::string RccFileBuild_;
+  std::string RccPathChecksum_;
+  std::string RccFileName_;
+  std::string RccFileOutput_;
+  std::string RccFilePublic_;
   std::vector<std::string> Options_;
   std::vector<std::string> Inputs_;
   // -- Subprocess
@@ -91,6 +92,7 @@ private:
   // -- Settings file
   std::string SettingsFile_;
   std::string SettingsString_;
+  bool SettingsChanged_;
   // -- libuv loop
   StageT Stage_;
   bool Error_;