| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614 | /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying   file Copyright.txt or https://cmake.org/licensing for details.  */#include "cmQtAutoGenInitializer.h"#include "cmQtAutoGen.h"#include "cmAlgorithms.h"#include "cmCustomCommand.h"#include "cmCustomCommandLines.h"#include "cmDuration.h"#include "cmFilePathChecksum.h"#include "cmGeneratedFileStream.h"#include "cmGeneratorTarget.h"#include "cmGlobalGenerator.h"#include "cmLinkItem.h"#include "cmLocalGenerator.h"#include "cmMakefile.h"#include "cmOutputConverter.h"#include "cmPolicies.h"#include "cmProcessOutput.h"#include "cmSourceFile.h"#include "cmSourceGroup.h"#include "cmState.h"#include "cmStateTypes.h"#include "cmSystemTools.h"#include "cmTarget.h"#include "cmake.h"#include "cmsys/FStream.hxx"#include "cmsys/SystemInformation.hxx"#include <algorithm>#include <array>#include <deque>#include <map>#include <set>#include <sstream>#include <string>#include <utility>#include <vector>static std::size_t GetParallelCPUCount(){  static std::size_t count = 0;  // Detect only on the first call  if (count == 0) {    cmsys::SystemInformation info;    info.RunCPUCheck();    count = info.GetNumberOfPhysicalCPU();    count = std::max<std::size_t>(count, 1);    count = std::min<std::size_t>(count, cmQtAutoGen::ParallelMax);  }  return count;}static bool AddToSourceGroup(cmMakefile* makefile, std::string const& fileName,                             cmQtAutoGen::GeneratorT genType){  cmSourceGroup* sourceGroup = nullptr;  // Acquire source group  {    std::string property;    std::string groupName;    {      std::array<std::string, 2> props;      // Use generator specific group name      switch (genType) {        case cmQtAutoGen::GeneratorT::MOC:          props[0] = "AUTOMOC_SOURCE_GROUP";          break;        case cmQtAutoGen::GeneratorT::RCC:          props[0] = "AUTORCC_SOURCE_GROUP";          break;        default:          props[0] = "AUTOGEN_SOURCE_GROUP";          break;      }      props[1] = "AUTOGEN_SOURCE_GROUP";      for (std::string& prop : props) {        const char* propName = makefile->GetState()->GetGlobalProperty(prop);        if ((propName != nullptr) && (*propName != '\0')) {          groupName = propName;          property = std::move(prop);          break;        }      }    }    // Generate a source group on demand    if (!groupName.empty()) {      sourceGroup = makefile->GetOrCreateSourceGroup(groupName);      if (sourceGroup == nullptr) {        std::ostringstream ost;        ost << cmQtAutoGen::GeneratorNameUpper(genType);        ost << ": " << property;        ost << ": Could not find or create the source group ";        ost << cmQtAutoGen::Quoted(groupName);        cmSystemTools::Error(ost.str().c_str());        return false;      }    }  }  if (sourceGroup != nullptr) {    sourceGroup->AddGroupFile(fileName);  }  return true;}static void AddCleanFile(cmMakefile* makefile, std::string const& fileName){  makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fileName.c_str(),                           false);}static std::string FileProjectRelativePath(cmMakefile* 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;}/* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its * recursive STATIC_LIBRARY dependencies depends on targetOrigin * (STATIC_LIBRARY cycle). */static 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);      if (libs != nullptr) {        for (cmLinkItem const& item : libs->Libraries) {          cmGeneratorTarget const* depTarget = item.Target;          if ((depTarget != nullptr) &&              (depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) &&              knownLibs.insert(depTarget).second) {            testLibs.push_back(depTarget);          }        }      }    }  }  return cycle;}cmQtAutoGenInitializer::cmQtAutoGenInitializer(cmGeneratorTarget* target,                                               bool mocEnabled,                                               bool uicEnabled,                                               bool rccEnabled,                                               IntegerVersion const& qtVersion)  : Target(target)  , QtVersion(qtVersion){  Moc.Enabled = mocEnabled;  Uic.Enabled = uicEnabled;  Rcc.Enabled = rccEnabled;}bool cmQtAutoGenInitializer::InitCustomTargets(){  cmMakefile* makefile = this->Target->Target->GetMakefile();  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();  // Configurations  this->MultiConfig = globalGen->IsMultiConfig();  this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);  if (this->ConfigsList.empty()) {    this->ConfigsList.push_back(this->ConfigDefault);  }  // Verbosity  this->Verbosity = makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");  if (!this->Verbosity.empty()) {    unsigned long iVerb = 0;    if (!cmSystemTools::StringToULong(this->Verbosity.c_str(), &iVerb)) {      // Non numeric verbosity      this->Verbosity = cmSystemTools::IsOn(this->Verbosity) ? "1" : "0";    }  }  // Targets FOLDER  {    const char* folder =      makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");    if (folder == nullptr) {      folder =        makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");    }    // Inherit FOLDER property from target (#13688)    if (folder == nullptr) {      folder = this->Target->GetProperty("FOLDER");    }    if (folder != nullptr) {      this->TargetsFolder = folder;    }  }  // Common directories  {    // Collapsed current binary directory    std::string const cbd = cmSystemTools::CollapseFullPath(      std::string(), makefile->GetCurrentBinaryDirectory());    // Info directory    this->Dir.Info = cbd;    this->Dir.Info += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();    this->Dir.Info += '/';    this->Dir.Info += this->Target->GetName();    this->Dir.Info += "_autogen";    this->Dir.Info += ".dir";    cmSystemTools::ConvertToUnixSlashes(this->Dir.Info);    // Build directory    this->Dir.Build = this->Target->GetSafeProperty("AUTOGEN_BUILD_DIR");    if (this->Dir.Build.empty()) {      this->Dir.Build = cbd;      this->Dir.Build += '/';      this->Dir.Build += this->Target->GetName();      this->Dir.Build += "_autogen";    }    cmSystemTools::ConvertToUnixSlashes(this->Dir.Build);    // Cleanup build directory    AddCleanFile(makefile, this->Dir.Build);    // Working directory    this->Dir.Work = cbd;    cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);    // Include directory    this->Dir.Include = this->Dir.Build;    this->Dir.Include += "/include";    if (this->MultiConfig) {      this->Dir.Include += "_$<CONFIG>";    }    // Per config include directories    if (this->MultiConfig) {      for (std::string const& cfg : this->ConfigsList) {        std::string& dir = this->Dir.ConfigInclude[cfg];        dir = this->Dir.Build;        dir += "/include_";        dir += cfg;      }    }  }  // Moc, Uic and _autogen target settings  if (this->Moc.Enabled || this->Uic.Enabled) {    // Init moc specific settings    if (this->Moc.Enabled && !InitMoc()) {      return false;    }    // Init uic specific settings    if (this->Uic.Enabled && !InitUic()) {      return false;    }    // Autogen target name    this->AutogenTarget.Name = this->Target->GetName();    this->AutogenTarget.Name += "_autogen";    // Autogen target parallel processing    this->AutogenTarget.Parallel =      this->Target->GetSafeProperty("AUTOGEN_PARALLEL");    if (this->AutogenTarget.Parallel.empty() ||        (this->AutogenTarget.Parallel == "AUTO")) {      // Autodetect number of CPUs      this->AutogenTarget.Parallel = std::to_string(GetParallelCPUCount());    }    // Autogen target info and settings files    {      this->AutogenTarget.InfoFile = this->Dir.Info;      this->AutogenTarget.InfoFile += "/AutogenInfo.cmake";      this->AutogenTarget.SettingsFile = this->Dir.Info;      this->AutogenTarget.SettingsFile += "/AutogenOldSettings.txt";      if (this->MultiConfig) {        for (std::string const& cfg : this->ConfigsList) {          std::string& filename = this->AutogenTarget.ConfigSettingsFile[cfg];          filename =            AppendFilenameSuffix(this->AutogenTarget.SettingsFile, "_" + cfg);          AddCleanFile(makefile, filename);        }      } else {        AddCleanFile(makefile, this->AutogenTarget.SettingsFile);      }    }    // Autogen target: Compute user defined dependencies    {      std::string const deps =        this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");      if (!deps.empty()) {        std::vector<std::string> extraDeps;        cmSystemTools::ExpandListArgument(deps, extraDeps);        for (std::string const& depName : extraDeps) {          // Allow target and file dependencies          auto* depTarget = makefile->FindTargetToUse(depName);          if (depTarget != nullptr) {            this->AutogenTarget.DependTargets.insert(depTarget);          } else {            this->AutogenTarget.DependFiles.insert(depName);          }        }      }    }  }  // Init rcc specific settings  if (this->Rcc.Enabled && !InitRcc()) {    return false;  }  // Add autogen include directory to the origin target INCLUDE_DIRECTORIES  if (this->Moc.Enabled || this->Uic.Enabled ||      (this->Rcc.Enabled && this->MultiConfig)) {    this->Target->AddIncludeDirectory(this->Dir.Include, true);  }  // Scan files  if (!this->InitScanFiles()) {    return false;  }  // Create autogen target  if ((this->Moc.Enabled || this->Uic.Enabled) && !this->InitAutogenTarget()) {    return false;  }  // Create rcc targets  if (this->Rcc.Enabled && !this->InitRccTargets()) {    return false;  }  return true;}bool cmQtAutoGenInitializer::InitMoc(){  cmMakefile* makefile = this->Target->Target->GetMakefile();  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();  // Mocs compilation file  this->Moc.MocsCompilation = this->Dir.Build;  this->Moc.MocsCompilation += "/mocs_compilation.cpp";  // Moc predefs command  if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&      (this->QtVersion >= IntegerVersion(5, 8))) {    this->Moc.PredefsCmd =      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");  }  // Moc includes  {    // We need to disable this until we have all implicit includes available.    // See issue #18669.    // bool const appendImplicit = (this->QtVersion.Major == 5);    auto GetIncludeDirs = [this,                           localGen](std::string const& cfg) -> std::string {      bool const appendImplicit = false;      // Get the include dirs for this target, without stripping the implicit      // include dirs off, see      // https://gitlab.kitware.com/cmake/cmake/issues/13667      std::vector<std::string> dirs;      localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false,                                      appendImplicit);      return cmJoin(dirs, ";");    };    // Default configuration include directories    this->Moc.Includes = GetIncludeDirs(this->ConfigDefault);    // Other configuration settings    if (this->MultiConfig) {      for (std::string const& cfg : this->ConfigsList) {        std::string dirs = GetIncludeDirs(cfg);        if (dirs != this->Moc.Includes) {          this->Moc.ConfigIncludes[cfg] = std::move(dirs);        }      }    }  }  // Moc compile definitions  {    auto GetCompileDefinitions =      [this, localGen](std::string const& cfg) -> std::string {      std::set<std::string> defines;      localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");      return cmJoin(defines, ";");    };    // Default configuration defines    this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault);    // Other configuration defines    if (this->MultiConfig) {      for (std::string const& cfg : this->ConfigsList) {        std::string defines = GetCompileDefinitions(cfg);        if (defines != this->Moc.Defines) {          this->Moc.ConfigDefines[cfg] = std::move(defines);        }      }    }  }  // Moc executable  if (!GetMocExecutable()) {    return false;  }  return true;}bool cmQtAutoGenInitializer::InitUic(){  cmMakefile* makefile = this->Target->Target->GetMakefile();  // Uic search paths  {    std::string const usp =      this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS");    if (!usp.empty()) {      cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths);      std::string const& srcDir = makefile->GetCurrentSourceDirectory();      for (std::string& path : this->Uic.SearchPaths) {        path = cmSystemTools::CollapseFullPath(path, srcDir);      }    }  }  // Uic target options  {    auto UicGetOpts = [this](std::string const& cfg) -> std::string {      std::vector<std::string> opts;      this->Target->GetAutoUicOptions(opts, cfg);      return cmJoin(opts, ";");    };    // Default settings    this->Uic.Options = UicGetOpts(this->ConfigDefault);    // Configuration specific settings    if (this->MultiConfig) {      for (std::string const& cfg : this->ConfigsList) {        std::string options = UicGetOpts(cfg);        if (options != this->Uic.Options) {          this->Uic.ConfigOptions[cfg] = std::move(options);        }      }    }  }  // .ui files skip and options  {    std::string const uiExt = "ui";    std::string pathError;    for (cmSourceFile* sf : makefile->GetSourceFiles()) {      // sf->GetExtension() is only valid after sf->GetFullPath() ...      // Since we're iterating over source files that might be not in the      // target we need to check for path errors (not existing files).      std::string const& fPath = sf->GetFullPath(&pathError);      if (!pathError.empty()) {        pathError.clear();        continue;      }      if (sf->GetExtension() == uiExt) {        std::string const absFile = cmSystemTools::GetRealPath(fPath);        // Check if the .ui file should be skipped        if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||            sf->GetPropertyAsBool("SKIP_AUTOGEN")) {          this->Uic.Skip.insert(absFile);        }        // Check if the .ui file has uic options        std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS");        if (!uicOpts.empty()) {          // Check if file isn't skipped          if (this->Uic.Skip.count(absFile) == 0) {            this->Uic.FileFiles.push_back(absFile);            std::vector<std::string> optsVec;            cmSystemTools::ExpandListArgument(uicOpts, optsVec);            this->Uic.FileOptions.push_back(std::move(optsVec));          }        }      }    }  }  // Uic executable  if (!GetUicExecutable()) {    return false;  }  return true;}bool cmQtAutoGenInitializer::InitRcc(){  if (!GetRccExecutable()) {    return false;  }  return true;}bool cmQtAutoGenInitializer::InitScanFiles(){  cmMakefile* makefile = this->Target->Target->GetMakefile();  // Scan through target files  {    std::string const qrcExt = "qrc";    std::vector<cmSourceFile*> srcFiles;    this->Target->GetConfigCommonSourceFiles(srcFiles);    for (cmSourceFile* sf : srcFiles) {      if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {        continue;      }      // sf->GetExtension() is only valid after sf->GetFullPath() ...      std::string const& fPath = sf->GetFullPath();      std::string const& ext = sf->GetExtension();      // Register generated files that will be scanned by moc or uic      if (this->Moc.Enabled || this->Uic.Enabled) {        cmSystemTools::FileFormat const fileType =          cmSystemTools::GetFileFormat(ext.c_str());        if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||            (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {          std::string const absPath = cmSystemTools::GetRealPath(fPath);          if ((this->Moc.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||              (this->Uic.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {            // Register source            const bool generated = sf->GetPropertyAsBool("GENERATED");            if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {              if (generated) {                this->AutogenTarget.HeadersGenerated.push_back(absPath);              } else {                this->AutogenTarget.Headers.push_back(absPath);              }            } else {              if (generated) {                this->AutogenTarget.SourcesGenerated.push_back(absPath);              } else {                this->AutogenTarget.Sources.push_back(absPath);              }            }          }        }      }      // Register rcc enabled files      if (this->Rcc.Enabled && (ext == qrcExt) &&          !sf->GetPropertyAsBool("SKIP_AUTORCC")) {        // Register qrc file        {          Qrc qrc;          qrc.QrcFile = cmSystemTools::GetRealPath(fPath);          qrc.QrcName =            cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);          qrc.Generated = sf->GetPropertyAsBool("GENERATED");          // RCC options          {            std::string const opts = sf->GetSafeProperty("AUTORCC_OPTIONS");            if (!opts.empty()) {              cmSystemTools::ExpandListArgument(opts, qrc.Options);            }          }          this->Rcc.Qrcs.push_back(std::move(qrc));        }      }    }  }  // cmGeneratorTarget::GetConfigCommonSourceFiles 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->Target->ClearSourcesCache();  if (this->Moc.Enabled || this->Uic.Enabled) {    // Read skip files from makefile sources    {      std::string pathError;      for (cmSourceFile* sf : makefile->GetSourceFiles()) {        // sf->GetExtension() is only valid after sf->GetFullPath() ...        // Since we're iterating over source files that might be not in the        // target we need to check for path errors (not existing files).        std::string const& fPath = sf->GetFullPath(&pathError);        if (!pathError.empty()) {          pathError.clear();          continue;        }        cmSystemTools::FileFormat const fileType =          cmSystemTools::GetFileFormat(sf->GetExtension().c_str());        if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&            !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {          continue;        }        const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");        const bool mocSkip = this->Moc.Enabled &&          (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));        const bool uicSkip = this->Uic.Enabled &&          (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));        if (mocSkip || uicSkip) {          std::string const absFile = cmSystemTools::GetRealPath(fPath);          if (mocSkip) {            this->Moc.Skip.insert(absFile);          }          if (uicSkip) {            this->Uic.Skip.insert(absFile);          }        }      }    }    // Process GENERATED sources and headers    if (!this->AutogenTarget.SourcesGenerated.empty() ||        !this->AutogenTarget.HeadersGenerated.empty()) {      // Check status of policy CMP0071      bool policyAccept = false;      bool policyWarn = false;      cmPolicies::PolicyStatus const CMP0071_status =        makefile->GetPolicyStatus(cmPolicies::CMP0071);      switch (CMP0071_status) {        case cmPolicies::WARN:          policyWarn = true;          CM_FALLTHROUGH;        case cmPolicies::OLD:          // Ignore GENERATED file          break;        case cmPolicies::REQUIRED_IF_USED:        case cmPolicies::REQUIRED_ALWAYS:        case cmPolicies::NEW:          // Process GENERATED file          policyAccept = true;          break;      }      if (policyAccept) {        // Accept GENERATED sources        for (std::string const& absFile :             this->AutogenTarget.HeadersGenerated) {          this->AutogenTarget.Headers.push_back(absFile);          this->AutogenTarget.DependFiles.insert(absFile);        }        for (std::string const& absFile :             this->AutogenTarget.SourcesGenerated) {          this->AutogenTarget.Sources.push_back(absFile);          this->AutogenTarget.DependFiles.insert(absFile);        }      } else {        if (policyWarn) {          std::string msg;          msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);          msg += "\n";          std::string tools;          std::string property;          if (this->Moc.Enabled && this->Uic.Enabled) {            tools = "AUTOMOC and AUTOUIC";            property = "SKIP_AUTOGEN";          } else if (this->Moc.Enabled) {            tools = "AUTOMOC";            property = "SKIP_AUTOMOC";          } else if (this->Uic.Enabled) {            tools = "AUTOUIC";            property = "SKIP_AUTOUIC";          }          msg += "For compatibility, CMake is excluding the GENERATED source "                 "file(s):\n";          for (const std::string& absFile :               this->AutogenTarget.HeadersGenerated) {            msg.append("  ").append(Quoted(absFile)).append("\n");          }          for (const std::string& absFile :               this->AutogenTarget.SourcesGenerated) {            msg.append("  ").append(Quoted(absFile)).append("\n");          }          msg += "from processing by ";          msg += tools;          msg +=            ". 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 ";          msg += property;          msg += ":\n  set_property(SOURCE file.h PROPERTY ";          msg += property;          msg += " ON)\n";          makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);        }      }    }    // Sort headers and sources    if (this->Moc.Enabled || this->Uic.Enabled) {      std::sort(this->AutogenTarget.Headers.begin(),                this->AutogenTarget.Headers.end());      std::sort(this->AutogenTarget.Sources.begin(),                this->AutogenTarget.Sources.end());    }  }  // Process qrc files  if (!this->Rcc.Qrcs.empty()) {    const bool QtV5 = (this->QtVersion.Major == 5);    // Target rcc options    std::vector<std::string> optionsTarget;    cmSystemTools::ExpandListArgument(      this->Target->GetSafeProperty("AUTORCC_OPTIONS"), optionsTarget);    // 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    {      cmFilePathChecksum const fpathCheckSum(makefile);      for (Qrc& qrc : this->Rcc.Qrcs) {        qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);        // RCC output file name        {          std::string rccFile = this->Dir.Build + "/";          rccFile += qrc.PathChecksum;          rccFile += "/qrc_";          rccFile += qrc.QrcName;          rccFile += ".cpp";          qrc.RccFile = std::move(rccFile);        }        {          std::string base = this->Dir.Info;          base += "/RCC";          base += qrc.QrcName;          if (!qrc.Unique) {            base += qrc.PathChecksum;          }          qrc.LockFile = base;          qrc.LockFile += ".lock";          qrc.InfoFile = base;          qrc.InfoFile += "Info.cmake";          qrc.SettingsFile = base;          qrc.SettingsFile += "Settings.txt";          if (this->MultiConfig) {            for (std::string const& cfg : this->ConfigsList) {              qrc.ConfigSettingsFile[cfg] =                AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);            }          }        }      }    }    // 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 += "_";          name += qrc.PathChecksum;        }        std::vector<std::string> nameOpts;        nameOpts.emplace_back("-name");        nameOpts.emplace_back(std::move(name));        RccMergeOptions(opts, nameOpts, QtV5);      }      // Merge file option      RccMergeOptions(opts, qrc.Options, QtV5);      qrc.Options = std::move(opts);    }    // RCC resources    for (Qrc& qrc : this->Rcc.Qrcs) {      if (!qrc.Generated) {        std::string error;        if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) {          cmSystemTools::Error(error.c_str());          return false;        }      }    }  }  return true;}bool cmQtAutoGenInitializer::InitAutogenTarget(){  cmMakefile* makefile = this->Target->Target->GetMakefile();  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();  // Register info file as generated by CMake  makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile);  // Files provided by the autogen target  std::vector<std::string> autogenProvides;  if (this->Moc.Enabled) {    this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC);    autogenProvides.push_back(this->Moc.MocsCompilation);  }  // 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 = "Automatic ";    autogenComment += tools;    autogenComment += " for target ";    autogenComment += this->Target->GetName();  }  // Compose command lines  cmCustomCommandLines commandLines;  {    cmCustomCommandLine currentLine;    currentLine.push_back(cmSystemTools::GetCMakeCommand());    currentLine.push_back("-E");    currentLine.push_back("cmake_autogen");    currentLine.push_back(this->AutogenTarget.InfoFile);    currentLine.push_back("$<CONFIGURATION>");    commandLines.push_back(std::move(currentLine));  }  // Use PRE_BUILD on demand  bool usePRE_BUILD = false;  if (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;    }  }  // Create the autogen target/command  if (usePRE_BUILD) {    // Add additional autogen target dependencies to origin target    for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {      this->Target->Target->AddUtility(depTarget->GetName(), makefile);    }    // 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!    const std::vector<std::string> no_output;    const std::vector<std::string> no_deps;    cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,                       commandLines, autogenComment.c_str(),                       this->Dir.Work.c_str());    cc.SetEscapeOldStyle(false);    cc.SetEscapeAllowMakeVars(true);    this->Target->Target->AddPreBuildCommand(cc);  } else {    // Add link library target dependencies to the autogen target    // dependencies    {      // 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> commonTargets;      for (std::string const& config : this->ConfigsList) {        cmLinkImplementationLibraries const* libs =          this->Target->GetLinkImplementationLibraries(config);        if (libs != nullptr) {          for (cmLinkItem const& item : libs->Libraries) {            cmGeneratorTarget const* libTarget = item.Target;            if ((libTarget != nullptr) &&                !StaticLibraryCycle(this->Target, libTarget, config)) {              // Increment target config count              commonTargets[libTarget]++;            }          }        }      }      for (auto const& item : commonTargets) {        if (item.second == this->ConfigsList.size()) {          this->AutogenTarget.DependTargets.insert(item.first->Target);        }      }    }    // Create autogen target    cmTarget* autogenTarget = makefile->AddUtilityCommand(      this->AutogenTarget.Name, cmMakefile::TargetOrigin::Generator, true,      this->Dir.Work.c_str(), /*byproducts=*/autogenProvides,      std::vector<std::string>(this->AutogenTarget.DependFiles.begin(),                               this->AutogenTarget.DependFiles.end()),      commandLines, false, autogenComment.c_str());    // Create autogen generator target    localGen->AddGeneratorTarget(      new cmGeneratorTarget(autogenTarget, localGen));    // Forward origin utilities to autogen target    for (std::string const& depName : this->Target->Target->GetUtilities()) {      autogenTarget->AddUtility(depName, makefile);    }    // Add additional autogen target dependencies to autogen target    for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {      autogenTarget->AddUtility(depTarget->GetName(), makefile);    }    // Set FOLDER property in autogen target    if (!this->TargetsFolder.empty()) {      autogenTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());    }    // Add autogen target to the origin target dependencies    this->Target->Target->AddUtility(this->AutogenTarget.Name, makefile);  }  return true;}bool cmQtAutoGenInitializer::InitRccTargets(){  cmMakefile* makefile = this->Target->Target->GetMakefile();  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();  for (Qrc const& qrc : this->Rcc.Qrcs) {    // Register info file as generated by CMake    makefile->AddCMakeOutputFile(qrc.InfoFile);    // Register file at target    this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);    std::vector<std::string> ccOutput;    ccOutput.push_back(qrc.RccFile);    cmCustomCommandLines commandLines;    if (this->MultiConfig) {      // Build for all configurations      for (std::string const& config : this->ConfigsList) {        cmCustomCommandLine currentLine;        currentLine.push_back(cmSystemTools::GetCMakeCommand());        currentLine.push_back("-E");        currentLine.push_back("cmake_autorcc");        currentLine.push_back(qrc.InfoFile);        currentLine.push_back(config);        commandLines.push_back(std::move(currentLine));      }    } else {      cmCustomCommandLine currentLine;      currentLine.push_back(cmSystemTools::GetCMakeCommand());      currentLine.push_back("-E");      currentLine.push_back("cmake_autorcc");      currentLine.push_back(qrc.InfoFile);      currentLine.push_back("$<CONFIG>");      commandLines.push_back(std::move(currentLine));    }    std::string ccComment = "Automatic RCC for ";    ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);    if (qrc.Generated) {      // Create custom rcc target      std::string ccName;      {        ccName = this->Target->GetName();        ccName += "_arcc_";        ccName += qrc.QrcName;        if (!qrc.Unique) {          ccName += "_";          ccName += qrc.PathChecksum;        }        std::vector<std::string> ccDepends;        // Add the .qrc and info file to the custom target dependencies        ccDepends.push_back(qrc.QrcFile);        ccDepends.push_back(qrc.InfoFile);        cmTarget* autoRccTarget = makefile->AddUtilityCommand(          ccName, cmMakefile::TargetOrigin::Generator, true,          this->Dir.Work.c_str(), ccOutput, ccDepends, commandLines, false,          ccComment.c_str());        // Create autogen generator target        localGen->AddGeneratorTarget(          new cmGeneratorTarget(autoRccTarget, localGen));        // Set FOLDER property in autogen target        if (!this->TargetsFolder.empty()) {          autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());        }      }      // Add autogen target to the origin target dependencies      this->Target->Target->AddUtility(ccName, makefile);    } else {      // Create custom rcc command      {        std::vector<std::string> ccByproducts;        std::vector<std::string> ccDepends;        // Add the .qrc and info file to the custom command dependencies        ccDepends.push_back(qrc.QrcFile);        ccDepends.push_back(qrc.InfoFile);        // Add the resource files to the dependencies        for (std::string const& fileName : qrc.Resources) {          // Add resource file to the custom command dependencies          ccDepends.push_back(fileName);        }        makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,                                           /*main_dependency*/ std::string(),                                           commandLines, ccComment.c_str(),                                           this->Dir.Work.c_str());      }      // Reconfigure when .qrc file changes      makefile->AddCMakeDependFile(qrc.QrcFile);    }  }  return true;}bool cmQtAutoGenInitializer::SetupCustomTargets(){  // Create info directory on demand  if (!cmSystemTools::MakeDirectory(this->Dir.Info)) {    std::string emsg = ("AutoGen: Could not create directory: ");    emsg += Quoted(this->Dir.Info);    cmSystemTools::Error(emsg.c_str());    return false;  }  // Generate autogen target info file  if (this->Moc.Enabled || this->Uic.Enabled) {    // Write autogen target info files    if (!this->SetupWriteAutogenInfo()) {      return false;    }  }  // Write AUTORCC info files  if (this->Rcc.Enabled && !this->SetupWriteRccInfo()) {    return false;  }  return true;}bool cmQtAutoGenInitializer::SetupWriteAutogenInfo(){  cmMakefile* makefile = this->Target->Target->GetMakefile();  cmGeneratedFileStream ofs;  ofs.SetCopyIfDifferent(true);  ofs.Open(this->AutogenTarget.InfoFile, false, true);  if (ofs) {    // Utility lambdas    auto CWrite = [&ofs](const char* key, std::string const& value) {      ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)          << ")\n";    };    auto CWriteUInt = [&ofs](const char* key, unsigned int value) {      ofs << "set(" << key << " " << value << ")\n";    };    auto CWriteList = [&CWrite](const char* key,                                std::vector<std::string> const& list) {      CWrite(key, cmJoin(list, ";"));    };    auto CWriteNestedLists =      [&CWrite](const char* key,                std::vector<std::vector<std::string>> const& lists) {        std::vector<std::string> seplist;        for (const std::vector<std::string>& list : lists) {          std::string blist = "{";          blist += cmJoin(list, ";");          blist += "}";          seplist.push_back(std::move(blist));        }        CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));      };    auto CWriteSet = [&CWrite](const char* key,                               std::set<std::string> const& list) {      CWrite(key, cmJoin(list, ";"));    };    auto CWriteMap = [&ofs](const char* key,                            std::map<std::string, std::string> const& map) {      for (auto const& item : map) {        ofs << "set(" << key << "_" << item.first << " "            << cmOutputConverter::EscapeForCMake(item.second) << ")\n";      }    };    auto MfDef = [makefile](const char* key) {      return makefile->GetSafeDefinition(key);    };    // Write    ofs << "# Meta\n";    CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");    CWrite("AM_PARALLEL", this->AutogenTarget.Parallel);    CWrite("AM_VERBOSITY", this->Verbosity);    ofs << "# Directories\n";    CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));    CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));    CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));    CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));    CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",           MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));    CWrite("AM_BUILD_DIR", this->Dir.Build);    CWrite("AM_INCLUDE_DIR", this->Dir.Include);    CWriteMap("AM_INCLUDE_DIR", this->Dir.ConfigInclude);    ofs << "# Files\n";    CWriteList("AM_SOURCES", this->AutogenTarget.Sources);    CWriteList("AM_HEADERS", this->AutogenTarget.Headers);    CWrite("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile);    CWriteMap("AM_SETTINGS_FILE", this->AutogenTarget.ConfigSettingsFile);    ofs << "# Qt\n";    CWriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major);    CWrite("AM_QT_MOC_EXECUTABLE", this->Moc.Executable);    CWrite("AM_QT_UIC_EXECUTABLE", this->Uic.Executable);    if (this->Moc.Enabled) {      ofs << "# MOC settings\n";      CWriteSet("AM_MOC_SKIP", this->Moc.Skip);      CWrite("AM_MOC_DEFINITIONS", this->Moc.Defines);      CWriteMap("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines);      CWrite("AM_MOC_INCLUDES", this->Moc.Includes);      CWriteMap("AM_MOC_INCLUDES", this->Moc.ConfigIncludes);      CWrite("AM_MOC_OPTIONS",             this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS"));      CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));      CWrite("AM_MOC_MACRO_NAMES",             this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES"));      CWrite("AM_MOC_DEPEND_FILTERS",             this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));      CWrite("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd);    }    if (this->Uic.Enabled) {      ofs << "# UIC settings\n";      CWriteSet("AM_UIC_SKIP", this->Uic.Skip);      CWrite("AM_UIC_TARGET_OPTIONS", this->Uic.Options);      CWriteMap("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions);      CWriteList("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles);      CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions);      CWriteList("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths);    }  } else {    std::string err = "AutoGen: Could not write file ";    err += this->AutogenTarget.InfoFile;    cmSystemTools::Error(err.c_str());    return false;  }  return true;}bool cmQtAutoGenInitializer::SetupWriteRccInfo(){  for (Qrc const& qrc : this->Rcc.Qrcs) {    cmGeneratedFileStream ofs;    ofs.SetCopyIfDifferent(true);    ofs.Open(qrc.InfoFile, false, true);    if (ofs) {      // Utility lambdas      auto CWrite = [&ofs](const char* key, std::string const& value) {        ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)            << ")\n";      };      auto CWriteMap = [&ofs](const char* key,                              std::map<std::string, std::string> const& map) {        for (auto const& item : map) {          ofs << "set(" << key << "_" << item.first << " "              << cmOutputConverter::EscapeForCMake(item.second) << ")\n";        }      };      // Write      ofs << "# Configurations\n";      CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");      CWrite("ARCC_VERBOSITY", this->Verbosity);      ofs << "# Settings file\n";      CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);      CWriteMap("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile);      ofs << "# Directories\n";      CWrite("ARCC_BUILD_DIR", this->Dir.Build);      CWrite("ARCC_INCLUDE_DIR", this->Dir.Include);      CWriteMap("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude);      ofs << "# Rcc executable\n";      CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);      CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->Rcc.ListOptions, ";"));      ofs << "# Rcc job\n";      CWrite("ARCC_LOCK_FILE", qrc.LockFile);      CWrite("ARCC_SOURCE", qrc.QrcFile);      CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);      CWrite("ARCC_OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.RccFile));      CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));      CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));    } else {      std::string err = "AutoRcc: Could not write file ";      err += qrc.InfoFile;      cmSystemTools::Error(err.c_str());      return false;    }  }  return true;}void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,                                                GeneratorT genType){  // Register source file in makefile  cmMakefile* makefile = this->Target->Target->GetMakefile();  {    cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);    gFile->SetProperty("GENERATED", "1");    gFile->SetProperty("SKIP_AUTOGEN", "On");  }  // Add source file to source group  AddToSourceGroup(makefile, filename, genType);  // Add source file to target  this->Target->AddSource(filename);}cmQtAutoGenInitializer::IntegerVersion cmQtAutoGenInitializer::GetQtVersion(  cmGeneratorTarget const* target){  cmQtAutoGenInitializer::IntegerVersion res;  cmMakefile* makefile = target->Target->GetMakefile();  // -- Major version  std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");  if (qtMajor.empty()) {    qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");  }  if (qtMajor.empty()) {    const char* dirprop = makefile->GetProperty("Qt5Core_VERSION_MAJOR");    if (dirprop) {      qtMajor = dirprop;    }  }  {    const char* targetQtVersion =      target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");    if (targetQtVersion != nullptr) {      qtMajor = targetQtVersion;    }  }  // -- Minor version  std::string qtMinor;  if (!qtMajor.empty()) {    if (qtMajor == "5") {      qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");      if (qtMinor.empty()) {        const char* dirprop = makefile->GetProperty("Qt5Core_VERSION_MINOR");        if (dirprop) {          qtMinor = dirprop;        }      }    }    if (qtMinor.empty()) {      qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");    }    {      const char* targetQtVersion =        target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION",                                                        "");      if (targetQtVersion != nullptr) {        qtMinor = targetQtVersion;      }    }  }  // -- Convert to integer  if (!qtMajor.empty() && !qtMinor.empty()) {    unsigned long majorUL(0);    unsigned long minorUL(0);    if (cmSystemTools::StringToULong(qtMajor.c_str(), &majorUL) &&        cmSystemTools::StringToULong(qtMinor.c_str(), &minorUL)) {      res.Major = static_cast<unsigned int>(majorUL);      res.Minor = static_cast<unsigned int>(minorUL);    }  }  return res;}bool cmQtAutoGenInitializer::GetMocExecutable(){  std::string err;  // Find moc executable  {    std::string targetName;    if (this->QtVersion.Major == 5) {      targetName = "Qt5::moc";    } else if (this->QtVersion.Major == 4) {      targetName = "Qt4::moc";    } else {      err = "The AUTOMOC feature supports only Qt 4 and Qt 5";    }    if (!targetName.empty()) {      cmLocalGenerator* localGen = this->Target->GetLocalGenerator();      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);      if (tgt != nullptr) {        this->Moc.Executable = tgt->ImportedGetLocation("");      } else {        err = "Could not find target " + targetName;      }    }  }  // Test moc command  if (err.empty()) {    if (cmSystemTools::FileExists(this->Moc.Executable, true)) {      std::vector<std::string> command;      command.push_back(this->Moc.Executable);      command.push_back("-h");      std::string stdOut;      std::string stdErr;      int retVal = 0;      bool result = cmSystemTools::RunSingleCommand(        command, &stdOut, &stdErr, &retVal, nullptr,        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);      if (!result) {        err = "The moc test command failed: ";        err += QuotedCommand(command);      }    } else {      err = "The moc executable ";      err += Quoted(this->Moc.Executable);      err += " does not exist";    }  }  // Print error  if (!err.empty()) {    std::string msg = "AutoMoc (";    msg += this->Target->GetName();    msg += "): ";    msg += err;    cmSystemTools::Error(msg.c_str());    return false;  }  return true;}bool cmQtAutoGenInitializer::GetUicExecutable(){  std::string err;  // Find uic executable  {    std::string targetName;    if (this->QtVersion.Major == 5) {      targetName = "Qt5::uic";    } else if (this->QtVersion.Major == 4) {      targetName = "Qt4::uic";    } else {      err = "The AUTOUIC feature supports only Qt 4 and Qt 5";    }    if (!targetName.empty()) {      cmLocalGenerator* localGen = this->Target->GetLocalGenerator();      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);      if (tgt != nullptr) {        this->Uic.Executable = tgt->ImportedGetLocation("");      } else {        if (this->QtVersion.Major == 5) {          // Project does not use Qt5Widgets, but has AUTOUIC ON anyway        } else {          err = "Could not find target " + targetName;        }      }    }  }  // Test uic command  if (err.empty() && !this->Uic.Executable.empty()) {    if (cmSystemTools::FileExists(this->Uic.Executable, true)) {      std::vector<std::string> command;      command.push_back(this->Uic.Executable);      command.push_back("-h");      std::string stdOut;      std::string stdErr;      int retVal = 0;      bool result = cmSystemTools::RunSingleCommand(        command, &stdOut, &stdErr, &retVal, nullptr,        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);      if (!result) {        err = "The uic test command failed: ";        err += QuotedCommand(command);      }    } else {      err = "The uic executable ";      err += Quoted(this->Uic.Executable);      err += " does not exist";    }  }  // Print error  if (!err.empty()) {    std::string msg = "AutoUic (";    msg += this->Target->GetName();    msg += "): ";    msg += err;    cmSystemTools::Error(msg.c_str());    return false;  }  return true;}bool cmQtAutoGenInitializer::GetRccExecutable(){  std::string err;  // Find rcc executable  {    std::string targetName;    if (this->QtVersion.Major == 5) {      targetName = "Qt5::rcc";    } else if (this->QtVersion.Major == 4) {      targetName = "Qt4::rcc";    } else {      err = "The AUTORCC feature supports only Qt 4 and Qt 5";    }    if (!targetName.empty()) {      cmLocalGenerator* localGen = this->Target->GetLocalGenerator();      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);      if (tgt != nullptr) {        this->Rcc.Executable = tgt->ImportedGetLocation("");      } else {        err = "Could not find target " + targetName;      }    }  }  // Test rcc command  if (err.empty()) {    if (cmSystemTools::FileExists(this->Rcc.Executable, true)) {      std::vector<std::string> command;      command.push_back(this->Rcc.Executable);      command.push_back("-h");      std::string stdOut;      std::string stdErr;      int retVal = 0;      bool result = cmSystemTools::RunSingleCommand(        command, &stdOut, &stdErr, &retVal, nullptr,        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);      if (result) {        // Detect if rcc supports (-)-list        if (this->QtVersion.Major == 5) {          if (stdOut.find("--list") != std::string::npos) {            this->Rcc.ListOptions.push_back("--list");          } else {            this->Rcc.ListOptions.push_back("-list");          }        }      } else {        err = "The rcc test command failed: ";        err += QuotedCommand(command);      }    } else {      err = "The rcc executable ";      err += Quoted(this->Rcc.Executable);      err += " does not exist";    }  }  // Print error  if (!err.empty()) {    std::string msg = "AutoRcc (";    msg += this->Target->GetName();    msg += "): ";    msg += err;    cmSystemTools::Error(msg.c_str());    return false;  }  return true;}/// @brief Reads the resource files list from from a .qrc file/// @arg fileName Must be the absolute path of the .qrc file/// @return True if the rcc file was successfully readbool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName,                                           std::vector<std::string>& files,                                           std::string& error){  if (!cmSystemTools::FileExists(fileName)) {    error = "rcc resource file does not exist:\n  ";    error += Quoted(fileName);    error += "\n";    return false;  }  if (!this->Rcc.ListOptions.empty()) {    // Use rcc for file listing    if (this->Rcc.Executable.empty()) {      error = "rcc executable not available";      return false;    }    // Run rcc list command in the directory of the qrc file with the    // pathless    // qrc file name argument. This way rcc prints relative paths.    // This avoids issues on Windows when the qrc file is in a path that    // contains non-ASCII characters.    std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);    std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);    bool result = false;    int retVal = 0;    std::string rccStdOut;    std::string rccStdErr;    {      std::vector<std::string> cmd;      cmd.push_back(this->Rcc.Executable);      cmd.insert(cmd.end(), this->Rcc.ListOptions.begin(),                 this->Rcc.ListOptions.end());      cmd.push_back(fileNameName);      result = cmSystemTools::RunSingleCommand(        cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);    }    if (!result || retVal) {      error = "rcc list process failed for:\n  ";      error += Quoted(fileName);      error += "\n";      error += rccStdOut;      error += "\n";      error += rccStdErr;      error += "\n";      return false;    }    if (!RccListParseOutput(rccStdOut, rccStdErr, files, error)) {      return false;    }  } else {    // We can't use rcc for the file listing.    // Read the qrc file content into string and parse it.    {      std::string qrcContents;      {        cmsys::ifstream ifs(fileName.c_str());        if (ifs) {          std::ostringstream osst;          osst << ifs.rdbuf();          qrcContents = osst.str();        } else {          error = "rcc file not readable:\n  ";          error += Quoted(fileName);          error += "\n";          return false;        }      }      // Parse string content      RccListParseContent(qrcContents, files);    }  }  // Convert relative paths to absolute paths  RccListConvertFullPath(cmSystemTools::GetFilenamePath(fileName), files);  return true;}
 |