| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567 | /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying   file LICENSE.rst or https://cmake.org/licensing for details.  */#include "cmQtAutoGenInitializer.h"#include <array>#include <cstddef>#include <deque>#include <initializer_list>#include <limits>#include <map>#include <set>#include <sstream> // for basic_ios, istringstream#include <string>#include <unordered_set>#include <utility>#include <vector>#include <cm/algorithm>#include <cm/iterator>#include <cm/memory>#include <cm/string_view>#include <cmext/algorithm>#include <cmext/string_view>#include <cm3p/json/value.h>#include <cm3p/json/writer.h>#include "cmsys/SystemInformation.hxx"#include "cmAlgorithms.h"#include "cmCustomCommand.h"#include "cmCustomCommandLines.h"#include "cmEvaluatedTargetProperty.h"#include "cmGeneratedFileStream.h"#include "cmGeneratorExpression.h"#include "cmGeneratorExpressionDAGChecker.h"#include "cmGeneratorTarget.h"#include "cmGlobalGenerator.h"#include "cmLinkItem.h"#include "cmList.h"#include "cmListFileCache.h"#include "cmLocalGenerator.h"#include "cmMakefile.h"#include "cmMessageType.h"#include "cmPolicies.h"#include "cmQtAutoGen.h"#include "cmQtAutoGenGlobalInitializer.h"#include "cmSourceFile.h"#include "cmSourceFileLocationKind.h"#include "cmSourceGroup.h"#include "cmStandardLevelResolver.h"#include "cmState.h"#include "cmStateTypes.h"#include "cmStringAlgorithms.h"#include "cmSystemTools.h"#include "cmTarget.h"#include "cmValue.h"#include "cmake.h"namespace {unsigned int GetParallelCPUCount(){  static unsigned int count = 0;  // Detect only on the first call  if (count == 0) {    cmsys::SystemInformation info;    info.RunCPUCheck();    count =      cm::clamp(info.GetNumberOfPhysicalCPU(), 1u, cmQtAutoGen::ParallelMax);  }  return count;}std::string FileProjectRelativePath(cmMakefile const* makefile,                                    std::string const& fileName){  std::string res;  {    std::string pSource = cmSystemTools::RelativePath(      makefile->GetCurrentSourceDirectory(), fileName);    std::string pBinary = cmSystemTools::RelativePath(      makefile->GetCurrentBinaryDirectory(), fileName);    if (pSource.size() < pBinary.size()) {      res = std::move(pSource);    } else if (pBinary.size() < fileName.size()) {      res = std::move(pBinary);    } else {      res = fileName;    }  }  return res;}/** * Tests if targetDepend is a STATIC_LIBRARY and if any of its * recursive STATIC_LIBRARY dependencies depends on targetOrigin * (STATIC_LIBRARY cycle). */bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,                        cmGeneratorTarget const* targetDepend,                        std::string const& config){  bool cycle = false;  if ((targetOrigin->GetType() == cmStateEnums::STATIC_LIBRARY) &&      (targetDepend->GetType() == cmStateEnums::STATIC_LIBRARY)) {    std::set<cmGeneratorTarget const*> knownLibs;    std::deque<cmGeneratorTarget const*> testLibs;    // Insert initial static_library dependency    knownLibs.insert(targetDepend);    testLibs.push_back(targetDepend);    while (!testLibs.empty()) {      cmGeneratorTarget const* testTarget = testLibs.front();      testLibs.pop_front();      // Check if the test target is the origin target (cycle)      if (testTarget == targetOrigin) {        cycle = true;        break;      }      // Collect all static_library dependencies from the test target      cmLinkImplementationLibraries const* libs =        testTarget->GetLinkImplementationLibraries(          config, cmGeneratorTarget::UseTo::Link);      if (libs) {        for (cmLinkItem const& item : libs->Libraries) {          cmGeneratorTarget const* depTarget = item.Target;          if (depTarget &&              (depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) &&              knownLibs.insert(depTarget).second) {            testLibs.push_back(depTarget);          }        }      }    }  }  return cycle;}/** Sanitizes file search paths.  */class SearchPathSanitizer{public:  SearchPathSanitizer(cmMakefile* makefile)    : SourcePath_(makefile->GetCurrentSourceDirectory())  {  }  std::vector<std::string> operator()(    std::vector<std::string> const& paths) const;private:  std::string SourcePath_;};std::vector<std::string> SearchPathSanitizer::operator()(  std::vector<std::string> const& paths) const{  std::vector<std::string> res;  res.reserve(paths.size());  for (std::string const& srcPath : paths) {    // Collapse relative paths    std::string path =      cmSystemTools::CollapseFullPath(srcPath, this->SourcePath_);    // Remove suffix slashes    while (cmHasSuffix(path, '/')) {      path.pop_back();    }    // Accept only non empty paths    if (!path.empty()) {      res.emplace_back(std::move(path));    }  }  return res;}/** @brief Writes a CMake info file.  */class InfoWriter{public:  // -- Single value  void Set(std::string const& key, std::string const& value)  {    this->Value_[key] = value;  }  void SetConfig(std::string const& key,                 cmQtAutoGenInitializer::ConfigString const& cfgStr);  void SetBool(std::string const& key, bool value)  {    this->Value_[key] = value;  }  void SetUInt(std::string const& key, unsigned int value)  {    this->Value_[key] = value;  }  // -- Array utility  template <typename CONT>  static bool MakeArray(Json::Value& jval, CONT const& container);  template <typename CONT>  static void MakeStringArray(Json::Value& jval, CONT const& container);  // -- Array value  template <typename CONT>  void SetArray(std::string const& key, CONT const& container);  template <typename CONT>  void SetConfigArray(    std::string const& key,    cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr);  // -- Array of arrays  template <typename CONT, typename FUNC>  void SetArrayArray(std::string const& key, CONT const& container, FUNC func);  // -- Save to json file  bool Save(std::string const& filename);private:  Json::Value Value_;};void InfoWriter::SetConfig(std::string const& key,                           cmQtAutoGenInitializer::ConfigString const& cfgStr){  this->Set(key, cfgStr.Default);  for (auto const& item : cfgStr.Config) {    this->Set(cmStrCat(key, '_', item.first), item.second);  }}template <typename CONT>bool InfoWriter::MakeArray(Json::Value& jval, CONT const& container){  jval = Json::arrayValue;  std::size_t const listSize = cm::size(container);  if (listSize == 0) {    return false;  }  jval.resize(static_cast<unsigned int>(listSize));  return true;}template <typename CONT>void InfoWriter::MakeStringArray(Json::Value& jval, CONT const& container){  if (MakeArray(jval, container)) {    Json::ArrayIndex ii = 0;    for (std::string const& item : container) {      jval[ii++] = item;    }  }}template <typename CONT>void InfoWriter::SetArray(std::string const& key, CONT const& container){  MakeStringArray(this->Value_[key], container);}template <typename CONT, typename FUNC>void InfoWriter::SetArrayArray(std::string const& key, CONT const& container,                               FUNC func){  Json::Value& jval = this->Value_[key];  if (MakeArray(jval, container)) {    Json::ArrayIndex ii = 0;    for (auto const& citem : container) {      Json::Value& aval = jval[ii++];      aval = Json::arrayValue;      func(aval, citem);    }  }}template <typename CONT>void InfoWriter::SetConfigArray(  std::string const& key,  cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr){  this->SetArray(key, cfgStr.Default);  for (auto const& item : cfgStr.Config) {    this->SetArray(cmStrCat(key, '_', item.first), item.second);  }}bool InfoWriter::Save(std::string const& filename){  cmGeneratedFileStream fileStream;  fileStream.SetCopyIfDifferent(true);  fileStream.Open(filename, false, true);  if (!fileStream) {    return false;  }  Json::StyledStreamWriter jsonWriter;  try {    jsonWriter.write(fileStream, this->Value_);  } catch (...) {    return false;  }  return fileStream.Close();}cmQtAutoGen::ConfigStrings<std::vector<std::string>> generateListOptions(  cmQtAutoGen::ConfigStrings<cmQtAutoGen::CompilerFeaturesHandle> const&    executableFeatures,  bool IsMultiConfig){  cmQtAutoGen::ConfigStrings<std::vector<std::string>> tempListOptions;  if (IsMultiConfig) {    for (auto const& executableFeature : executableFeatures.Config) {      tempListOptions.Config[executableFeature.first] =        executableFeature.second->ListOptions;    }  } else {    tempListOptions.Default = executableFeatures.Default->ListOptions;  }  return tempListOptions;}} // End of unnamed namespacecmQtAutoGenInitializer::cmQtAutoGenInitializer(  cmQtAutoGenGlobalInitializer* globalInitializer,  cmGeneratorTarget* genTarget, IntegerVersion qtVersion, bool mocEnabled,  bool uicEnabled, bool rccEnabled, bool globalAutogenTarget,  bool globalAutoRccTarget)  : GlobalInitializer(globalInitializer)  , GenTarget(genTarget)  , GlobalGen(genTarget->GetGlobalGenerator())  , LocalGen(genTarget->GetLocalGenerator())  , Makefile(genTarget->Makefile)  , PathCheckSum(genTarget->Makefile)  , QtVersion(qtVersion){  this->AutogenTarget.GlobalTarget = globalAutogenTarget;  this->Moc.Enabled = mocEnabled;  this->Uic.Enabled = uicEnabled;  this->Rcc.Enabled = rccEnabled;  this->Rcc.GlobalTarget = globalAutoRccTarget;  this->CrossConfig =    !this->Makefile->GetSafeDefinition("CMAKE_CROSS_CONFIGS").empty();  this->UseBetterGraph =    this->GenTarget->GetProperty("AUTOGEN_BETTER_GRAPH_MULTI_CONFIG").IsSet()    ? this->GenTarget->GetProperty("AUTOGEN_BETTER_GRAPH_MULTI_CONFIG").IsOn()    : (this->QtVersion >= IntegerVersion(6, 8));  // AUTOGEN_BETTER_GRAPH_MULTI_CONFIG is set explicitly because it is read by  // the qt library  this->GenTarget->Target->SetProperty("AUTOGEN_BETTER_GRAPH_MULTI_CONFIG",                                       this->UseBetterGraph ? "ON" : "OFF");}void cmQtAutoGenInitializer::AddAutogenExecutableToDependencies(  cmQtAutoGenInitializer::GenVarsT const& genVars,  std::vector<std::string>& dependencies) const{  if (genVars.ExecutableTarget) {    dependencies.push_back(genVars.ExecutableTarget->Target->GetName());  } else if (this->MultiConfig && this->UseBetterGraph) {    cm::string_view const configGenexWithCommandConfig =      "$<COMMAND_CONFIG:$<$<CONFIG:";    cm::string_view const configGenex = "$<$<CONFIG:";    cm::string_view const configGenexEnd = ">";    cm::string_view const configGenexEndWithCommandConfig = ">>";    auto genexBegin =      this->CrossConfig ? configGenexWithCommandConfig : configGenex;    auto genexEnd =      this->CrossConfig ? configGenexEndWithCommandConfig : configGenexEnd;    for (auto const& config : genVars.Executable.Config) {      auto executableWithConfig =        cmStrCat(genexBegin, config.first, ">:", config.second, genexEnd);      dependencies.emplace_back(std::move(executableWithConfig));    }  } else {    if (!genVars.Executable.Default.empty()) {      dependencies.push_back(genVars.Executable.Default);    }  }}bool cmQtAutoGenInitializer::InitCustomTargets(){  // Configurations  this->MultiConfig = this->GlobalGen->IsMultiConfig();  this->ConfigDefault = this->Makefile->GetDefaultConfiguration();  this->ConfigsList =    this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);  // Verbosity  {    std::string const def =      this->Makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");    if (!def.empty()) {      unsigned long iVerb = 0;      if (cmStrToULong(def, &iVerb)) {        // Numeric verbosity        this->Verbosity = static_cast<unsigned int>(iVerb);      } else {        // Non numeric verbosity        if (cmIsOn(def)) {          this->Verbosity = 1;        }      }    }  }  // Targets FOLDER  {    cmValue folder =      this->Makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");    if (!folder) {      folder = this->Makefile->GetState()->GetGlobalProperty(        "AUTOGEN_TARGETS_FOLDER");    }    // Inherit FOLDER property from target (#13688)    if (!folder) {      folder = this->GenTarget->GetProperty("FOLDER");    }    if (folder) {      this->TargetsFolder = *folder;    }  }  // Check status of policy CMP0071 regarding handling of GENERATED files  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0071)) {    case cmPolicies::WARN:      // Ignore GENERATED files but warn      this->CMP0071Warn = true;      CM_FALLTHROUGH;    case cmPolicies::OLD:      // Ignore GENERATED files      break;    case cmPolicies::NEW:      // Process GENERATED files      this->CMP0071Accept = true;      break;  }  // Check status of policy CMP0100 regarding handling of .hh headers  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0100)) {    case cmPolicies::WARN:      // Ignore but .hh files but warn      this->CMP0100Warn = true;      CM_FALLTHROUGH;    case cmPolicies::OLD:      // Ignore .hh files      break;    case cmPolicies::NEW:      // Process .hh file      this->CMP0100Accept = true;      break;  }  // Common directories  std::string relativeBuildDir;  {    // Collapsed current binary directory    std::string const cbd = cmSystemTools::CollapseFullPath(      std::string(), this->Makefile->GetCurrentBinaryDirectory());    std::string infoDir;    std::string buildDir;    auto idirkind = cmStateEnums::IntermediateDirKind::QtAutogenMetadata;    if (this->GenTarget->GetUseShortObjectNames(idirkind)) {      infoDir = cmSystemTools::CollapseFullPath(        std::string(),        cmStrCat(this->GenTarget->GetSupportDirectory(idirkind),                 "/autogen_info"));      buildDir = cmSystemTools::CollapseFullPath(        std::string(),        cmStrCat(this->GenTarget->GetSupportDirectory(idirkind), "/autogen"));    } else {      infoDir = cmStrCat(cbd, "/CMakeFiles/", this->GenTarget->GetName(),                         "_autogen.dir");      buildDir = cmStrCat(cbd, '/', this->GenTarget->GetName(), "_autogen");    }    // Info directory    this->Dir.Info = infoDir;    cmSystemTools::ConvertToUnixSlashes(this->Dir.Info);    // Build directory    this->Dir.Build = this->GenTarget->GetSafeProperty("AUTOGEN_BUILD_DIR");    if (this->Dir.Build.empty()) {      this->Dir.Build = buildDir;    }    cmSystemTools::ConvertToUnixSlashes(this->Dir.Build);    this->Dir.RelativeBuild =      cmSystemTools::RelativePath(cbd, this->Dir.Build);    // Cleanup build directory    this->AddCleanFile(this->Dir.Build);    // Working directory    this->Dir.Work = cbd;    cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);    // Include directory    this->ConfigFileNamesAndGenex(this->Dir.Include, this->Dir.IncludeGenExp,                                  cmStrCat(this->Dir.Build, "/include"), "");  }  // Moc, Uic and _autogen target settings  if (this->MocOrUicEnabled()) {    // Init moc specific settings    if (this->Moc.Enabled && !this->InitMoc()) {      return false;    }    // Init uic specific settings    if (this->Uic.Enabled && !this->InitUic()) {      return false;    }    // Autogen target name    this->AutogenTarget.Name =      cmStrCat(this->GenTarget->GetName(), "_autogen");    // Autogen target parallel processing    {      using ParallelType = decltype(this->AutogenTarget.Parallel);      unsigned long propInt = 0;      std::string const& prop =        this->GenTarget->GetSafeProperty("AUTOGEN_PARALLEL");      if (prop.empty() || (prop == "AUTO")) {        // Autodetect number of CPUs        this->AutogenTarget.Parallel = GetParallelCPUCount();      } else if (cmStrToULong(prop, &propInt) && propInt > 0 &&                 propInt <= std::numeric_limits<ParallelType>::max()) {        this->AutogenTarget.Parallel = static_cast<ParallelType>(propInt);      } else {        // Warn the project author that AUTOGEN_PARALLEL is not valid.        this->Makefile->IssueMessage(          MessageType::AUTHOR_WARNING,          cmStrCat("AUTOGEN_PARALLEL=\"", prop, "\" for target \"",                   this->GenTarget->GetName(),                   "\" is not valid. Using AUTOGEN_PARALLEL=1"));        this->AutogenTarget.Parallel = 1;      }    }#ifdef _WIN32    {      auto const& value =        this->GenTarget->GetProperty("AUTOGEN_COMMAND_LINE_LENGTH_MAX");      if (value.IsSet()) {        using maxCommandLineLengthType =          decltype(this->AutogenTarget.MaxCommandLineLength);        unsigned long propInt = 0;        if (cmStrToULong(value, &propInt) && propInt > 0 &&            propInt <= std::numeric_limits<maxCommandLineLengthType>::max()) {          this->AutogenTarget.MaxCommandLineLength =            static_cast<maxCommandLineLengthType>(propInt);        } else {          // Warn the project author that AUTOGEN_PARALLEL is not valid.          this->Makefile->IssueMessage(            MessageType::AUTHOR_WARNING,            cmStrCat("AUTOGEN_COMMAND_LINE_LENGTH_MAX=\"", *value,                     "\" for target \"", this->GenTarget->GetName(),                     "\" is not valid. Using no limit for "                     "AUTOGEN_COMMAND_LINE_LENGTH_MAX"));          this->AutogenTarget.MaxCommandLineLength =            std::numeric_limits<maxCommandLineLengthType>::max();        }      } else {        // Actually 32767 (see        // https://devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553) but        // we allow for a small margin        this->AutogenTarget.MaxCommandLineLength = 32000;      }    }#endif    // Autogen target info and settings files    {      // Info file      this->AutogenTarget.InfoFile =        cmStrCat(this->Dir.Info, "/AutogenInfo.json");      // Used settings file      this->ConfigFileNames(this->AutogenTarget.SettingsFile,                            cmStrCat(this->Dir.Info, "/AutogenUsed"), ".txt");      this->ConfigFileClean(this->AutogenTarget.SettingsFile);      // Parse cache file      this->ConfigFileNames(this->AutogenTarget.ParseCacheFile,                            cmStrCat(this->Dir.Info, "/ParseCache"), ".txt");      this->ConfigFileClean(this->AutogenTarget.ParseCacheFile);    }    // Autogen target: Compute user defined dependencies    {      this->AutogenTarget.DependOrigin =        this->GenTarget->GetPropertyAsBool("AUTOGEN_ORIGIN_DEPENDS");      std::string const& deps =        this->GenTarget->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");      if (!deps.empty()) {        for (auto const& depName : cmList{ deps }) {          // Allow target and file dependencies          auto* depTarget = this->Makefile->FindTargetToUse(depName);          if (depTarget) {            this->AutogenTarget.DependTargets.insert(depTarget);          } else {            this->AutogenTarget.DependFiles.insert(depName);          }        }      }    }    if (this->Moc.Enabled) {      // Path prefix      if (this->GenTarget->GetProperty("AUTOMOC_PATH_PREFIX").IsOn()) {        this->Moc.PathPrefix = true;      }      // CMAKE_AUTOMOC_RELAXED_MODE      if (this->Makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE")) {        this->Moc.RelaxedMode = true;        this->Makefile->IssueMessage(          MessageType::AUTHOR_WARNING,          cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is "                   "deprecated an will be removed in the future.  Consider "                   "disabling it and converting the target ",                   this->GenTarget->GetName(), " to regular mode."));      }      // Options      cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MOC_OPTIONS"),                   this->Moc.Options);      // Filters      cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"),                   this->Moc.MacroNames);      this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames),                                 this->Moc.MacroNames.end());      {        cmList const filterList = { this->GenTarget->GetSafeProperty(          "AUTOMOC_DEPEND_FILTERS") };        if ((filterList.size() % 2) != 0) {          cmSystemTools::Error(            cmStrCat("AutoMoc: AUTOMOC_DEPEND_FILTERS predefs size ",                     filterList.size(), " is not a multiple of 2."));          return false;        }        this->Moc.DependFilters.reserve(1 + (filterList.size() / 2));        this->Moc.DependFilters.emplace_back(          "Q_PLUGIN_METADATA",          "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("          "[^\\)]*FILE[ \t]*\"([^\"]+)\"");        for (cmList::size_type ii = 0; ii != filterList.size(); ii += 2) {          this->Moc.DependFilters.emplace_back(filterList[ii],                                               filterList[ii + 1]);        }      }    }  }  // Init rcc specific settings  if (this->Rcc.Enabled && !this->InitRcc()) {    return false;  }  // Add autogen include directory to the origin target INCLUDE_DIRECTORIES  if (this->MocOrUicEnabled() || (this->Rcc.Enabled && this->MultiConfig)) {    auto addBefore = false;    auto const& value =      this->GenTarget->GetProperty("AUTOGEN_USE_SYSTEM_INCLUDE");    if (value.IsSet()) {      if (value.IsOn()) {        this->GenTarget->AddSystemIncludeDirectory(this->Dir.IncludeGenExp,                                                   "CXX");      } else {        addBefore = true;      }    } else {      switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0151)) {        case cmPolicies::WARN:        case cmPolicies::OLD:          addBefore = true;          break;        case cmPolicies::NEW:          this->GenTarget->AddSystemIncludeDirectory(this->Dir.IncludeGenExp,                                                     "CXX");          break;      }    }    this->GenTarget->AddIncludeDirectory(this->Dir.IncludeGenExp, addBefore);  }  // Scan files  if (!this->InitScanFiles()) {    return false;  }  // Create autogen target  if (this->MocOrUicEnabled() && !this->InitAutogenTarget()) {    return false;  }  // Create rcc targets  if (this->Rcc.Enabled && !this->InitRccTargets()) {    return false;  }  return true;}bool cmQtAutoGenInitializer::InitMoc(){  // Mocs compilation file  if (this->GlobalGen->IsXcode()) {    // XXX(xcode-per-cfg-src): Drop this Xcode-specific code path    // when the Xcode generator supports per-config sources.    this->Moc.CompilationFile.Default =      cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");    this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default;  } else {    this->ConfigFileNamesAndGenex(      this->Moc.CompilationFile, this->Moc.CompilationFileGenex,      cmStrCat(this->Dir.Build, "/mocs_compilation"_s), ".cpp"_s);  }  // Moc predefs  if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&      (this->QtVersion >= IntegerVersion(5, 8))) {    // Command    cmList::assign(      this->Moc.PredefsCmd,      this->Makefile->GetDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));    // Header    if (!this->Moc.PredefsCmd.empty()) {      this->ConfigFileNames(this->Moc.PredefsFile,                            cmStrCat(this->Dir.Build, "/moc_predefs"), ".h");    }  }  // Moc includes  {    // If the property AUTOMOC_INCLUDE_DIRECTORIES is set on the target,    // use its value for moc include paths instead of gathering all    // include directories from the target.    cmValue autoIncDirs =      this->GenTarget->GetProperty("AUTOMOC_INCLUDE_DIRECTORIES");    if (autoIncDirs) {      cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();      cmGeneratorExpression ge(*this->Makefile->GetCMakeInstance(), lfbt);      auto cge = ge.Parse(*autoIncDirs);      // Build a single list of configs to iterate, whether single or multi      std::vector<std::string> configs = this->MultiConfig        ? this->ConfigsList        : std::vector<std::string>{ this->ConfigDefault };      for (auto const& cfg : configs) {        std::string eval = cge->Evaluate(this->LocalGen, cfg);        std::vector<std::string> incList = cmList(eval);        // Validate absolute paths        for (auto const& path : incList) {          if (!cmGeneratorExpression::StartsWithGeneratorExpression(path) &&              !cmSystemTools::FileIsFullPath(path)) {            this->Makefile->IssueMessage(              MessageType::FATAL_ERROR,              cmStrCat("AUTOMOC_INCLUDE_DIRECTORIES: path '", path,                       "' is not absolute."));            return false;          }        }        if (this->MultiConfig) {          this->Moc.Includes.Config[cfg] = std::move(incList);        } else {          this->Moc.Includes.Default = std::move(incList);        }      }    } else {      // Otherwise, discover include directories from the target for moc.      SearchPathSanitizer const sanitizer(this->Makefile);      auto getDirs = [this, &sanitizer](                       std::string const& cfg) -> std::vector<std::string> {        // Get the include dirs for this target, without stripping the implicit        // include dirs off, see issue #13667.        std::vector<std::string> dirs;        bool const appendImplicit = (this->QtVersion.Major >= 5);        this->LocalGen->GetIncludeDirectoriesImplicit(          dirs, this->GenTarget, "CXX", cfg, false, appendImplicit);        return sanitizer(dirs);      };      // Other configuration settings      if (this->MultiConfig) {        for (std::string const& cfg : this->ConfigsList) {          std::vector<std::string> dirs = getDirs(cfg);          if (dirs == this->Moc.Includes.Default) {            continue;          }          this->Moc.Includes.Config[cfg] = std::move(dirs);        }      } else {        // Default configuration include directories        this->Moc.Includes.Default = getDirs(this->ConfigDefault);      }    }  }  // Moc compile definitions  {    auto getDefs = [this](std::string const& cfg) -> std::set<std::string> {      std::set<std::string> defines;      this->LocalGen->GetTargetDefines(this->GenTarget, cfg, "CXX", defines);      if (this->Moc.PredefsCmd.empty() &&          this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") ==            "Windows") {        // Add WIN32 definition if we don't have a moc_predefs.h        defines.insert("WIN32");      }      return defines;    };    // Other configuration defines    if (this->MultiConfig) {      for (std::string const& cfg : this->ConfigsList) {        std::set<std::string> defines = getDefs(cfg);        if (defines == this->Moc.Defines.Default) {          continue;        }        this->Moc.Defines.Config[cfg] = std::move(defines);      }    } else {      // Default configuration defines      this->Moc.Defines.Default = getDefs(this->ConfigDefault);    }  }  // Moc executable  {    if (!this->GetQtExecutable(this->Moc, "moc", false)) {      return false;    }    // Let the _autogen target depend on the moc executable    if (this->Moc.ExecutableTarget) {      this->AutogenTarget.DependTargets.insert(        this->Moc.ExecutableTarget->Target);    }  }  return true;}bool cmQtAutoGenInitializer::InitUic(){  // Uic search paths  {    std::string const& usp =      this->GenTarget->GetSafeProperty("AUTOUIC_SEARCH_PATHS");    if (!usp.empty()) {      this->Uic.SearchPaths =        SearchPathSanitizer(this->Makefile)(cmList{ usp });    }  }  // Uic target options  {    auto getOpts = [this](std::string const& cfg) -> std::vector<std::string> {      std::vector<std::string> opts;      this->GenTarget->GetAutoUicOptions(opts, cfg);      return opts;    };    // Default options    this->Uic.Options.Default = getOpts(this->ConfigDefault);    // Configuration specific options    if (this->MultiConfig) {      for (std::string const& cfg : this->ConfigsList) {        std::vector<std::string> options = getOpts(cfg);        if (options == this->Uic.Options.Default) {          continue;        }        this->Uic.Options.Config[cfg] = std::move(options);      }    }  }  // Uic executable  {    if (!this->GetQtExecutable(this->Uic, "uic", true)) {      return false;    }    // Let the _autogen target depend on the uic executable    if (this->Uic.ExecutableTarget) {      this->AutogenTarget.DependTargets.insert(        this->Uic.ExecutableTarget->Target);    }  }  return true;}bool cmQtAutoGenInitializer::InitRcc(){  // Rcc executable  {    if (!this->GetQtExecutable(this->Rcc, "rcc", false)) {      return false;    }    // Evaluate test output on demand    auto& features = this->Rcc.ExecutableFeatures;    auto checkAndAddOptions = [this](CompilerFeaturesHandle& feature) {      if (!feature->Evaluated) {        // Look for list options        if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) {          static std::array<std::string, 2> const listOptions{ { "--list",                                                                 "-list" } };          for (std::string const& opt : listOptions) {            if (feature->HelpOutput.find(opt) != std::string::npos) {              feature->ListOptions.emplace_back(opt);              break;            }          }        }        // Evaluation finished        feature->Evaluated = true;      }    };    if (this->MultiConfig && this->UseBetterGraph) {      for (auto const& config : this->ConfigsList) {        checkAndAddOptions(features.Config[config]);      }    } else {      checkAndAddOptions(features.Default);    }  }  // Disable zstd if it is not supported  {    std::string const qtFeatureZSTD = "QT_FEATURE_zstd";    if (this->GenTarget->Target->GetMakefile()->IsDefinitionSet(          qtFeatureZSTD)) {      auto const zstdDef =        this->GenTarget->Target->GetMakefile()->GetSafeDefinition(          qtFeatureZSTD);      auto const zstdVal = cmValue(zstdDef);      if (zstdVal.IsOff()) {        auto const& kw = this->GlobalInitializer->kw();        auto rccOptions = this->GenTarget->GetSafeProperty(kw.AUTORCC_OPTIONS);        std::string const nozstd = "--no-zstd";        if (rccOptions.find(nozstd) == std::string::npos) {          rccOptions.append(";" + nozstd + ";");        }        this->GenTarget->Target->SetProperty(kw.AUTORCC_OPTIONS, rccOptions);      }    }  }  return true;}bool cmQtAutoGenInitializer::InitScanFiles(){  cmake const* cm = this->Makefile->GetCMakeInstance();  auto const& kw = this->GlobalInitializer->kw();  auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath,                                std::vector<size_t> const& configs,                                bool muIt) -> MUFileHandle {    MUFileHandle muf = cm::make_unique<MUFile>();    muf->FullPath = fullPath;    muf->SF = sf;    if (!configs.empty() && configs.size() != this->ConfigsList.size()) {      muf->Configs = configs;    }    muf->Generated = sf->GetIsGenerated();    bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);    muf->SkipMoc = this->Moc.Enabled &&      (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOMOC));    muf->SkipUic = this->Uic.Enabled &&      (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));    if (muIt) {      muf->MocIt = this->Moc.Enabled && !muf->SkipMoc;      muf->UicIt = this->Uic.Enabled && !muf->SkipUic;    }    return muf;  };  auto addMUHeader = [this](MUFileHandle&& muf, cm::string_view extension) {    cmSourceFile* sf = muf->SF;    bool const muIt = (muf->MocIt || muf->UicIt);    if (this->CMP0100Accept || (extension != "hh")) {      // Accept      if (muIt && muf->Generated) {        this->AutogenTarget.FilesGenerated.emplace_back(muf.get());      }      this->AutogenTarget.Headers.emplace(sf, std::move(muf));    } else if (muIt && this->CMP0100Warn) {      // Store file for warning message      this->AutogenTarget.CMP0100HeadersWarn.push_back(sf);    }  };  auto addMUSource = [this](MUFileHandle&& muf) {    if ((muf->MocIt || muf->UicIt) && muf->Generated) {      this->AutogenTarget.FilesGenerated.emplace_back(muf.get());    }    this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf));  };  // Scan through target files  {    // Scan through target files    for (cmGeneratorTarget::AllConfigSource const& acs :         this->GenTarget->GetAllConfigSources()) {      std::string const& fullPath = acs.Source->GetFullPath();      std::string const& extLower =        cmSystemTools::LowerCase(acs.Source->GetExtension());      // Register files that will be scanned by moc or uic      if (this->MocOrUicEnabled()) {        if (cm->IsAHeaderExtension(extLower)) {          addMUHeader(makeMUFile(acs.Source, fullPath, acs.Configs, true),                      extLower);        } else if (cm->IsACLikeSourceExtension(extLower)) {          addMUSource(makeMUFile(acs.Source, fullPath, acs.Configs, true));        }      }      // Register rcc enabled files      if (this->Rcc.Enabled) {        if ((extLower == kw.qrc) &&            !acs.Source->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&            !acs.Source->GetPropertyAsBool(kw.SKIP_AUTORCC)) {          // Register qrc file          Qrc qrc;          qrc.QrcFile = fullPath;          qrc.QrcName =            cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);          qrc.Generated = acs.Source->GetIsGenerated();          // RCC options          {            std::string const& opts =              acs.Source->GetSafeProperty(kw.AUTORCC_OPTIONS);            if (!opts.empty()) {              cmExpandList(opts, qrc.Options);            }          }          this->Rcc.Qrcs.push_back(std::move(qrc));        }      }    }  }  // cmGeneratorTarget::GetAllConfigSources computes the target's  // sources meta data cache. Clear it so that OBJECT library targets that  // are AUTOGEN initialized after this target get their added  // mocs_compilation.cpp source acknowledged by this target.  this->GenTarget->ClearSourcesCache();  // For source files find additional headers and private headers  if (this->MocOrUicEnabled()) {    // Header search suffixes and extensions    static std::initializer_list<cm::string_view> const suffixes{ "", "_p" };    auto const& exts = cm->GetHeaderExtensions();    // Scan through sources    for (auto const& pair : this->AutogenTarget.Sources) {      MUFile const& muf = *pair.second;      if (muf.MocIt || muf.UicIt) {        // Search for the default header file and a private header        std::string const& srcFullPath = muf.SF->ResolveFullPath();        std::string const basePath = cmStrCat(          cmQtAutoGen::SubDirPrefix(srcFullPath),          cmSystemTools::GetFilenameWithoutLastExtension(srcFullPath));        for (auto const& suffix : suffixes) {          std::string const suffixedPath = cmStrCat(basePath, suffix);          for (auto const& ext : exts) {            std::string const fullPath = cmStrCat(suffixedPath, '.', ext);            auto constexpr locationKind = cmSourceFileLocationKind::Known;            cmSourceFile* sf =              this->Makefile->GetSource(fullPath, locationKind);            if (sf) {              // Check if we know about this header already              if (cm::contains(this->AutogenTarget.Headers, sf)) {                continue;              }              // We only accept not-GENERATED files that do exist.              if (!sf->GetIsGenerated() &&                  !cmSystemTools::FileExists(fullPath)) {                continue;              }            } else if (cmSystemTools::FileExists(fullPath)) {              // Create a new source file for the existing file              sf = this->Makefile->CreateSource(fullPath, false, locationKind);            }            if (sf) {              auto eMuf = makeMUFile(sf, fullPath, muf.Configs, true);              // Only process moc/uic when the parent is processed as well              if (!muf.MocIt) {                eMuf->MocIt = false;              }              if (!muf.UicIt) {                eMuf->UicIt = false;              }              addMUHeader(std::move(eMuf), ext);            }          }        }      }    }  }  // Scan through all source files in the makefile to extract moc and uic  // parameters.  Historically we support non target source file parameters.  // The reason is that their file names might be discovered from source files  // at generation time.  if (this->MocOrUicEnabled()) {    for (auto const& sf : this->Makefile->GetSourceFiles()) {      // sf->GetExtension() is only valid after sf->ResolveFullPath() ...      // 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 pathError;      std::string const& fullPath = sf->ResolveFullPath(&pathError);      if (!pathError.empty() || fullPath.empty()) {        continue;      }      std::string const& extLower =        cmSystemTools::LowerCase(sf->GetExtension());      if (cm->IsAHeaderExtension(extLower)) {        if (!cm::contains(this->AutogenTarget.Headers, sf.get())) {          auto muf = makeMUFile(sf.get(), fullPath, {}, false);          if (muf->SkipMoc || muf->SkipUic) {            addMUHeader(std::move(muf), extLower);          }        }      } else if (cm->IsACLikeSourceExtension(extLower)) {        if (!cm::contains(this->AutogenTarget.Sources, sf.get())) {          auto muf = makeMUFile(sf.get(), fullPath, {}, false);          if (muf->SkipMoc || muf->SkipUic) {            addMUSource(std::move(muf));          }        }      } else if (this->Uic.Enabled && (extLower == kw.ui)) {        // .ui file        bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);        bool const skipUic =          (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));        if (!skipUic) {          // Check if the .ui file has uic options          std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);          if (uicOpts.empty()) {            this->Uic.UiFilesNoOptions.emplace_back(fullPath);          } else {            this->Uic.UiFilesWithOptions.emplace_back(              fullPath, std::move(cmList{ uicOpts }.data()));          }          auto uiHeaderRelativePath = cmSystemTools::RelativePath(            this->LocalGen->GetCurrentSourceDirectory(),            cmSystemTools::GetFilenamePath(fullPath));          // Avoid creating a path containing adjacent slashes          if (!uiHeaderRelativePath.empty() &&              uiHeaderRelativePath.back() != '/') {            uiHeaderRelativePath += '/';          }          auto uiHeaderFilePath = cmStrCat(            '/', uiHeaderRelativePath, "ui_"_s,            cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s);          ConfigString uiHeader;          std::string uiHeaderGenex;          this->ConfigFileNamesAndGenex(            uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s),            uiHeaderFilePath);          this->Uic.UiHeaders.emplace_back(uiHeader, uiHeaderGenex);        } else {          // Register skipped .ui file          this->Uic.SkipUi.insert(fullPath);        }      }    }  }  // Process GENERATED sources and headers  if (this->MocOrUicEnabled() && !this->AutogenTarget.FilesGenerated.empty()) {    if (this->CMP0071Accept) {      // Let the autogen target depend on the GENERATED files      if (this->MultiConfig && !this->CrossConfig) {        for (MUFile const* muf : this->AutogenTarget.FilesGenerated) {          if (muf->Configs.empty()) {            this->AutogenTarget.DependFiles.insert(muf->FullPath);          } else {            for (size_t ci : muf->Configs) {              std::string const& config = this->ConfigsList[ci];              std::string const& pathWithConfig =                cmStrCat("$<$<CONFIG:", config, ">:", muf->FullPath, '>');              this->AutogenTarget.DependFiles.insert(pathWithConfig);            }          }        }      } else {        for (MUFile const* muf : this->AutogenTarget.FilesGenerated) {          this->AutogenTarget.DependFiles.insert(muf->FullPath);        }      }    } else if (this->CMP0071Warn) {      cm::string_view property;      if (this->Moc.Enabled && this->Uic.Enabled) {        property = "SKIP_AUTOGEN";      } else if (this->Moc.Enabled) {        property = "SKIP_AUTOMOC";      } else if (this->Uic.Enabled) {        property = "SKIP_AUTOUIC";      }      std::string files;      for (MUFile const* muf : this->AutogenTarget.FilesGenerated) {        files += cmStrCat("  ", Quoted(muf->FullPath), '\n');      }      this->Makefile->IssueMessage(        MessageType::AUTHOR_WARNING,        cmStrCat(          cmPolicies::GetPolicyWarning(cmPolicies::CMP0071),          "\n"          "For compatibility, CMake is excluding the GENERATED source "          "file(s):\n",          files, "from processing by ",          cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false),          ".  If any of the files should be processed, set CMP0071 to NEW.  "          "If any of the files should not be processed, "          "explicitly exclude them by setting the source file property ",          property, ":\n  set_property(SOURCE file.h PROPERTY ", property,          " ON)\n"));    }  }  // Generate CMP0100 warning  if (this->MocOrUicEnabled() &&      !this->AutogenTarget.CMP0100HeadersWarn.empty()) {    cm::string_view property;    if (this->Moc.Enabled && this->Uic.Enabled) {      property = "SKIP_AUTOGEN";    } else if (this->Moc.Enabled) {      property = "SKIP_AUTOMOC";    } else if (this->Uic.Enabled) {      property = "SKIP_AUTOUIC";    }    std::string files;    for (cmSourceFile const* sf : this->AutogenTarget.CMP0100HeadersWarn) {      files += cmStrCat("  ", Quoted(sf->GetFullPath()), '\n');    }    this->Makefile->IssueMessage(      MessageType::AUTHOR_WARNING,      cmStrCat(        cmPolicies::GetPolicyWarning(cmPolicies::CMP0100),        "\n"        "For compatibility, CMake is excluding the header file(s):\n",        files, "from processing by ",        cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false),        ".  If any of the files should be processed, set CMP0100 to NEW.  "        "If any of the files should not be processed, "        "explicitly exclude them by setting the source file property ",        property, ":\n  set_property(SOURCE file.hh PROPERTY ", property,        " ON)\n"));  }  // Process qrc files  if (!this->Rcc.Qrcs.empty()) {    bool const modernQt = (this->QtVersion.Major >= 5);    // Target rcc options    cmList const optionsTarget{ this->GenTarget->GetSafeProperty(      kw.AUTORCC_OPTIONS) };    // Check if file name is unique    for (Qrc& qrc : this->Rcc.Qrcs) {      qrc.Unique = true;      for (Qrc const& qrc2 : this->Rcc.Qrcs) {        if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) {          qrc.Unique = false;          break;        }      }    }    // Path checksum and file names    for (Qrc& qrc : this->Rcc.Qrcs) {      // Path checksum      qrc.QrcPathChecksum = this->PathCheckSum.getPart(qrc.QrcFile);      // Output file name      if (this->MultiConfig && !this->GlobalGen->IsXcode() &&          this->UseBetterGraph) {        qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,                                  "_$<CONFIG>/qrc_", qrc.QrcName, ".cpp");      } else {        qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,                                  "/qrc_", qrc.QrcName, ".cpp");      }      std::string const base = cmStrCat(this->Dir.Info, "/AutoRcc_",                                        qrc.QrcName, '_', qrc.QrcPathChecksum);      qrc.LockFile = cmStrCat(base, "_Lock.lock");      qrc.InfoFile = cmStrCat(base, "_Info.json");      this->ConfigFileNames(qrc.SettingsFile, cmStrCat(base, "_Used"), ".txt");    }    // rcc options    for (Qrc& qrc : this->Rcc.Qrcs) {      // Target options      std::vector<std::string> opts = optionsTarget;      // Merge computed "-name XYZ" option      {        std::string name = qrc.QrcName;        // Replace '-' with '_'. The former is not valid for symbol names.        std::replace(name.begin(), name.end(), '-', '_');        if (!qrc.Unique) {          name += cmStrCat('_', qrc.QrcPathChecksum);        }        std::vector<std::string> nameOpts;        nameOpts.emplace_back("-name");        nameOpts.emplace_back(std::move(name));        RccMergeOptions(opts, nameOpts, modernQt);      }      // Merge file option      RccMergeOptions(opts, qrc.Options, modernQt);      qrc.Options = std::move(opts);    }    // rcc resources    for (Qrc& qrc : this->Rcc.Qrcs) {      if (!qrc.Generated) {        std::string error;        if (this->MultiConfig && this->UseBetterGraph) {          for (auto const& config : this->ConfigsList) {            RccLister const lister(              this->Rcc.Executable.Config[config],              this->Rcc.ExecutableFeatures.Config[config]->ListOptions);            if (!lister.list(qrc.QrcFile, qrc.Resources.Config[config],                             error)) {              cmSystemTools::Error(error);              return false;            }          }        } else {          RccLister const lister(            this->Rcc.Executable.Default,            this->Rcc.ExecutableFeatures.Default->ListOptions);          if (!lister.list(qrc.QrcFile, qrc.Resources.Default, error)) {            cmSystemTools::Error(error);            return false;          }        }      }    }  }  return true;}bool cmQtAutoGenInitializer::InitAutogenTarget(){  // Register info file as generated by CMake  this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile);  // Determine whether to use a depfile for the AUTOGEN target.  bool const useDepfile = [this]() -> bool {    auto const& gen = this->GlobalGen->GetName();    return this->QtVersion >= IntegerVersion(5, 15) &&      (gen.find("Ninja") != std::string::npos ||       gen.find("Make") != std::string::npos);  }();  // Files provided by the autogen target  std::vector<std::string> autogenByproducts;  std::vector<std::string> timestampByproducts;  if (this->Moc.Enabled) {    this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true);    if (useDepfile) {      if (this->CrossConfig &&          this->GlobalGen->GetName().find("Ninja") != std::string::npos &&          !this->UseBetterGraph) {        // Make all mocs_compilation_<CONFIG>.cpp files byproducts of the        // ${target}_autogen/timestamp custom command.        // We cannot just use Moc.CompilationFileGenex here, because that        // custom command runs cmake_autogen for each configuration.        for (auto const& p : this->Moc.CompilationFile.Config) {          timestampByproducts.push_back(p.second);        }      } else {        timestampByproducts.push_back(this->Moc.CompilationFileGenex);      }    } else {      autogenByproducts.push_back(this->Moc.CompilationFileGenex);    }  }  if (this->Uic.Enabled) {    for (auto const& file : this->Uic.UiHeaders) {      this->AddGeneratedSource(file.first, this->Uic);      autogenByproducts.push_back(file.second);    }  }  // Compose target comment  std::string autogenComment;  {    std::string tools;    if (this->Moc.Enabled) {      tools += "MOC";    }    if (this->Uic.Enabled) {      if (!tools.empty()) {        tools += " and ";      }      tools += "UIC";    }    autogenComment = cmStrCat("Automatic ", tools, " for target ",                              this->GenTarget->GetName());  }  // Compose command lines  // FIXME: Take advantage of our per-config mocs_compilation_$<CONFIG>.cpp  // instead of fiddling with the include directories  bool constexpr stdPipesUTF8 = true;  cmCustomCommandLines commandLines;  AddCMakeProcessToCommandLines(this->AutogenTarget.InfoFile, "cmake_autogen",                                commandLines);  // Use PRE_BUILD on demand  bool usePRE_BUILD = false;  if (this->GlobalGen->GetName().find("Visual Studio") != std::string::npos) {    // Under VS use a PRE_BUILD event instead of a separate target to    // reduce the number of targets loaded into the IDE.    // This also works around a VS 11 bug that may skip updating the target:    //  https://connect.microsoft.com/VisualStudio/feedback/details/769495    usePRE_BUILD = true;  }  // Disable PRE_BUILD in some cases  if (usePRE_BUILD) {    // Cannot use PRE_BUILD with file depends    if (!this->AutogenTarget.DependFiles.empty()) {      usePRE_BUILD = false;    }    // Cannot use PRE_BUILD when a global autogen target is in place    if (this->AutogenTarget.GlobalTarget) {      usePRE_BUILD = false;    }  }  // Create the autogen target/command  if (usePRE_BUILD) {    // Add additional autogen target dependencies to origin target    for (cmTarget const* depTarget : this->AutogenTarget.DependTargets) {      this->GenTarget->Target->AddUtility(depTarget->GetName(), false,                                          this->Makefile);    }    if (!this->Uic.UiFilesNoOptions.empty() ||        !this->Uic.UiFilesWithOptions.empty()) {      // Add a generated timestamp file      ConfigString timestampFile;      std::string timestampFileGenex;      ConfigFileNamesAndGenex(timestampFile, timestampFileGenex,                              cmStrCat(this->Dir.Build, "/autouic"_s),                              ".stamp"_s);      this->AddGeneratedSource(timestampFile, this->Uic);      // Add a step in the pre-build command to touch the timestamp file      commandLines.push_back(        cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", "touch",                            timestampFileGenex }));      // UIC needs to be re-run if any of the known UI files change or the      // executable itself has been updated      auto uicDependencies = this->Uic.UiFilesNoOptions;      for (auto const& uiFile : this->Uic.UiFilesWithOptions) {        uicDependencies.push_back(uiFile.first);      }      AddAutogenExecutableToDependencies(this->Uic, uicDependencies);      // Add a rule file to cause the target to build if a dependency has      // changed, which will trigger the pre-build command to run autogen      auto cc = cm::make_unique<cmCustomCommand>();      cc->SetOutputs(timestampFileGenex);      cc->SetDepends(uicDependencies);      cc->SetComment("");      cc->SetWorkingDirectory(this->Dir.Work.c_str());      cc->SetEscapeOldStyle(false);      cc->SetStdPipesUTF8(stdPipesUTF8);      this->LocalGen->AddCustomCommandToOutput(std::move(cc));    }    // Add the pre-build command directly to bypass the OBJECT_LIBRARY    // rejection in cmMakefile::AddCustomCommandToTarget because we know    // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.    //    // PRE_BUILD does not support file dependencies!    cmCustomCommand cc;    cc.SetByproducts(autogenByproducts);    cc.SetCommandLines(commandLines);    cc.SetComment(autogenComment.c_str());    cc.SetBacktrace(this->Makefile->GetBacktrace());    cc.SetWorkingDirectory(this->Dir.Work.c_str());    cc.SetStdPipesUTF8(stdPipesUTF8);    cc.SetEscapeOldStyle(false);    cc.SetEscapeAllowMakeVars(true);    this->GenTarget->Target->AddPreBuildCommand(std::move(cc));  } else {    // Add link library target dependencies to the autogen target    // dependencies    if (this->AutogenTarget.DependOrigin) {      // add_dependencies/addUtility do not support generator expressions.      // We depend only on the libraries found in all configs therefore.      std::map<cmGeneratorTarget const*, std::size_t> targetsPartOfAllConfigs;      for (std::string const& config : this->ConfigsList) {        // The same target might appear multiple times in a config, but we        // should only count it once.        std::set<cmGeneratorTarget const*> seenTargets;        cmLinkImplementationLibraries const* libs =          this->GenTarget->GetLinkImplementationLibraries(            config, cmGeneratorTarget::UseTo::Link);        if (libs) {          for (cmLinkItem const& item : libs->Libraries) {            cmGeneratorTarget const* libTarget = item.Target;            if (libTarget &&                !StaticLibraryCycle(this->GenTarget, libTarget, config) &&                seenTargets.insert(libTarget).second) {              // Increment target config count              targetsPartOfAllConfigs[libTarget]++;            }          }        }      }      for (auto const& item : targetsPartOfAllConfigs) {        if (item.second == this->ConfigsList.size()) {          this->AutogenTarget.DependTargets.insert(item.first->Target);        }      }    }    cmTarget* timestampTarget = nullptr;    std::vector<std::string> dependencies(      this->AutogenTarget.DependFiles.begin(),      this->AutogenTarget.DependFiles.end());    if (useDepfile) {      // Create a custom command that generates a timestamp file and      // has a depfile assigned. The depfile is created by JobDepFilesMergeT.      //      // Also create an additional '_autogen_timestamp_deps' that the custom      // command will depend on. It will have no sources or commands to      // execute, but it will have dependencies that would originally be      // assigned to the pre-Qt 5.15 'autogen' target. These dependencies will      // serve as a list of order-only dependencies for the custom command,      // without forcing the custom command to re-execute.      //      // The dependency tree would then look like      // '_autogen_timestamp_deps (order-only)' <- '/timestamp' file <-      // '_autogen' target.      auto const timestampTargetName =        cmStrCat(this->GenTarget->GetName(), "_autogen_timestamp_deps");      auto cc = cm::make_unique<cmCustomCommand>();      cc->SetWorkingDirectory(this->Dir.Work.c_str());      cc->SetDepends(dependencies);      cc->SetEscapeOldStyle(false);      timestampTarget = this->LocalGen->AddUtilityCommand(timestampTargetName,                                                          true, std::move(cc));      this->LocalGen->AddGeneratorTarget(        cm::make_unique<cmGeneratorTarget>(timestampTarget, this->LocalGen));      // Set FOLDER property on the timestamp target, so it appears in the      // appropriate folder in an IDE or in the file api.      if (!this->TargetsFolder.empty()) {        timestampTarget->SetProperty("FOLDER", this->TargetsFolder);      }      // Make '/timestamp' file depend on '_autogen_timestamp_deps' and on the      // moc and uic executables (whichever are enabled).      dependencies.clear();      dependencies.push_back(timestampTargetName);      AddAutogenExecutableToDependencies(this->Moc, dependencies);      AddAutogenExecutableToDependencies(this->Uic, dependencies);      std::string outputFile;      std::string depFile;      // Create the custom command that outputs the timestamp file.      if (this->MultiConfig && this->UseBetterGraph) {        // create timestamp file with $<CONFIG> in the name so that        // every cmake_autogen target has its own timestamp file        std::string const configView = "$<CONFIG>";        std::string const timestampFileWithoutConfig = "timestamp_";        std::string const depFileWithoutConfig =          cmStrCat(this->Dir.Build, "/deps_");        std::string const timestampFileName =          timestampFileWithoutConfig + configView;        outputFile = cmStrCat(this->Dir.Build, '/', timestampFileName);        auto const depFileWithConfig =          cmStrCat(depFileWithoutConfig, configView);        depFile = depFileWithConfig;        commandLines.push_back(cmMakeCommandLine(          { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile }));        ConfigString outputFileWithConfig;        for (std::string const& config : this->ConfigsList) {          auto tempTimestampFileName = timestampFileWithoutConfig + config;          auto tempDepFile = depFileWithoutConfig + config;          outputFileWithConfig.Config[config] = tempTimestampFileName;          this->AutogenTarget.DepFileRuleName.Config[config] =            cmStrCat(this->Dir.RelativeBuild, '/', tempTimestampFileName);          this->AutogenTarget.DepFile.Config[config] = tempDepFile;        }        this->AddGeneratedSource(outputFileWithConfig, this->Moc);      } else {        cm::string_view const timestampFileName = "timestamp";        outputFile = cmStrCat(this->Dir.Build, '/', timestampFileName);        this->AutogenTarget.DepFile.Default =          cmStrCat(this->Dir.Build, "/deps");        depFile = this->AutogenTarget.DepFile.Default;        this->AutogenTarget.DepFileRuleName.Default =          cmStrCat(this->Dir.RelativeBuild, '/', timestampFileName);        commandLines.push_back(cmMakeCommandLine(          { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile }));        this->AddGeneratedSource(outputFile, this->Moc);      }      cc = cm::make_unique<cmCustomCommand>();      cc->SetOutputs(outputFile);      cc->SetByproducts(timestampByproducts);      cc->SetDepends(dependencies);      cc->SetCommandLines(commandLines);      cc->SetComment(autogenComment.c_str());      cc->SetWorkingDirectory(this->Dir.Work.c_str());      cc->SetEscapeOldStyle(false);      cc->SetDepfile(depFile);      cc->SetStdPipesUTF8(stdPipesUTF8);      this->LocalGen->AddCustomCommandToOutput(std::move(cc));      dependencies.clear();      dependencies.emplace_back(std::move(outputFile));      commandLines.clear();      autogenComment.clear();    }    // Create autogen target    auto cc = cm::make_unique<cmCustomCommand>();    cc->SetWorkingDirectory(this->Dir.Work.c_str());    cc->SetByproducts(autogenByproducts);    cc->SetDepends(dependencies);    cc->SetCommandLines(commandLines);    cc->SetEscapeOldStyle(false);    cc->SetComment(autogenComment.c_str());    cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand(      this->AutogenTarget.Name, true, std::move(cc));    // Create autogen generator target    this->LocalGen->AddGeneratorTarget(      cm::make_unique<cmGeneratorTarget>(autogenTarget, this->LocalGen));    // Order the autogen target(s) just before the original target.    cmTarget* orderTarget = timestampTarget ? timestampTarget : autogenTarget;    // Forward origin utilities to autogen target    if (this->AutogenTarget.DependOrigin) {      for (BT<std::pair<std::string, bool>> const& depName :           this->GenTarget->GetUtilities()) {        orderTarget->AddUtility(depName.Value.first, false, this->Makefile);      }    }    // Add additional autogen target dependencies to autogen target    for (cmTarget const* depTarget : this->AutogenTarget.DependTargets) {      orderTarget->AddUtility(depTarget->GetName(), false, this->Makefile);    }    // Set FOLDER property in autogen target    if (!this->TargetsFolder.empty()) {      autogenTarget->SetProperty("FOLDER", this->TargetsFolder);    }    // Add autogen target to the origin target dependencies    this->GenTarget->Target->AddUtility(this->AutogenTarget.Name, false,                                        this->Makefile);    // Add autogen target to the global autogen target dependencies    if (this->AutogenTarget.GlobalTarget) {      this->GlobalInitializer->AddToGlobalAutoGen(this->LocalGen,                                                  this->AutogenTarget.Name);    }  }  return true;}void cmQtAutoGenInitializer::AddCMakeProcessToCommandLines(  std::string const& infoFile, std::string const& processName,  cmCustomCommandLines& commandLines){  std::vector<std::string> autogenConfigs;  this->GlobalGen->GetQtAutoGenConfigs(autogenConfigs);  if (this->CrossConfig && this->UseBetterGraph) {    commandLines.push_back(cmMakeCommandLine(      { cmSystemTools::GetCMakeCommand(), "-E", processName, infoFile,        "$<CONFIG>", "$<COMMAND_CONFIG:$<CONFIG>>" }));  } else if ((this->MultiConfig && this->GlobalGen->IsXcode()) ||             this->CrossConfig) {    auto const& configs =      processName == "cmake_autorcc" ? this->ConfigsList : autogenConfigs;    for (std::string const& config : configs) {      commandLines.push_back(        cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E",                            processName, infoFile, config }));    }  } else {    std::string autoInfoFileConfig;    if (this->MultiConfig) {      autoInfoFileConfig = "$<CONFIG>";    } else {      autoInfoFileConfig = autogenConfigs[0];    }    commandLines.push_back(      cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", processName,                          infoFile, autoInfoFileConfig }));  }}bool cmQtAutoGenInitializer::InitRccTargets(){  for (Qrc const& qrc : this->Rcc.Qrcs) {    // Register info file as generated by CMake    this->Makefile->AddCMakeOutputFile(qrc.InfoFile);    // Register file at target    {      cmSourceFile* sf = this->AddGeneratedSource(qrc.OutputFile, this->Rcc);      sf->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "On");    }    std::vector<std::string> ccOutput{ qrc.OutputFile };    // Add the .qrc and info file to the custom command dependencies    std::vector<std::string> ccDepends{ qrc.QrcFile, qrc.InfoFile };    cmCustomCommandLines commandLines;    AddCMakeProcessToCommandLines(qrc.InfoFile, "cmake_autorcc", commandLines);    std::string const ccComment =      cmStrCat("Automatic RCC for ",               FileProjectRelativePath(this->Makefile, qrc.QrcFile));    auto cc = cm::make_unique<cmCustomCommand>();    cc->SetWorkingDirectory(this->Dir.Work.c_str());    cc->SetCommandLines(commandLines);    cc->SetComment(ccComment.c_str());    cc->SetStdPipesUTF8(true);    if (qrc.Generated || this->Rcc.GlobalTarget) {      // Create custom rcc target      std::string ccName;      {        ccName = cmStrCat(this->GenTarget->GetName(), "_arcc_", qrc.QrcName);        if (!qrc.Unique) {          ccName += cmStrCat('_', qrc.QrcPathChecksum);        }        cc->SetByproducts(ccOutput);        cc->SetDepends(ccDepends);        cc->SetEscapeOldStyle(false);        cmTarget* autoRccTarget =          this->LocalGen->AddUtilityCommand(ccName, true, std::move(cc));        // Create autogen generator target        this->LocalGen->AddGeneratorTarget(          cm::make_unique<cmGeneratorTarget>(autoRccTarget, this->LocalGen));        // Set FOLDER property in autogen target        if (!this->TargetsFolder.empty()) {          autoRccTarget->SetProperty("FOLDER", this->TargetsFolder);        }        if (!this->Rcc.ExecutableTargetName.empty()) {          autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName, false,                                    this->Makefile);        }      }      // Add autogen target to the origin target dependencies      this->GenTarget->Target->AddUtility(ccName, false, this->Makefile);      // Add autogen target to the global autogen target dependencies      if (this->Rcc.GlobalTarget) {        this->GlobalInitializer->AddToGlobalAutoRcc(this->LocalGen, ccName);      }    } else {      // Create custom rcc command      {        // Add the resource files to the dependencies        if (this->MultiConfig && this->UseBetterGraph) {          for (auto const& config : this->ConfigsList) {            // Add resource file to the custom command dependencies            auto resourceFilesWithConfig = cmStrCat(              "$<$<CONFIG:", config,              ">:", cmList{ qrc.Resources.Config.at(config) }.to_string(),              '>');            ccDepends.emplace_back(std::move(resourceFilesWithConfig));          }        } else {          for (std::string const& fileName : qrc.Resources.Default) {            // Add resource file to the custom command dependencies            ccDepends.push_back(fileName);          }        }        if (!this->Rcc.ExecutableTargetName.empty()) {          ccDepends.push_back(this->Rcc.ExecutableTargetName);        }        AddAutogenExecutableToDependencies(this->Rcc, ccDepends);        cc->SetOutputs(ccOutput);        cc->SetDepends(ccDepends);        this->LocalGen->AddCustomCommandToOutput(std::move(cc));      }      // Reconfigure when .qrc file changes      this->Makefile->AddCMakeDependFile(qrc.QrcFile);    }  }  return true;}bool cmQtAutoGenInitializer::SetupCustomTargets(){  // Create info directory on demand  if (!cmSystemTools::MakeDirectory(this->Dir.Info)) {    cmSystemTools::Error(cmStrCat("AutoGen: Could not create directory: ",                                  Quoted(this->Dir.Info)));    return false;  }  // Generate autogen target info file  if (this->MocOrUicEnabled()) {    // Write autogen target info files    if (!this->SetupWriteAutogenInfo()) {      return false;    }  }  // Write AUTORCC info files  return !this->Rcc.Enabled || this->SetupWriteRccInfo();}bool cmQtAutoGenInitializer::SetupWriteAutogenInfo(){  // Utility lambdas  auto MfDef = [this](std::string const& key) {    return this->Makefile->GetSafeDefinition(key);  };  // Filtered headers and sources  std::set<std::string> moc_skip;  std::set<std::string> uic_skip;  std::vector<MUFile const*> headers;  std::vector<MUFile const*> sources;  // Filter headers  {    headers.reserve(this->AutogenTarget.Headers.size());    for (auto const& pair : this->AutogenTarget.Headers) {      MUFile const* const muf = pair.second.get();      if (muf->SkipMoc) {        moc_skip.insert(muf->FullPath);      }      if (muf->SkipUic) {        uic_skip.insert(muf->FullPath);      }      if (muf->Generated && !this->CMP0071Accept) {        continue;      }      if (muf->MocIt || muf->UicIt) {        headers.emplace_back(muf);      }    }    std::sort(headers.begin(), headers.end(),              [](MUFile const* a, MUFile const* b) {                return (a->FullPath < b->FullPath);              });  }  // Filter sources  {    sources.reserve(this->AutogenTarget.Sources.size());    for (auto const& pair : this->AutogenTarget.Sources) {      MUFile const* const muf = pair.second.get();      if (muf->Generated && !this->CMP0071Accept) {        continue;      }      if (muf->SkipMoc) {        moc_skip.insert(muf->FullPath);      }      if (muf->SkipUic) {        uic_skip.insert(muf->FullPath);      }      if (muf->MocIt || muf->UicIt) {        sources.emplace_back(muf);      }    }    std::sort(sources.begin(), sources.end(),              [](MUFile const* a, MUFile const* b) {                return (a->FullPath < b->FullPath);              });  }  // Info writer  InfoWriter info;  // General  info.SetBool("MULTI_CONFIG", this->MultiConfig);  info.SetBool("CROSS_CONFIG", this->CrossConfig);  info.SetBool("USE_BETTER_GRAPH", this->UseBetterGraph);  info.SetUInt("PARALLEL", this->AutogenTarget.Parallel);#ifdef _WIN32  info.SetUInt("AUTOGEN_COMMAND_LINE_LENGTH_MAX",               this->AutogenTarget.MaxCommandLineLength);#endif  info.SetUInt("VERBOSITY", this->Verbosity);  // Directories  info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));  info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));  info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));  info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));  info.Set("BUILD_DIR", this->Dir.Build);  info.SetConfig("INCLUDE_DIR", this->Dir.Include);  info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major);  info.SetUInt("QT_VERSION_MINOR", this->QtVersion.Minor);  info.SetConfig("QT_MOC_EXECUTABLE", this->Moc.Executable);  info.SetConfig("QT_UIC_EXECUTABLE", this->Uic.Executable);  info.Set("CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());  info.SetConfig("SETTINGS_FILE", this->AutogenTarget.SettingsFile);  info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);  info.SetConfig("DEP_FILE", this->AutogenTarget.DepFile);  info.SetConfig("DEP_FILE_RULE_NAME", this->AutogenTarget.DepFileRuleName);  info.SetArray("CMAKE_LIST_FILES", this->Makefile->GetListFiles());  info.SetArray("HEADER_EXTENSIONS",                this->Makefile->GetCMakeInstance()->GetHeaderExtensions());  auto cfgArray = [this](std::vector<size_t> const& configs) -> Json::Value {    Json::Value value;    if (!configs.empty()) {      value = Json::arrayValue;      for (size_t ci : configs) {        value.append(this->ConfigsList[ci]);      }    }    return value;  };  info.SetArrayArray("HEADERS", headers,                     [this, &cfgArray](Json::Value& jval, MUFile const* muf) {                       jval.resize(4u);                       jval[0u] = muf->FullPath;                       jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm',                                           muf->UicIt ? 'U' : 'u');                       jval[2u] = this->GetMocBuildPath(*muf);                       jval[3u] = cfgArray(muf->Configs);                     });  info.SetArrayArray(    "SOURCES", sources, [&cfgArray](Json::Value& jval, MUFile const* muf) {      jval.resize(3u);      jval[0u] = muf->FullPath;      jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');      jval[2u] = cfgArray(muf->Configs);    });  // Write moc settings  if (this->Moc.Enabled) {    info.SetArray("MOC_SKIP", moc_skip);    info.SetConfigArray("MOC_DEFINITIONS", this->Moc.Defines);    info.SetConfigArray("MOC_INCLUDES", this->Moc.Includes);    info.SetArray("MOC_OPTIONS", this->Moc.Options);    info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode);    info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix);    EvaluatedTargetPropertyEntries InterfaceAutoMocMacroNamesEntries;    if (this->MultiConfig) {      for (auto const& cfg : this->ConfigsList) {        if (!cfg.empty()) {          cmGeneratorExpressionDAGChecker dagChecker{            this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr,            nullptr,         this->LocalGen,        cfg,          };          AddInterfaceEntries(this->GenTarget, cfg,                              "INTERFACE_AUTOMOC_MACRO_NAMES", "CXX",                              &dagChecker, InterfaceAutoMocMacroNamesEntries,                              IncludeRuntimeInterface::Yes);        }      }    } else {      cmGeneratorExpressionDAGChecker dagChecker{        this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr,        nullptr,         this->LocalGen,        this->ConfigDefault,      };      AddInterfaceEntries(this->GenTarget, this->ConfigDefault,                          "INTERFACE_AUTOMOC_MACRO_NAMES", "CXX", &dagChecker,                          InterfaceAutoMocMacroNamesEntries,                          IncludeRuntimeInterface::Yes);    }    for (auto const& entry : InterfaceAutoMocMacroNamesEntries.Entries) {      this->Moc.MacroNames.insert(this->Moc.MacroNames.end(),                                  entry.Values.begin(), entry.Values.end());    }    this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames),                               this->Moc.MacroNames.end());    info.SetArray("MOC_MACRO_NAMES", this->Moc.MacroNames);    info.SetArrayArray(      "MOC_DEPEND_FILTERS", this->Moc.DependFilters,      [](Json::Value& jval, std::pair<std::string, std::string> const& pair) {        jval.resize(2u);        jval[0u] = pair.first;        jval[1u] = pair.second;      });    info.SetConfig("MOC_COMPILATION_FILE", this->Moc.CompilationFile);    info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile);    cmStandardLevelResolver const resolver{ this->Makefile };    auto const CompileOptionFlag =      resolver.GetCompileOptionDef(this->GenTarget, "CXX", "");    auto const CompileOptionValue =      this->GenTarget->Makefile->GetSafeDefinition(CompileOptionFlag);    if (!CompileOptionValue.empty()) {      if (this->Moc.PredefsCmd.size() >= 3) {        this->Moc.PredefsCmd.insert(this->Moc.PredefsCmd.begin() + 1,                                    CompileOptionValue);      }    }    info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);  }  // Write uic settings  if (this->Uic.Enabled) {    // Add skipped .ui files    uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());    info.SetArray("UIC_SKIP", uic_skip);    info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFilesWithOptions,                       [](Json::Value& jval, UicT::UiFileT const& uiFile) {                         jval.resize(2u);                         jval[0u] = uiFile.first;                         InfoWriter::MakeStringArray(jval[1u], uiFile.second);                       });    info.SetConfigArray("UIC_OPTIONS", this->Uic.Options);    info.SetArray("UIC_SEARCH_PATHS", this->Uic.SearchPaths);  }  info.Save(this->AutogenTarget.InfoFile);  return true;}bool cmQtAutoGenInitializer::SetupWriteRccInfo(){  for (Qrc const& qrc : this->Rcc.Qrcs) {    // Utility lambdas    auto MfDef = [this](std::string const& key) {      return this->Makefile->GetSafeDefinition(key);    };    InfoWriter info;    // General    info.SetBool("MULTI_CONFIG", this->MultiConfig);    info.SetBool("CROSS_CONFIG", this->CrossConfig);    info.SetBool("USE_BETTER_GRAPH", this->UseBetterGraph);    info.SetUInt("VERBOSITY", this->Verbosity);    info.Set("GENERATOR", this->GlobalGen->GetName());    // Files    info.Set("LOCK_FILE", qrc.LockFile);    info.SetConfig("SETTINGS_FILE", qrc.SettingsFile);    // Directories    info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));    info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));    info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));    info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));    info.Set("BUILD_DIR", this->Dir.Build);    info.SetConfig("INCLUDE_DIR", this->Dir.Include);    // rcc executable    info.SetConfig("RCC_EXECUTABLE", this->Rcc.Executable);    info.SetConfigArray(      "RCC_LIST_OPTIONS",      generateListOptions(this->Rcc.ExecutableFeatures, this->MultiConfig));    // qrc file    info.Set("SOURCE", qrc.QrcFile);    info.Set("OUTPUT_CHECKSUM", qrc.QrcPathChecksum);    info.Set("OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.OutputFile));    info.SetArray("OPTIONS", qrc.Options);    info.SetConfigArray("INPUTS", qrc.Resources);    info.Save(qrc.InfoFile);  }  return true;}cmSourceFile* cmQtAutoGenInitializer::RegisterGeneratedSource(  std::string const& filename){  cmSourceFile* gFile = this->Makefile->GetOrCreateSource(filename, true);  gFile->MarkAsGenerated();  gFile->SetProperty("SKIP_AUTOGEN", "1");  gFile->SetProperty("SKIP_LINTING", "ON");  gFile->SetProperty("CXX_SCAN_FOR_MODULES", "0");  return gFile;}cmSourceFile* cmQtAutoGenInitializer::AddGeneratedSource(  std::string const& filename, GenVarsT const& genVars, bool prepend){  // Register source at makefile  cmSourceFile* gFile = this->RegisterGeneratedSource(filename);  // Add source file to target  this->GenTarget->AddSource(filename, prepend);  // Add source file to source group  this->AddToSourceGroup(filename, genVars.GenNameUpper);  return gFile;}void cmQtAutoGenInitializer::AddGeneratedSource(ConfigString const& filename,                                                GenVarsT const& genVars,                                                bool prepend){  // XXX(xcode-per-cfg-src): Drop the Xcode-specific part of the condition  // when the Xcode generator supports per-config sources.  if (!this->MultiConfig || this->GlobalGen->IsXcode()) {    cmSourceFile* sf =      this->AddGeneratedSource(filename.Default, genVars, prepend);    handleSkipPch(sf);    return;  }  for (auto const& cfg : this->ConfigsList) {    std::string const& filenameCfg = filename.Config.at(cfg);    // Register source at makefile    cmSourceFile* sf = this->RegisterGeneratedSource(filenameCfg);    handleSkipPch(sf);    // Add source file to target for this configuration.    this->GenTarget->AddSource(      cmStrCat("$<$<CONFIG:"_s, cfg, ">:"_s, filenameCfg, ">"_s), prepend);    // Add source file to source group    this->AddToSourceGroup(filenameCfg, genVars.GenNameUpper);  }}void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,                                              cm::string_view genNameUpper){  cmSourceGroup* sourceGroup = nullptr;  // Acquire source group  {    std::string property;    std::string groupName;    {      // Prefer generator specific source group name      std::initializer_list<std::string> const props{        cmStrCat(genNameUpper, "_SOURCE_GROUP"), "AUTOGEN_SOURCE_GROUP"      };      for (std::string const& prop : props) {        cmValue propName = this->Makefile->GetState()->GetGlobalProperty(prop);        if (cmNonempty(propName)) {          groupName = *propName;          property = prop;          break;        }      }    }    // Generate a source group on demand    if (!groupName.empty()) {      sourceGroup = this->Makefile->GetOrCreateSourceGroup(groupName);      if (!sourceGroup) {        cmSystemTools::Error(          cmStrCat(genNameUpper, " error in ", property,                   ": Could not find or create the source group ",                   cmQtAutoGen::Quoted(groupName)));      }    }  }  if (sourceGroup) {    sourceGroup->AddGroupFile(fileName);  }}void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName){  this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName);}void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,                                             cm::string_view prefix,                                             cm::string_view suffix){  configString.Default = cmStrCat(prefix, suffix);  if (this->MultiConfig) {    for (auto const& cfg : this->ConfigsList) {      configString.Config[cfg] = cmStrCat(prefix, '_', cfg, suffix);    }  }}void cmQtAutoGenInitializer::ConfigFileNamesAndGenex(  ConfigString& configString, std::string& genex, cm::string_view const prefix,  cm::string_view const suffix){  this->ConfigFileNames(configString, prefix, suffix);  if (this->MultiConfig) {    genex = cmStrCat(prefix, "_$<CONFIG>"_s, suffix);  } else {    genex = configString.Default;  }}void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString){  this->AddCleanFile(configString.Default);  if (this->MultiConfig) {    for (auto const& pair : configString.Config) {      this->AddCleanFile(pair.second);    }  }}static cmQtAutoGen::IntegerVersion parseMocVersion(std::string str){  cmQtAutoGen::IntegerVersion result;  static std::string const prelude = "moc ";  size_t const pos = str.find(prelude);  if (pos == std::string::npos) {    return result;  }  str.erase(0, prelude.size() + pos);  std::istringstream iss(str);  std::string major;  std::string minor;  if (!std::getline(iss, major, '.') || !std::getline(iss, minor, '.')) {    return result;  }  result.Major = static_cast<unsigned int>(std::stoi(major));  result.Minor = static_cast<unsigned int>(std::stoi(minor));  return result;}static cmQtAutoGen::IntegerVersion GetMocVersion(  std::string const& mocExecutablePath){  std::string capturedStdOut;  int exitCode;  if (!cmSystemTools::RunSingleCommand({ mocExecutablePath, "--version" },                                       &capturedStdOut, nullptr, &exitCode,                                       nullptr, cmSystemTools::OUTPUT_NONE)) {    return {};  }  if (exitCode != 0) {    return {};  }  return parseMocVersion(capturedStdOut);}static std::string FindMocExecutableFromMocTarget(cmMakefile const* makefile,                                                  unsigned int qtMajorVersion){  std::string result;  std::string const mocTargetName = cmStrCat("Qt", qtMajorVersion, "::moc");  cmTarget const* mocTarget = makefile->FindTargetToUse(mocTargetName);  if (mocTarget) {    result = mocTarget->GetSafeProperty("IMPORTED_LOCATION");  }  return result;}std::pair<cmQtAutoGen::IntegerVersion, unsigned int>cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target,                                     std::string mocExecutable){  // Converts a char ptr to an unsigned int value  auto toUInt = [](char const* const input) -> unsigned int {    unsigned long tmp = 0;    if (input && cmStrToULong(input, &tmp)) {      return static_cast<unsigned int>(tmp);    }    return 0u;  };  auto toUInt2 = [](cmValue input) -> unsigned int {    unsigned long tmp = 0;    if (input && cmStrToULong(*input, &tmp)) {      return static_cast<unsigned int>(tmp);    }    return 0u;  };  // Initialize return value to a default  std::pair<IntegerVersion, unsigned int> res(    IntegerVersion(),    toUInt(target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",                                                           "")));  // Acquire known Qt versions  std::vector<cmQtAutoGen::IntegerVersion> knownQtVersions;  {    // Qt version variable prefixes    static std::initializer_list<      std::pair<cm::string_view, cm::string_view>> const keys{      { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" },      { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" },      { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" },    };    knownQtVersions.reserve(keys.size() * 2);    // Adds a version to the result (nullptr safe)    auto addVersion = [&knownQtVersions, &toUInt2](cmValue major,                                                   cmValue minor) {      cmQtAutoGen::IntegerVersion ver(toUInt2(major), toUInt2(minor));      if (ver.Major != 0) {        knownQtVersions.emplace_back(ver);      }    };    // Read versions from variables    for (auto const& keyPair : keys) {      addVersion(target->Makefile->GetDefinition(std::string(keyPair.first)),                 target->Makefile->GetDefinition(std::string(keyPair.second)));    }    // Read versions from directory properties    for (auto const& keyPair : keys) {      addVersion(target->Makefile->GetProperty(std::string(keyPair.first)),                 target->Makefile->GetProperty(std::string(keyPair.second)));    }  }  // Evaluate known Qt versions  if (!knownQtVersions.empty()) {    if (res.second == 0) {      // No specific version was requested by the target:      // Use highest known Qt version.      res.first = knownQtVersions.at(0);    } else {      // Pick a version from the known versions:      for (auto const& it : knownQtVersions) {        if (it.Major == res.second) {          res.first = it;          break;        }      }    }  }  if (res.first.Major == 0) {    // We could not get the version number from variables or directory    // properties. This might happen if the find_package call for Qt is wrapped    // in a function. Try to find the moc executable path from the available    // targets and call "moc --version" to get the Qt version.    if (mocExecutable.empty()) {      mocExecutable =        FindMocExecutableFromMocTarget(target->Makefile, res.second);    }    if (!mocExecutable.empty()) {      res.first = GetMocVersion(mocExecutable);    }  }  return res;}std::string cmQtAutoGenInitializer::GetMocBuildPath(MUFile const& muf){  std::string res;  if (!muf.MocIt) {    return res;  }  std::string basePath =    cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_",             FileNameWithoutLastExtension(muf.FullPath));  res = cmStrCat(basePath, ".cpp");  if (this->Moc.EmittedBuildPaths.emplace(res).second) {    return res;  }  // File name already emitted.  // Try appending the header suffix to the base path.  basePath = cmStrCat(basePath, '_', muf.SF->GetExtension());  res = cmStrCat(basePath, ".cpp");  if (this->Moc.EmittedBuildPaths.emplace(res).second) {    return res;  }  // File name with header extension already emitted.  // Try adding a number to the base path.  constexpr std::size_t number_begin = 2;  constexpr std::size_t number_end = 256;  for (std::size_t ii = number_begin; ii != number_end; ++ii) {    res = cmStrCat(basePath, '_', ii, ".cpp");    if (this->Moc.EmittedBuildPaths.emplace(res).second) {      return res;    }  }  // Output file name conflict (unlikely, but still...)  cmSystemTools::Error(    cmStrCat("moc output file name conflict for ", muf.FullPath));  return res;}bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,                                             std::string const& executable,                                             bool ignoreMissingTarget) const{  auto print_err = [this, &genVars](std::string const& err) {    cmSystemTools::Error(cmStrCat(genVars.GenNameUpper, " for target ",                                  this->GenTarget->GetName(), ": ", err));  };  // Custom executable  {    std::string const prop = cmStrCat(genVars.GenNameUpper, "_EXECUTABLE");    std::string const& val = this->GenTarget->Target->GetSafeProperty(prop);    if (!val.empty()) {      // Evaluate generator expression      {        cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();        cmGeneratorExpression ge(*this->Makefile->GetCMakeInstance(), lfbt);        std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(val);        if (this->MultiConfig && this->UseBetterGraph) {          for (auto const& config : this->ConfigsList) {            genVars.Executable.Config[config] =              cge->Evaluate(this->LocalGen, config);          }        } else {          genVars.Executable.Default = cge->Evaluate(this->LocalGen, "");        }      }      if (genVars.Executable.Default.empty() &&          genVars.Executable.Config.empty() && !ignoreMissingTarget) {        print_err(prop + " evaluates to an empty value");        return false;      }      // Create empty compiler features.      if (this->MultiConfig && this->UseBetterGraph) {        for (auto const& config : this->ConfigsList) {          genVars.ExecutableFeatures.Config[config] =            std::make_shared<cmQtAutoGen::CompilerFeatures>();        }      } else {        genVars.ExecutableFeatures.Default =          std::make_shared<cmQtAutoGen::CompilerFeatures>();      }      return true;    }  }  // Find executable target  {    // Find executable target name    cm::string_view prefix;    if (this->QtVersion.Major == 4) {      prefix = "Qt4::";    } else if (this->QtVersion.Major == 5) {      prefix = "Qt5::";    } else if (this->QtVersion.Major == 6) {      prefix = "Qt6::";    }    std::string const targetName = cmStrCat(prefix, executable);    // Find target    cmGeneratorTarget* genTarget =      this->LocalGen->FindGeneratorTargetToUse(targetName);    if (genTarget) {      genVars.ExecutableTargetName = targetName;      genVars.ExecutableTarget = genTarget;      if (genTarget->IsImported()) {        if (this->MultiConfig && this->UseBetterGraph) {          for (auto const& config : this->ConfigsList) {            genVars.Executable.Config[config] =              genTarget->ImportedGetLocation(config);          }        } else {          genVars.Executable.Default =            genTarget->ImportedGetLocation(this->ConfigDefault);        }      } else {        if (this->MultiConfig && this->UseBetterGraph) {          for (auto const& config : this->ConfigsList) {            genVars.Executable.Config[config] = genTarget->GetLocation(config);          }        } else {          genVars.Executable.Default =            genTarget->GetLocation(this->ConfigDefault);        }      }    } else {      if (ignoreMissingTarget) {        // Create empty compiler features.        if (this->MultiConfig && this->UseBetterGraph) {          for (auto const& config : this->ConfigsList) {            genVars.ExecutableFeatures.Config[config] =              std::make_shared<cmQtAutoGen::CompilerFeatures>();          }        } else {          genVars.ExecutableFeatures.Default =            std::make_shared<cmQtAutoGen::CompilerFeatures>();        }        return true;      }      print_err(cmStrCat("Could not find ", executable, " executable target ",                         targetName));      return false;    }  }  // Get executable features  {    std::string err;    genVars.ExecutableFeatures = this->GlobalInitializer->GetCompilerFeatures(      executable, genVars.Executable, err, this->MultiConfig,      this->UseBetterGraph);    if (this->MultiConfig && this->UseBetterGraph) {      for (auto const& config : this->ConfigsList) {        if (!genVars.ExecutableFeatures.Config[config]) {          if (!genVars.ExecutableFeatures.Config[config]) {            print_err(err);            return false;          }        }      }    } else {      if (!genVars.ExecutableFeatures.Default) {        print_err(err);        return false;      }    }  }  return true;}void cmQtAutoGenInitializer::handleSkipPch(cmSourceFile* sf){  bool skipPch = true;  for (auto const& pair : this->AutogenTarget.Sources) {    if (!pair.first->GetIsGenerated() &&        !pair.first->GetProperty("SKIP_PRECOMPILE_HEADERS")) {      skipPch = false;    }  }  if (skipPch) {    sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON");  }}
 |