| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091 | /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying   file Copyright.txt or https://cmake.org/licensing for details.  */#include "cmQtAutoGen.h"#include "cmQtAutoGeneratorInitializer.h"#include "cmAlgorithms.h"#include "cmCustomCommand.h"#include "cmCustomCommandLines.h"#include "cmFilePathChecksum.h"#include "cmGeneratorTarget.h"#include "cmGlobalGenerator.h"#include "cmLocalGenerator.h"#include "cmMakefile.h"#include "cmOutputConverter.h"#include "cmPolicies.h"#include "cmSourceFile.h"#include "cmSourceGroup.h"#include "cmState.h"#include "cmSystemTools.h"#include "cmTarget.h"#include "cm_sys_stat.h"#include "cmake.h"#include "cmsys/FStream.hxx"#include <algorithm>#include <array>#include <map>#include <set>#include <sstream>#include <string>#include <utility>#include <vector>inline static const char* SafeString(const char* value){  return (value != nullptr) ? value : "";}inline static std::string GetSafeProperty(cmGeneratorTarget const* target,                                          const char* key){  return std::string(SafeString(target->GetProperty(key)));}inline static std::string GetSafeProperty(cmSourceFile const* sf,                                          const char* key){  return std::string(SafeString(sf->GetProperty(key)));}inline static bool AutogenMultiConfig(cmGlobalGenerator* globalGen){  return globalGen->IsMultiConfig();}static std::string GetAutogenTargetName(cmGeneratorTarget const* target){  std::string autogenTargetName = target->GetName();  autogenTargetName += "_autogen";  return autogenTargetName;}static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target){  cmMakefile* makefile = target->Target->GetMakefile();  std::string targetDir = makefile->GetCurrentBinaryDirectory();  targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();  targetDir += "/";  targetDir += GetAutogenTargetName(target);  targetDir += ".dir";  return targetDir;}static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target){  std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR");  if (targetDir.empty()) {    cmMakefile* makefile = target->Target->GetMakefile();    targetDir = makefile->GetCurrentBinaryDirectory();    targetDir += "/";    targetDir += GetAutogenTargetName(target);  }  return targetDir;}std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion(  cmGeneratorTarget const* target){  cmMakefile* makefile = target->Target->GetMakefile();  std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");  if (qtMajor.empty()) {    qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");  }  const char* targetQtVersion =    target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");  if (targetQtVersion != nullptr) {    qtMajor = targetQtVersion;  }  return qtMajor;}std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion(  cmGeneratorTarget const* target, const std::string& qtVersionMajor){  cmMakefile* makefile = target->Target->GetMakefile();  std::string qtMinor;  if (qtVersionMajor == "5") {    qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");  }  if (qtMinor.empty()) {    qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");  }  const char* targetQtVersion =    target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");  if (targetQtVersion != nullptr) {    qtMinor = targetQtVersion;  }  return qtMinor;}static bool QtVersionGreaterOrEqual(const std::string& major,                                    const std::string& minor,                                    unsigned long requestMajor,                                    unsigned long requestMinor){  unsigned long majorUL(0);  unsigned long minorUL(0);  if (cmSystemTools::StringToULong(major.c_str(), &majorUL) &&      cmSystemTools::StringToULong(minor.c_str(), &minorUL)) {    return (majorUL > requestMajor) ||      (majorUL == requestMajor && minorUL >= requestMinor);  }  return false;}static std::vector<std::string> GetConfigurations(  cmMakefile* makefile, std::string* config = nullptr){  std::vector<std::string> configs;  {    std::string cfg = makefile->GetConfigurations(configs);    if (config != nullptr) {      *config = cfg;    }  }  // Add empty configuration on demand  if (configs.empty()) {    configs.push_back("");  }  return configs;}static std::vector<std::string> GetConfigurationSuffixes(cmMakefile* makefile){  std::vector<std::string> suffixes;  if (AutogenMultiConfig(makefile->GetGlobalGenerator())) {    makefile->GetConfigurations(suffixes);    for (std::string& suffix : suffixes) {      suffix.insert(0, "_");    }  }  if (suffixes.empty()) {    suffixes.push_back("");  }  return suffixes;}static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,                                 const std::string& value){  makefile->AddDefinition(key,                          cmOutputConverter::EscapeForCMake(value).c_str());}static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,                                 const std::vector<std::string>& values){  makefile->AddDefinition(    key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());}static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,                                 const std::set<std::string>& values){  makefile->AddDefinition(    key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());}static void AddDefinitionEscaped(  cmMakefile* makefile, const char* key,  const std::vector<std::vector<std::string>>& lists){  std::vector<std::string> seplist;  for (const std::vector<std::string>& list : lists) {    std::string blist = "{";    blist += cmJoin(list, ";");    blist += "}";    seplist.push_back(std::move(blist));  }  makefile->AddDefinition(key, cmOutputConverter::EscapeForCMake(                                 cmJoin(seplist, cmQtAutoGen::listSep))                                 .c_str());}static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName,                             cmQtAutoGen::GeneratorType 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::MOC:          props[0] = "AUTOMOC_SOURCE_GROUP";          break;        case cmQtAutoGen::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, const std::string& fileName){  makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fileName.c_str(),                           false);}static void AddGeneratedSource(cmGeneratorTarget* target,                               const std::string& filename,                               cmQtAutoGen::GeneratorType genType){  cmMakefile* makefile = target->Target->GetMakefile();  {    cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);    gFile->SetProperty("GENERATED", "1");    gFile->SetProperty("SKIP_AUTOGEN", "On");  }  target->AddSource(filename);  AddToSourceGroup(makefile, filename, genType);}struct cmQtAutoGenSetup{  std::set<std::string> MocSkip;  std::set<std::string> UicSkip;  std::map<std::string, std::string> ConfigMocIncludes;  std::map<std::string, std::string> ConfigMocDefines;  std::map<std::string, std::string> ConfigUicOptions;};static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest,                                  cmQtAutoGenSetup& setup){  // Read skip files from makefile sources  {    const std::vector<cmSourceFile*>& allSources =      digest.Target->Makefile->GetSourceFiles();    for (cmSourceFile* sf : allSources) {      // sf->GetExtension() is only valid after sf->GetFullPath() ...      const std::string& fPath = sf->GetFullPath();      const cmSystemTools::FileFormat 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 = digest.MocEnabled &&        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));      const bool uicSkip = digest.UicEnabled &&        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));      if (mocSkip || uicSkip) {        const std::string absFile = cmSystemTools::GetRealPath(fPath);        if (mocSkip) {          setup.MocSkip.insert(absFile);        }        if (uicSkip) {          setup.UicSkip.insert(absFile);        }      }    }  }}static void SetupAutoTargetMoc(const cmQtAutoGenDigest& digest,                               std::string const& config,                               std::vector<std::string> const& configs,                               cmQtAutoGenSetup& setup){  cmGeneratorTarget const* target = digest.Target;  cmLocalGenerator* localGen = target->GetLocalGenerator();  cmMakefile* makefile = target->Target->GetMakefile();  AddDefinitionEscaped(makefile, "_moc_skip", setup.MocSkip);  AddDefinitionEscaped(makefile, "_moc_options",                       GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"                                                                    : "FALSE");  AddDefinitionEscaped(makefile, "_moc_macro_names",                       GetSafeProperty(target, "AUTOMOC_MACRO_NAMES"));  AddDefinitionEscaped(makefile, "_moc_depend_filters",                       GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));  if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor, 5,                              8)) {    AddDefinitionEscaped(      makefile, "_moc_predefs_cmd",      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));  }  // Moc includes and compile definitions  {    auto GetCompileDefinitionsAndDirectories = [target, localGen](      const std::string& cfg, std::string& incs, std::string& defs) {      {        std::vector<std::string> includeDirs;        // Get the include dirs for this target, without stripping the implicit        // include dirs off, see        // https://gitlab.kitware.com/cmake/cmake/issues/13667        localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg,                                        false);        incs = cmJoin(includeDirs, ";");      }      {        std::set<std::string> defines;        localGen->AddCompileDefinitions(defines, target, cfg, "CXX");        defs += cmJoin(defines, ";");      }    };    // Default settings    std::string incs;    std::string compileDefs;    GetCompileDefinitionsAndDirectories(config, incs, compileDefs);    AddDefinitionEscaped(makefile, "_moc_incs", incs);    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);    // Configuration specific settings    for (const std::string& cfg : configs) {      std::string configIncs;      std::string configCompileDefs;      GetCompileDefinitionsAndDirectories(cfg, configIncs, configCompileDefs);      if (configIncs != incs) {        setup.ConfigMocIncludes[cfg] = configIncs;      }      if (configCompileDefs != compileDefs) {        setup.ConfigMocDefines[cfg] = configCompileDefs;      }    }  }  // Moc executable  {    std::string mocExec;    std::string err;    if (digest.QtVersionMajor == "5") {      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");      if (tgt != nullptr) {        mocExec = SafeString(tgt->ImportedGetLocation(""));      } else {        err = "AUTOMOC: Qt5::moc target not found";      }    } else if (digest.QtVersionMajor == "4") {      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");      if (tgt != nullptr) {        mocExec = SafeString(tgt->ImportedGetLocation(""));      } else {        err = "AUTOMOC: Qt4::moc target not found";      }    } else {      err = "The AUTOMOC feature supports only Qt 4 and Qt 5";    }    if (err.empty()) {      AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);    } else {      err += " (" + target->GetName() + ")";      cmSystemTools::Error(err.c_str());    }  }}static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest,                               std::string const& config,                               std::vector<std::string> const& configs,                               cmQtAutoGenSetup& setup){  cmGeneratorTarget const* target = digest.Target;  cmMakefile* makefile = target->Target->GetMakefile();  AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip);  // Uic search paths  {    std::vector<std::string> uicSearchPaths;    {      const std::string usp = GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS");      if (!usp.empty()) {        cmSystemTools::ExpandListArgument(usp, uicSearchPaths);        const std::string srcDir = makefile->GetCurrentSourceDirectory();        for (std::string& path : uicSearchPaths) {          path = cmSystemTools::CollapseFullPath(path, srcDir);        }      }    }    AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);  }  // Uic target options  {    auto UicGetOpts = [target](const std::string& cfg) -> std::string {      std::vector<std::string> opts;      target->GetAutoUicOptions(opts, cfg);      return cmJoin(opts, ";");    };    // Default settings    const std::string uicOpts = UicGetOpts(config);    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);    // Configuration specific settings    for (const std::string& cfg : configs) {      const std::string configUicOpts = UicGetOpts(cfg);      if (configUicOpts != uicOpts) {        setup.ConfigUicOptions[cfg] = configUicOpts;      }    }  }  // Uic files options  {    std::vector<std::string> uiFileFiles;    std::vector<std::vector<std::string>> uiFileOptions;    {      const std::string uiExt = "ui";      const std::vector<cmSourceFile*>& srcFiles = makefile->GetSourceFiles();      for (cmSourceFile* sf : srcFiles) {        // sf->GetExtension() is only valid after sf->GetFullPath() ...        const std::string& fPath = sf->GetFullPath();        if (sf->GetExtension() == uiExt) {          // Check if the files has uic options          const std::string uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");          if (!uicOpts.empty()) {            const std::string absFile = cmSystemTools::GetRealPath(fPath);            // Check if file isn't skipped            if (setup.UicSkip.count(absFile) == 0) {              uiFileFiles.push_back(absFile);              std::vector<std::string> optsVec;              cmSystemTools::ExpandListArgument(uicOpts, optsVec);              uiFileOptions.push_back(std::move(optsVec));            }          }        }      }    }    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);  }  // Uic executable  {    std::string err;    std::string uicExec;    cmLocalGenerator* localGen = target->GetLocalGenerator();    if (digest.QtVersionMajor == "5") {      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");      if (tgt != nullptr) {        uicExec = SafeString(tgt->ImportedGetLocation(""));      } else {        // Project does not use Qt5Widgets, but has AUTOUIC ON anyway      }    } else if (digest.QtVersionMajor == "4") {      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");      if (tgt != nullptr) {        uicExec = SafeString(tgt->ImportedGetLocation(""));      } else {        err = "AUTOUIC: Qt4::uic target not found";      }    } else {      err = "The AUTOUIC feature supports only Qt 4 and Qt 5";    }    if (err.empty()) {      AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);    } else {      err += " (" + target->GetName() + ")";      cmSystemTools::Error(err.c_str());    }  }}static std::string RccGetExecutable(cmGeneratorTarget const* target,                                    const std::string& qtMajorVersion){  std::string rccExec;  std::string err;  cmLocalGenerator* localGen = target->GetLocalGenerator();  if (qtMajorVersion == "5") {    cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc");    if (tgt != nullptr) {      rccExec = SafeString(tgt->ImportedGetLocation(""));    } else {      err = "AUTORCC: Qt5::rcc target not found";    }  } else if (qtMajorVersion == "4") {    cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc");    if (tgt != nullptr) {      rccExec = SafeString(tgt->ImportedGetLocation(""));    } else {      err = "AUTORCC: Qt4::rcc target not found";    }  } else {    err = "The AUTORCC feature supports only Qt 4 and Qt 5";  }  if (!err.empty()) {    err += " (" + target->GetName() + ")";    cmSystemTools::Error(err.c_str());  }  return rccExec;}static void SetupAutoTargetRcc(const cmQtAutoGenDigest& digest){  std::vector<std::string> rccFiles;  std::vector<std::string> rccBuilds;  std::vector<std::vector<std::string>> rccOptions;  std::vector<std::vector<std::string>> rccInputs;  for (const cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {    rccFiles.push_back(qrcDigest.QrcFile);    rccBuilds.push_back(qrcDigest.RccFile);    rccOptions.push_back(qrcDigest.Options);    rccInputs.push_back(qrcDigest.Resources);  }  cmMakefile* makefile = digest.Target->Target->GetMakefile();  AddDefinitionEscaped(makefile, "_qt_rcc_executable",                       RccGetExecutable(digest.Target, digest.QtVersionMajor));  AddDefinitionEscaped(makefile, "_rcc_files", rccFiles);  AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds);  AddDefinitionEscaped(makefile, "_rcc_options", rccOptions);  AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs);}void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(  cmQtAutoGenDigest& digest){  cmGeneratorTarget* target = digest.Target;  cmMakefile* makefile = target->Target->GetMakefile();  cmLocalGenerator* localGen = target->GetLocalGenerator();  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();  // Create a custom target for running generators at buildtime  const bool multiConfig = AutogenMultiConfig(globalGen);  const std::string autogenTargetName = GetAutogenTargetName(target);  const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);  const std::string workingDirectory =    cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());  const std::vector<std::string> suffixes = GetConfigurationSuffixes(makefile);  std::set<std::string> autogenDependFiles;  std::set<std::string> autogenDependTargets;  std::vector<std::string> autogenProvides;  // Remove build directories on cleanup  AddCleanFile(makefile, autogenBuildDir);  // Remove old settings on cleanup  {    std::string base = GetAutogenTargetFilesDir(target);    base += "/AutogenOldSettings";    for (const std::string& suffix : suffixes) {      AddCleanFile(makefile, (base + suffix).append(".cmake"));    }  }  // Compose command lines  cmCustomCommandLines commandLines;  {    cmCustomCommandLine currentLine;    currentLine.push_back(cmSystemTools::GetCMakeCommand());    currentLine.push_back("-E");    currentLine.push_back("cmake_autogen");    currentLine.push_back(GetAutogenTargetFilesDir(target));    currentLine.push_back("$<CONFIGURATION>");    commandLines.push_back(currentLine);  }  // Compose target comment  std::string autogenComment;  {    std::vector<std::string> toolNames;    if (digest.MocEnabled) {      toolNames.push_back("MOC");    }    if (digest.UicEnabled) {      toolNames.push_back("UIC");    }    if (digest.RccEnabled) {      toolNames.push_back("RCC");    }    std::string tools = toolNames[0];    toolNames.erase(toolNames.begin());    while (toolNames.size() > 1) {      tools += ", " + toolNames[0];      toolNames.erase(toolNames.begin());    }    if (toolNames.size() == 1) {      tools += " and " + toolNames[0];    }    autogenComment = "Automatic " + tools + " for target " + target->GetName();  }  // Add moc compilation to generated files list  if (digest.MocEnabled) {    const std::string mocsComp = autogenBuildDir + "/mocs_compilation.cpp";    AddGeneratedSource(target, mocsComp, cmQtAutoGen::MOC);    autogenProvides.push_back(mocsComp);  }  // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES  if (digest.MocEnabled || digest.UicEnabled) {    std::string includeDir = autogenBuildDir + "/include";    if (multiConfig) {      includeDir += "_$<CONFIG>";    }    target->AddIncludeDirectory(includeDir, true);  }  // Extract relevant source files  std::vector<std::string> generatedSources;  std::vector<std::string> generatedHeaders;  {    const std::string qrcExt = "qrc";    std::vector<cmSourceFile*> srcFiles;    target->GetConfigCommonSourceFiles(srcFiles);    for (cmSourceFile* sf : srcFiles) {      if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {        continue;      }      // sf->GetExtension() is only valid after sf->GetFullPath() ...      const std::string& fPath = sf->GetFullPath();      const std::string& ext = sf->GetExtension();      // Register generated files that will be scanned by moc or uic      if (digest.MocEnabled || digest.UicEnabled) {        const cmSystemTools::FileFormat fileType =          cmSystemTools::GetFileFormat(ext.c_str());        if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||            (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {          const std::string absPath = cmSystemTools::GetRealPath(fPath);          if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||              (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {            // Register source            const bool generated = sf->GetPropertyAsBool("GENERATED");            if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {              if (generated) {                generatedHeaders.push_back(absPath);              } else {                digest.Headers.push_back(absPath);              }            } else {              if (generated) {                generatedSources.push_back(absPath);              } else {                digest.Sources.push_back(absPath);              }            }          }        }      }      // Register rcc enabled files      if (digest.RccEnabled && (ext == qrcExt) &&          !sf->GetPropertyAsBool("SKIP_AUTORCC")) {        // Register qrc file        {          cmQtAutoGenDigestQrc qrcDigest;          qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath);          qrcDigest.QrcName =            cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile);          qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED");          // RCC options          {            const std::string opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");            if (!opts.empty()) {              cmSystemTools::ExpandListArgument(opts, qrcDigest.Options);            }          }          digest.Qrcs.push_back(std::move(qrcDigest));        }      }    }    // 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.    target->ClearSourcesCache();  }  // Process GENERATED sources and headers  if (!generatedSources.empty() || !generatedHeaders.empty()) {    // Check status of policy CMP0071    bool policyAccept = false;    bool policyWarn = false;    const cmPolicies::PolicyStatus CMP0071_status =      target->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 (const std::string& absFile : generatedHeaders) {        digest.Headers.push_back(absFile);        autogenDependFiles.insert(absFile);      }      for (const std::string& absFile : generatedSources) {        digest.Sources.push_back(absFile);        autogenDependFiles.insert(absFile);      }    } else {      if (policyWarn) {        std::string msg;        msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);        msg += "\n";        std::string tools;        if (digest.MocEnabled) {          tools += "AUTOMOC";        }        if (digest.UicEnabled) {          if (!tools.empty()) {            tools += ",";          }          tools += "AUTOUIC";        }        if (!generatedHeaders.empty()) {          msg.append(tools).append(": Ignoring GENERATED header file(s):\n");          for (const std::string& absFile : generatedHeaders) {            msg.append("  ").append(cmQtAutoGen::Quoted(absFile)).append("\n");          }        }        if (!generatedSources.empty()) {          msg.append(tools).append(": Ignoring GENERATED source file(s):\n");          for (const std::string& absFile : generatedSources) {            msg.append("  ").append(cmQtAutoGen::Quoted(absFile)).append("\n");          }        }        makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);      }    }  }  // Sort headers and sources  std::sort(digest.Headers.begin(), digest.Headers.end());  std::sort(digest.Sources.begin(), digest.Sources.end());  // Process qrc files  if (!digest.Qrcs.empty()) {    const bool QtV5 = (digest.QtVersionMajor == "5");    const std::string rcc = RccGetExecutable(target, digest.QtVersionMajor);    // Target rcc options    std::vector<std::string> optionsTarget;    cmSystemTools::ExpandListArgument(      GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget);    // Check if file name is unique    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {      qrcDigest.Unique = true;      for (const cmQtAutoGenDigestQrc& qrcDig2 : digest.Qrcs) {        if ((&qrcDigest != &qrcDig2) &&            (qrcDigest.QrcName == qrcDig2.QrcName)) {          qrcDigest.Unique = false;          break;        }      }    }    // Path checksum    {      const cmFilePathChecksum fpathCheckSum(makefile);      for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {        qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile);        // RCC output file name        std::string rccFile = autogenBuildDir + "/";        rccFile += qrcDigest.PathChecksum;        rccFile += "/qrc_";        rccFile += qrcDigest.QrcName;        rccFile += ".cpp";        qrcDigest.RccFile = std::move(rccFile);      }    }    // RCC options    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {      // Target options      std::vector<std::string> opts = optionsTarget;      // Merge computed "-name XYZ" option      {        std::string name = qrcDigest.QrcName;        // Replace '-' with '_'. The former is not valid for symbol names.        std::replace(name.begin(), name.end(), '-', '_');        if (!qrcDigest.Unique) {          name += "_";          name += qrcDigest.PathChecksum;        }        std::vector<std::string> nameOpts;        nameOpts.emplace_back("-name");        nameOpts.emplace_back(std::move(name));        cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5);      }      // Merge file option      cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5);      qrcDigest.Options = std::move(opts);    }    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {      // Register file at target      AddGeneratedSource(target, qrcDigest.RccFile, cmQtAutoGen::RCC);      autogenProvides.push_back(qrcDigest.RccFile);      // Dependencies      if (qrcDigest.Generated) {        // Add the GENERATED .qrc file to the dependencies        autogenDependFiles.insert(qrcDigest.QrcFile);      } else {        // Add the resource files to the dependencies        {          std::string error;          if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,                                         qrcDigest.QrcFile,                                         qrcDigest.Resources, &error)) {            for (const std::string& fileName : qrcDigest.Resources) {              autogenDependFiles.insert(fileName);            }          } else {            cmSystemTools::Error(error.c_str());          }        }        // Run cmake again when .qrc file changes        makefile->AddCMakeDependFile(qrcDigest.QrcFile);      }    }  }  // Add user defined autogen target dependencies  {    const std::string deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS");    if (!deps.empty()) {      std::vector<std::string> extraDeps;      cmSystemTools::ExpandListArgument(deps, extraDeps);      for (const std::string& depName : extraDeps) {        // Allow target and file dependencies        auto* depTarget = makefile->FindTargetToUse(depName);        if (depTarget != nullptr) {          autogenDependTargets.insert(depTarget->GetName());        } else {          autogenDependFiles.insert(depName);        }      }    }  }  // 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 (!autogenDependFiles.empty()) {      usePRE_BUILD = false;    }  }  // Create the autogen target/command  if (usePRE_BUILD) {    // Add additional autogen target dependencies to origin target    for (const std::string& depTarget : autogenDependTargets) {      target->Target->AddUtility(depTarget, 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(),                       workingDirectory.c_str());    cc.SetEscapeOldStyle(false);    cc.SetEscapeAllowMakeVars(true);    target->Target->AddPreBuildCommand(cc);  } else {    // Add utility target dependencies to the autogen target dependencies    for (const std::string& depTarget : target->Target->GetUtilities()) {      autogenDependTargets.insert(depTarget);    }    // Add link library target dependencies to the autogen target dependencies    for (const auto& item : target->Target->GetOriginalLinkLibraries()) {      if (makefile->FindTargetToUse(item.first) != nullptr) {        autogenDependTargets.insert(item.first);      }    }    // Convert file dependencies std::set to std::vector    const std::vector<std::string> autogenDepends(autogenDependFiles.begin(),                                                  autogenDependFiles.end());    // Create autogen target    cmTarget* autogenTarget = makefile->AddUtilityCommand(      autogenTargetName, true, workingDirectory.c_str(),      /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,      autogenComment.c_str());    // Create autogen generator target    localGen->AddGeneratorTarget(      new cmGeneratorTarget(autogenTarget, localGen));    // Add additional autogen target dependencies to autogen target    for (const std::string& depTarget : autogenDependTargets) {      autogenTarget->AddUtility(depTarget, makefile);    }    // Set FOLDER property in autogen target    {      const char* autogenFolder =        makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");      if (autogenFolder == nullptr) {        autogenFolder =          makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");      }      // Inherit FOLDER property from target (#13688)      if (autogenFolder == nullptr) {        autogenFolder = SafeString(target->Target->GetProperty("FOLDER"));      }      if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {        autogenTarget->SetProperty("FOLDER", autogenFolder);      }    }    // Add autogen target to the origin target dependencies    target->Target->AddUtility(autogenTargetName, makefile);  }}void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(  const cmQtAutoGenDigest& digest){  cmGeneratorTarget const* target = digest.Target;  cmMakefile* makefile = target->Target->GetMakefile();  // forget the variables added here afterwards again:  cmMakefile::ScopePushPop varScope(makefile);  static_cast<void>(varScope);  // Get configurations  std::string config;  const std::vector<std::string> configs(GetConfigurations(makefile, &config));  // Configuration suffixes  std::map<std::string, std::string> configSuffix;  if (AutogenMultiConfig(target->GetGlobalGenerator())) {    for (const std::string& cfg : configs) {      configSuffix[cfg] = "_" + cfg;    }  }  // Configurations settings buffers  cmQtAutoGenSetup setup;  // Basic setup  AddDefinitionEscaped(makefile, "_build_dir",                       GetAutogenTargetBuildDir(target));  AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);  AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);  AddDefinitionEscaped(makefile, "_sources", digest.Sources);  AddDefinitionEscaped(makefile, "_headers", digest.Headers);  {    if (digest.MocEnabled || digest.UicEnabled) {      SetupAcquireSkipFiles(digest, setup);      if (digest.MocEnabled) {        SetupAutoTargetMoc(digest, config, configs, setup);      }      if (digest.UicEnabled) {        SetupAutoTargetUic(digest, config, configs, setup);      }    }    if (digest.RccEnabled) {      SetupAutoTargetRcc(digest);    }  }  // Generate info file  std::string infoFile = GetAutogenTargetFilesDir(target);  infoFile += "/AutogenInfo.cmake";  {    std::string inf = cmSystemTools::GetCMakeRoot();    inf += "/Modules/AutogenInfo.cmake.in";    makefile->ConfigureFile(inf.c_str(), infoFile.c_str(), false, true, false);  }  // Append custom definitions to info file on demand  if (!configSuffix.empty() || !setup.ConfigMocDefines.empty() ||      !setup.ConfigMocIncludes.empty() || !setup.ConfigUicOptions.empty()) {    // Ensure we have write permission in case .in was read-only.    mode_t perm = 0;#if defined(_WIN32) && !defined(__CYGWIN__)    mode_t mode_write = S_IWRITE;#else    mode_t mode_write = S_IWUSR;#endif    cmSystemTools::GetPermissions(infoFile, perm);    if (!(perm & mode_write)) {      cmSystemTools::SetPermissions(infoFile, perm | mode_write);    }    // Open and write file    cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);    if (ofs) {      auto OfsWriteMap = [&ofs](        const char* key, const std::map<std::string, std::string>& map) {        for (const auto& item : map) {          ofs << "set(" << key << "_" << item.first << " "              << cmOutputConverter::EscapeForCMake(item.second) << ")\n";        }      };      ofs << "# Configuration specific options\n";      OfsWriteMap("AM_CONFIG_SUFFIX", configSuffix);      OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines);      OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes);      OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions);    } else {      // File open error      std::string error = "Internal CMake error when trying to open file: ";      error += cmQtAutoGen::Quoted(infoFile);      error += " for writing.";      cmSystemTools::Error(error.c_str());    }  }}
 |