| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmQtAutoMocUic.h"
- #include <algorithm>
- #include <array>
- #include <list>
- #include <set>
- #include <sstream>
- #include <utility>
- #include "cm_memory.hxx"
- #include "cmAlgorithms.h"
- #include "cmCryptoHash.h"
- #include "cmGeneratedFileStream.h"
- #include "cmMakefile.h"
- #include "cmQtAutoGen.h"
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- #include "cmake.h"
- #include "cmsys/FStream.hxx"
- #if defined(__APPLE__)
- # include <unistd.h>
- #endif
- static constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
- static constexpr std::size_t UiUnderscoreLength = 3; // Length of "ui_"
- cmQtAutoMocUic::IncludeKeyT::IncludeKeyT(std::string const& key,
- std::size_t basePrefixLength)
- : Key(key)
- , Dir(SubDirPrefix(key))
- , Base(cmSystemTools::GetFilenameWithoutLastExtension(key))
- {
- if (basePrefixLength != 0) {
- Base = Base.substr(basePrefixLength);
- }
- }
- void cmQtAutoMocUic::ParseCacheT::FileT::Clear()
- {
- Moc.Macro.clear();
- Moc.Include.Underscore.clear();
- Moc.Include.Dot.clear();
- Moc.Depends.clear();
- Uic.Include.clear();
- Uic.Depends.clear();
- }
- cmQtAutoMocUic::ParseCacheT::FileHandleT cmQtAutoMocUic::ParseCacheT::Get(
- std::string const& fileName) const
- {
- auto it = Map_.find(fileName);
- if (it != Map_.end()) {
- return it->second;
- }
- return FileHandleT();
- }
- cmQtAutoMocUic::ParseCacheT::GetOrInsertT
- cmQtAutoMocUic::ParseCacheT::GetOrInsert(std::string const& fileName)
- {
- // Find existing entry
- {
- auto it = Map_.find(fileName);
- if (it != Map_.end()) {
- return GetOrInsertT{ it->second, false };
- }
- }
- // Insert new entry
- return GetOrInsertT{
- Map_.emplace(fileName, std::make_shared<FileT>()).first->second, true
- };
- }
- cmQtAutoMocUic::ParseCacheT::ParseCacheT() = default;
- cmQtAutoMocUic::ParseCacheT::~ParseCacheT() = default;
- void cmQtAutoMocUic::ParseCacheT::Clear()
- {
- Map_.clear();
- }
- bool cmQtAutoMocUic::ParseCacheT::ReadFromFile(std::string const& fileName)
- {
- cmsys::ifstream fin(fileName.c_str());
- if (!fin) {
- return false;
- }
- FileHandleT fileHandle;
- std::string line;
- while (std::getline(fin, line)) {
- // Check if this an empty or a comment line
- if (line.empty() || line.front() == '#') {
- continue;
- }
- // Drop carriage return character at the end
- if (line.back() == '\r') {
- line.pop_back();
- if (line.empty()) {
- continue;
- }
- }
- // Check if this a file name line
- if (line.front() != ' ') {
- fileHandle = GetOrInsert(line).first;
- continue;
- }
- // Bad line or bad file handle
- if (!fileHandle || (line.size() < 6)) {
- continue;
- }
- constexpr std::size_t offset = 5;
- if (cmHasLiteralPrefix(line, " mmc:")) {
- fileHandle->Moc.Macro = line.substr(offset);
- continue;
- }
- if (cmHasLiteralPrefix(line, " miu:")) {
- fileHandle->Moc.Include.Underscore.emplace_back(line.substr(offset),
- MocUnderscoreLength);
- continue;
- }
- if (cmHasLiteralPrefix(line, " mid:")) {
- fileHandle->Moc.Include.Dot.emplace_back(line.substr(offset), 0);
- continue;
- }
- if (cmHasLiteralPrefix(line, " mdp:")) {
- fileHandle->Moc.Depends.emplace_back(line.substr(offset));
- continue;
- }
- if (cmHasLiteralPrefix(line, " uic:")) {
- fileHandle->Uic.Include.emplace_back(line.substr(offset),
- UiUnderscoreLength);
- continue;
- }
- if (cmHasLiteralPrefix(line, " udp:")) {
- fileHandle->Uic.Depends.emplace_back(line.substr(offset));
- continue;
- }
- }
- return true;
- }
- bool cmQtAutoMocUic::ParseCacheT::WriteToFile(std::string const& fileName)
- {
- cmGeneratedFileStream ofs(fileName);
- if (!ofs) {
- return false;
- }
- ofs << "# Generated by CMake. Changes will be overwritten." << std::endl;
- for (auto const& pair : Map_) {
- ofs << pair.first << std::endl;
- FileT const& file = *pair.second;
- if (!file.Moc.Macro.empty()) {
- ofs << " mmc:" << file.Moc.Macro << std::endl;
- }
- for (IncludeKeyT const& item : file.Moc.Include.Underscore) {
- ofs << " miu:" << item.Key << std::endl;
- }
- for (IncludeKeyT const& item : file.Moc.Include.Dot) {
- ofs << " mid:" << item.Key << std::endl;
- }
- for (std::string const& item : file.Moc.Depends) {
- ofs << " mdp:" << item << std::endl;
- }
- for (IncludeKeyT const& item : file.Uic.Include) {
- ofs << " uic:" << item.Key << std::endl;
- }
- for (std::string const& item : file.Uic.Depends) {
- ofs << " udp:" << item << std::endl;
- }
- }
- return ofs.Close();
- }
- cmQtAutoMocUic::BaseSettingsT::BaseSettingsT() = default;
- cmQtAutoMocUic::BaseSettingsT::~BaseSettingsT() = default;
- cmQtAutoMocUic::MocSettingsT::MocSettingsT()
- {
- RegExpInclude.compile(
- "(^|\n)[ \t]*#[ \t]*include[ \t]+"
- "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
- }
- cmQtAutoMocUic::MocSettingsT::~MocSettingsT() = default;
- bool cmQtAutoMocUic::MocSettingsT::skipped(std::string const& fileName) const
- {
- return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
- }
- std::string cmQtAutoMocUic::MocSettingsT::MacrosString() const
- {
- std::string res;
- const auto itB = MacroFilters.cbegin();
- const auto itE = MacroFilters.cend();
- const auto itL = itE - 1;
- auto itC = itB;
- for (; itC != itE; ++itC) {
- // Separator
- if (itC != itB) {
- if (itC != itL) {
- res += ", ";
- } else {
- res += " or ";
- }
- }
- // Key
- res += itC->Key;
- }
- return res;
- }
- cmQtAutoMocUic::UicSettingsT::UicSettingsT()
- {
- RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
- "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
- }
- cmQtAutoMocUic::UicSettingsT::~UicSettingsT() = default;
- bool cmQtAutoMocUic::UicSettingsT::skipped(std::string const& fileName) const
- {
- return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
- }
- void cmQtAutoMocUic::JobT::LogError(GenT genType,
- std::string const& message) const
- {
- Gen()->AbortError();
- Gen()->Log().Error(genType, message);
- }
- void cmQtAutoMocUic::JobT::LogFileError(GenT genType,
- std::string const& filename,
- std::string const& message) const
- {
- Gen()->AbortError();
- Gen()->Log().ErrorFile(genType, filename, message);
- }
- void cmQtAutoMocUic::JobT::LogCommandError(
- GenT genType, std::string const& message,
- std::vector<std::string> const& command, std::string const& output) const
- {
- Gen()->AbortError();
- Gen()->Log().ErrorCommand(genType, message, command, output);
- }
- bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
- cmWorkerPool::ProcessResultT& result,
- std::vector<std::string> const& command,
- std::string* infoMessage)
- {
- // Log command
- if (Log().Verbose()) {
- std::string msg;
- if ((infoMessage != nullptr) && !infoMessage->empty()) {
- msg = *infoMessage;
- if (msg.back() != '\n') {
- msg += '\n';
- }
- }
- msg += QuotedCommand(command);
- msg += '\n';
- Log().Info(genType, msg);
- }
- return cmWorkerPool::JobT::RunProcess(result, command,
- BaseConst().AutogenBuildDir);
- }
- void cmQtAutoMocUic::JobMocPredefsT::Process()
- {
- // (Re)generate moc_predefs.h on demand
- std::unique_ptr<std::string> reason;
- if (Log().Verbose()) {
- reason = cm::make_unique<std::string>();
- }
- if (!Update(reason.get())) {
- return;
- }
- std::string const& predefsFileRel = MocConst().PredefsFileRel;
- std::string const& predefsFileAbs = MocConst().PredefsFileAbs;
- {
- cmWorkerPool::ProcessResultT result;
- {
- // Compose command
- std::vector<std::string> cmd = MocConst().PredefsCmd;
- // Add includes
- cmAppend(cmd, MocConst().Includes);
- // Add definitions
- for (std::string const& def : MocConst().Definitions) {
- cmd.emplace_back("-D" + def);
- }
- // Execute command
- if (!RunProcess(GenT::MOC, result, cmd, reason.get())) {
- std::string msg =
- cmStrCat("The content generation command for ",
- Quoted(predefsFileRel), " failed.\n", result.ErrorMessage);
- LogCommandError(GenT::MOC, msg, cmd, result.StdOut);
- return;
- }
- }
- // (Re)write predefs file only on demand
- if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) {
- if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) {
- std::string msg =
- cmStrCat("Writing ", Quoted(predefsFileRel), " failed.");
- LogFileError(GenT::MOC, predefsFileAbs, msg);
- return;
- }
- } else {
- // Touch to update the time stamp
- if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Touching " + Quoted(predefsFileRel));
- }
- if (!cmSystemTools::Touch(predefsFileAbs, false)) {
- std::string msg =
- cmStrCat("Touching ", Quoted(predefsFileAbs), " failed.");
- LogFileError(GenT::MOC, predefsFileAbs, msg);
- return;
- }
- }
- }
- // Read file time afterwards
- if (!MocEval().PredefsTime.Load(predefsFileAbs)) {
- LogFileError(GenT::MOC, predefsFileAbs, "File time reading failed.");
- return;
- }
- }
- bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
- {
- // Test if the file exists
- if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(MocConst().PredefsFileRel);
- *reason += ", because it doesn't exist.";
- }
- return true;
- }
- // Test if the settings changed
- if (MocConst().SettingsChanged) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(MocConst().PredefsFileRel);
- *reason += ", because the moc settings changed.";
- }
- return true;
- }
- // Test if the executable is newer
- {
- std::string const& exec = MocConst().PredefsCmd.at(0);
- cmFileTime execTime;
- if (execTime.Load(exec)) {
- if (MocEval().PredefsTime.Older(execTime)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(MocConst().PredefsFileRel);
- *reason += " because it is older than ";
- *reason += Quoted(exec);
- *reason += ".";
- }
- return true;
- }
- }
- }
- return false;
- }
- bool cmQtAutoMocUic::JobParseT::ReadFile()
- {
- // Clear old parse information
- FileHandle->ParseData->Clear();
- std::string const& fileName = FileHandle->FileName;
- // Write info
- if (Log().Verbose()) {
- Log().Info(GenT::GEN, "Parsing " + Quoted(fileName));
- }
- // Read file content
- {
- std::string error;
- if (!cmQtAutoGenerator::FileRead(Content, fileName, &error)) {
- LogFileError(GenT::GEN, fileName, "Could not read the file: " + error);
- return false;
- }
- }
- // Warn if empty
- if (Content.empty()) {
- Log().WarningFile(GenT::GEN, fileName, "The file is empty.");
- return false;
- }
- return true;
- }
- void cmQtAutoMocUic::JobParseT::CreateKeys(std::vector<IncludeKeyT>& container,
- std::set<std::string> const& source,
- std::size_t basePrefixLength)
- {
- if (source.empty()) {
- return;
- }
- container.reserve(source.size());
- for (std::string const& src : source) {
- container.emplace_back(src, basePrefixLength);
- }
- }
- void cmQtAutoMocUic::JobParseT::MocMacro()
- {
- for (KeyExpT const& filter : MocConst().MacroFilters) {
- // Run a simple find string check
- if (Content.find(filter.Key) == std::string::npos) {
- continue;
- }
- // Run the expensive regular expression check loop
- cmsys::RegularExpressionMatch match;
- if (filter.Exp.find(Content.c_str(), match)) {
- // Keep detected macro name
- FileHandle->ParseData->Moc.Macro = filter.Key;
- return;
- }
- }
- }
- void cmQtAutoMocUic::JobParseT::MocDependecies()
- {
- if (MocConst().DependFilters.empty()) {
- return;
- }
- // Find dependency strings
- std::set<std::string> parseDepends;
- for (KeyExpT const& filter : MocConst().DependFilters) {
- // Run a simple find string check
- if (Content.find(filter.Key) == std::string::npos) {
- continue;
- }
- // Run the expensive regular expression check loop
- const char* contentChars = Content.c_str();
- cmsys::RegularExpressionMatch match;
- while (filter.Exp.find(contentChars, match)) {
- {
- std::string dep = match.match(1);
- if (!dep.empty()) {
- parseDepends.emplace(std::move(dep));
- }
- }
- contentChars += match.end();
- }
- }
- // Store dependency strings
- {
- auto& Depends = FileHandle->ParseData->Moc.Depends;
- Depends.reserve(parseDepends.size());
- for (std::string const& item : parseDepends) {
- Depends.emplace_back(item);
- // Replace end of line characters in filenames
- std::string& path = Depends.back();
- std::replace(path.begin(), path.end(), '\n', ' ');
- std::replace(path.begin(), path.end(), '\r', ' ');
- }
- }
- }
- void cmQtAutoMocUic::JobParseT::MocIncludes()
- {
- if (Content.find("moc") == std::string::npos) {
- return;
- }
- std::set<std::string> underscore;
- std::set<std::string> dot;
- {
- const char* contentChars = Content.c_str();
- cmsys::RegularExpression const& regExp = MocConst().RegExpInclude;
- cmsys::RegularExpressionMatch match;
- while (regExp.find(contentChars, match)) {
- std::string incString = match.match(2);
- std::string const incBase =
- cmSystemTools::GetFilenameWithoutLastExtension(incString);
- if (cmHasLiteralPrefix(incBase, "moc_")) {
- // moc_<BASE>.cpp
- // Remove the moc_ part from the base name
- underscore.emplace(std::move(incString));
- } else {
- // <BASE>.moc
- dot.emplace(std::move(incString));
- }
- // Forward content pointer
- contentChars += match.end();
- }
- }
- auto& Include = FileHandle->ParseData->Moc.Include;
- CreateKeys(Include.Underscore, underscore, MocUnderscoreLength);
- CreateKeys(Include.Dot, dot, 0);
- }
- void cmQtAutoMocUic::JobParseT::UicIncludes()
- {
- if (Content.find("ui_") == std::string::npos) {
- return;
- }
- std::set<std::string> includes;
- {
- const char* contentChars = Content.c_str();
- cmsys::RegularExpression const& regExp = UicConst().RegExpInclude;
- cmsys::RegularExpressionMatch match;
- while (regExp.find(contentChars, match)) {
- includes.emplace(match.match(2));
- // Forward content pointer
- contentChars += match.end();
- }
- }
- CreateKeys(FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength);
- }
- void cmQtAutoMocUic::JobParseHeaderT::Process()
- {
- if (!ReadFile()) {
- return;
- }
- // Moc parsing
- if (FileHandle->Moc) {
- MocMacro();
- MocDependecies();
- }
- // Uic parsing
- if (FileHandle->Uic) {
- UicIncludes();
- }
- }
- void cmQtAutoMocUic::JobParseSourceT::Process()
- {
- if (!ReadFile()) {
- return;
- }
- // Moc parsing
- if (FileHandle->Moc) {
- MocMacro();
- MocDependecies();
- MocIncludes();
- }
- // Uic parsing
- if (FileHandle->Uic) {
- UicIncludes();
- }
- }
- void cmQtAutoMocUic::JobEvaluateT::Process()
- {
- // Evaluate for moc
- if (MocConst().Enabled) {
- // Evaluate headers
- for (auto const& pair : BaseEval().Headers) {
- if (!MocEvalHeader(pair.second)) {
- return;
- }
- }
- // Evaluate sources
- for (auto const& pair : BaseEval().Sources) {
- if (!MocEvalSource(pair.second)) {
- return;
- }
- }
- }
- // Evaluate for uic
- if (UicConst().Enabled) {
- if (!UicEval(BaseEval().Headers) || !UicEval(BaseEval().Sources)) {
- return;
- }
- }
- // Add discovered header parse jobs
- Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
- // Add generate job after
- Gen()->WorkerPool().EmplaceJob<JobGenerateT>();
- }
- bool cmQtAutoMocUic::JobEvaluateT::MocEvalHeader(SourceFileHandleT source)
- {
- SourceFileT const& sourceFile = *source;
- auto const& parseData = sourceFile.ParseData->Moc;
- if (!source->Moc) {
- return true;
- }
- if (!parseData.Macro.empty()) {
- // Create a new mapping
- MappingHandleT handle = std::make_shared<MappingT>();
- handle->SourceFile = std::move(source);
- // Absolute build path
- if (BaseConst().MultiConfig) {
- handle->OutputFile = Gen()->AbsoluteIncludePath(sourceFile.BuildPath);
- } else {
- handle->OutputFile = Gen()->AbsoluteBuildPath(sourceFile.BuildPath);
- }
- // Register mapping in headers map
- MocRegisterMapping(handle, true);
- }
- return true;
- }
- bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
- SourceFileHandleT const& source)
- {
- SourceFileT const& sourceFile = *source;
- auto const& parseData = sourceFile.ParseData->Moc;
- if (!sourceFile.Moc ||
- (parseData.Macro.empty() && parseData.Include.Underscore.empty() &&
- parseData.Include.Dot.empty())) {
- return true;
- }
- std::string const sourceDir = SubDirPrefix(sourceFile.FileName);
- std::string const sourceBase =
- cmSystemTools::GetFilenameWithoutLastExtension(sourceFile.FileName);
- // For relaxed mode check if the own "moc_" or ".moc" file is included
- bool const relaxedMode = MocConst().RelaxedMode;
- bool sourceIncludesMocUnderscore = false;
- bool sourceIncludesDotMoc = false;
- // Check if the sources own "moc_" or ".moc" file is included
- if (relaxedMode) {
- for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
- if (incKey.Base == sourceBase) {
- sourceIncludesMocUnderscore = true;
- break;
- }
- }
- }
- for (IncludeKeyT const& incKey : parseData.Include.Dot) {
- if (incKey.Base == sourceBase) {
- sourceIncludesDotMoc = true;
- break;
- }
- }
- // Check if this source needs to be moc processed but doesn't.
- if (!sourceIncludesDotMoc && !parseData.Macro.empty() &&
- !(relaxedMode && sourceIncludesMocUnderscore)) {
- {
- std::string emsg =
- cmStrCat("The file contains a ", Quoted(parseData.Macro),
- " macro, but does not include ", Quoted(sourceBase + ".moc"),
- "!\nConsider to\n - add #include \"", sourceBase,
- ".moc\"\n - enable SKIP_AUTOMOC for this file");
- LogFileError(GenT::MOC, sourceFile.FileName, emsg);
- }
- return false;
- }
- // Evaluate "moc_" includes
- for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
- std::string const headerBase = incKey.Dir + incKey.Base;
- SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
- if (!header) {
- {
- std::string msg = "The file includes the moc file ";
- msg += Quoted(incKey.Key);
- msg += ",\nbut the header could not be found "
- "in the following locations\n";
- msg += MocMessageTestHeaders(headerBase);
- LogFileError(GenT::MOC, sourceFile.FileName, msg);
- }
- return false;
- }
- // The include might be handled differently in relaxed mode
- if (relaxedMode && !sourceIncludesDotMoc && !parseData.Macro.empty() &&
- (incKey.Base == sourceBase)) {
- // The <BASE>.cpp file includes a Qt macro but does not include the
- // <BASE>.moc file. In this case, the moc_<BASE>.cpp should probably
- // be generated from <BASE>.cpp instead of <BASE>.h, because otherwise
- // it won't build. But warn, since this is not how it is supposed to be
- // used. This is for KDE4 compatibility.
- {
- // Issue a warning
- std::string msg = cmStrCat(
- "The file contains a ", Quoted(parseData.Macro),
- " macro, but does not include ", Quoted(sourceBase + ".moc"),
- ".\nInstead it includes ", Quoted(incKey.Key),
- ".\nRunning moc on the source\n ", Quoted(sourceFile.FileName),
- "!\nBetter include ", Quoted(sourceBase + ".moc"),
- " for compatibility with regular mode.\n",
- "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n");
- Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
- }
- // Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
- return false;
- }
- continue;
- }
- // Check if header is skipped
- if (MocConst().skipped(header->FileName)) {
- continue;
- }
- // Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, std::move(header), true)) {
- return false;
- }
- }
- // Evaluate ".moc" includes
- if (relaxedMode) {
- // Relaxed mode
- for (IncludeKeyT const& incKey : parseData.Include.Dot) {
- // Check if this is the sources own .moc file
- bool const ownMoc = (incKey.Base == sourceBase);
- if (ownMoc && !parseData.Macro.empty()) {
- // Create mapping for the regular use case
- if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
- return false;
- }
- continue;
- }
- // Try to find a header instead but issue a warning.
- // This is for KDE4 compatibility.
- std::string const headerBase = incKey.Dir + incKey.Base;
- SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
- if (!header) {
- std::string msg = "The file includes the moc file ";
- msg += Quoted(incKey.Key);
- msg += ",\nwhich seems to be the moc file from a different source "
- "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header"
- "could not be found in the following locations\n";
- msg += MocMessageTestHeaders(headerBase);
- LogFileError(GenT::MOC, sourceFile.FileName, msg);
- return false;
- }
- // Check if header is skipped
- if (MocConst().skipped(header->FileName)) {
- continue;
- }
- // Issue a warning
- if (ownMoc && parseData.Macro.empty()) {
- std::string msg = cmStrCat(
- "The file includes the moc file ", Quoted(incKey.Key),
- ", but does not contain a\n", MocConst().MacrosString(),
- " macro.\nRunning moc on the header\n ", Quoted(header->FileName),
- "!\nBetter include ", Quoted("moc_" + incKey.Base + ".cpp"),
- " for a compatibility with regular mode.\n",
- "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n");
- Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
- } else {
- std::string msg = cmStrCat(
- "The file includes the moc file ", Quoted(incKey.Key),
- " instead of ", Quoted("moc_" + incKey.Base + ".cpp"),
- ".\nRunning moc on the header\n ", Quoted(header->FileName),
- "!\nBetter include ", Quoted("moc_" + incKey.Base + ".cpp"),
- " for compatibility with regular mode.\n",
- "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n");
- Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
- }
- // Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, std::move(header), true)) {
- return false;
- }
- }
- } else {
- // Strict mode
- for (IncludeKeyT const& incKey : parseData.Include.Dot) {
- // Check if this is the sources own .moc file
- bool const ownMoc = (incKey.Base == sourceBase);
- if (!ownMoc) {
- // Don't allow <BASE>.moc include other than own in regular mode
- std::string msg = "The file includes the moc file ";
- msg += Quoted(incKey.Key);
- msg += ",\nwhich seems to be the moc file from a different "
- "source file.\nThis is not supported. Include ";
- msg += Quoted(sourceBase + ".moc");
- msg += " to run moc on this source file.";
- LogFileError(GenT::MOC, sourceFile.FileName, msg);
- return false;
- }
- // Accept but issue a warning if moc isn't required
- if (parseData.Macro.empty()) {
- std::string msg = cmStrCat(
- "The file includes the moc file ", Quoted(incKey.Key),
- ", but does not contain a ", MocConst().MacrosString(), " macro.");
- Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
- }
- // Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
- return false;
- }
- }
- }
- return true;
- }
- cmQtAutoMocUic::SourceFileHandleT
- cmQtAutoMocUic::JobEvaluateT::MocFindIncludedHeader(
- std::string const& includerDir, std::string const& includeBase) const
- {
- // Search in vicinity of the source
- {
- SourceFileHandleT res = MocFindHeader(includerDir + includeBase);
- if (res) {
- return res;
- }
- }
- // Search in include directories
- for (std::string const& path : MocConst().IncludePaths) {
- std::string testPath = cmStrCat(path, '/', includeBase);
- SourceFileHandleT res = MocFindHeader(testPath);
- if (res) {
- return res;
- }
- }
- // Return without success
- return SourceFileHandleT();
- }
- cmQtAutoMocUic::SourceFileHandleT cmQtAutoMocUic::JobEvaluateT::MocFindHeader(
- std::string const& basePath) const
- {
- std::string testPath;
- testPath.reserve(basePath.size() + 8);
- for (std::string const& ext : BaseConst().HeaderExtensions) {
- testPath.clear();
- testPath += basePath;
- testPath += '.';
- testPath += ext;
- cmFileTime fileTime;
- if (fileTime.Load(testPath)) {
- // Compute real path of the file
- testPath = cmSystemTools::GetRealPath(testPath);
- // Return a known file if it exists already
- {
- auto it = BaseEval().Headers.find(testPath);
- if (it != BaseEval().Headers.end()) {
- return it->second;
- }
- }
- // Created and return discovered file entry
- SourceFileHandleT& res = MocEval().HeadersDiscovered[testPath];
- if (!res) {
- res = std::make_shared<SourceFileT>(testPath);
- res->FileTime = fileTime;
- res->Moc = true;
- }
- return res;
- }
- }
- // Return without success
- return SourceFileHandleT();
- }
- std::string cmQtAutoMocUic::JobEvaluateT::MocMessageTestHeaders(
- std::string const& fileBase) const
- {
- std::ostringstream res;
- {
- std::string exts =
- cmStrCat(".{", cmJoin(BaseConst().HeaderExtensions, ","),
- '}'); // Compose result string
- res << " " << fileBase << exts << '\n';
- for (std::string const& path : MocConst().IncludePaths) {
- res << " " << path << '/' << fileBase << exts << '\n';
- }
- }
- return res.str();
- }
- bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded(
- std::string const& includeString, SourceFileHandleT includerFileHandle,
- SourceFileHandleT sourceFileHandle, bool sourceIsHeader) const
- {
- // Check if this file is already included
- MappingHandleT& handle = MocEval().Includes[includeString];
- if (handle) {
- // Check if the output file would be generated from different source files
- if (handle->SourceFile != sourceFileHandle) {
- std::string msg = cmStrCat("The source files\n ",
- Quoted(includerFileHandle->FileName), '\n');
- for (auto const& item : handle->IncluderFiles) {
- msg += " ";
- msg += Quoted(item->FileName);
- msg += '\n';
- }
- msg += "contain the same include string ";
- msg += Quoted(includeString);
- msg += ", but\nthe moc file would be generated from different "
- "source files\n ";
- msg += Quoted(sourceFileHandle->FileName);
- msg += " and\n ";
- msg += Quoted(handle->SourceFile->FileName);
- msg += ".\nConsider to\n"
- " - not include the \"moc_<NAME>.cpp\" file\n"
- " - add a directory prefix to a \"<NAME>.moc\" include "
- "(e.g \"sub/<NAME>.moc\")\n"
- " - rename the source file(s)\n";
- LogError(GenT::MOC, msg);
- return false;
- }
- // The same mapping already exists. Just add to the includers list.
- handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
- return true;
- }
- // Create a new mapping
- handle = std::make_shared<MappingT>();
- handle->IncludeString = includeString;
- handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
- handle->SourceFile = std::move(sourceFileHandle);
- handle->OutputFile += Gen()->AbsoluteIncludePath(includeString);
- // Register mapping in sources/headers map
- MocRegisterMapping(handle, sourceIsHeader);
- return true;
- }
- void cmQtAutoMocUic::JobEvaluateT::MocRegisterMapping(
- MappingHandleT mappingHandle, bool sourceIsHeader) const
- {
- auto& regMap =
- sourceIsHeader ? MocEval().HeaderMappings : MocEval().SourceMappings;
- // Check if source file already gets mapped
- auto& regHandle = regMap[mappingHandle->SourceFile->FileName];
- if (!regHandle) {
- // Yet unknown mapping
- regHandle = std::move(mappingHandle);
- } else {
- // Mappings with include string override those without
- if (!mappingHandle->IncludeString.empty()) {
- regHandle = std::move(mappingHandle);
- }
- }
- }
- bool cmQtAutoMocUic::JobEvaluateT::UicEval(SourceFileMapT const& fileMap)
- {
- for (auto const& pair : fileMap) {
- if (!UicEvalFile(pair.second)) {
- return false;
- }
- }
- return true;
- }
- bool cmQtAutoMocUic::JobEvaluateT::UicEvalFile(
- SourceFileHandleT sourceFileHandle)
- {
- SourceFileT const& sourceFile = *sourceFileHandle;
- auto const& Include = sourceFile.ParseData->Uic.Include;
- if (!sourceFile.Uic || Include.empty()) {
- return true;
- }
- std::string const sourceDir = SubDirPrefix(sourceFile.FileName);
- for (IncludeKeyT const& incKey : Include) {
- // Find .ui file name
- SourceFileHandleT uiFileHandle =
- UicFindIncludedUi(sourceFile.FileName, sourceDir, incKey);
- if (!uiFileHandle || UicConst().skipped(uiFileHandle->FileName)) {
- continue;
- }
- // Register mapping
- if (!UicRegisterMapping(incKey.Key, std::move(uiFileHandle),
- std::move(sourceFileHandle))) {
- return false;
- }
- }
- return true;
- }
- bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping(
- std::string const& includeString, SourceFileHandleT uiFileHandle,
- SourceFileHandleT includerFileHandle)
- {
- auto& Includes = Gen()->UicEval().Includes;
- auto it = Includes.find(includeString);
- if (it != Includes.end()) {
- MappingHandleT const& handle = it->second;
- if (handle->SourceFile != uiFileHandle) {
- // The output file already gets generated - from a different .ui file!
- std::string msg = cmStrCat("The source files\n ",
- Quoted(includerFileHandle->FileName), '\n');
- for (auto const& item : handle->IncluderFiles) {
- msg += " ";
- msg += Quoted(item->FileName);
- msg += '\n';
- }
- msg += "contain the same include string ";
- msg += Quoted(includeString);
- msg += ", but\nthe uic file would be generated from different "
- "user interface files\n ";
- msg += Quoted(uiFileHandle->FileName);
- msg += " and\n ";
- msg += Quoted(handle->SourceFile->FileName);
- msg += ".\nConsider to\n"
- " - add a directory prefix to a \"ui_<NAME>.h\" include "
- "(e.g \"sub/ui_<NAME>.h\")\n"
- " - rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" "
- "include(s)\n";
- LogError(GenT::UIC, msg);
- return false;
- }
- // Add includer file to existing mapping
- handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
- } else {
- // New mapping handle
- MappingHandleT handle = std::make_shared<MappingT>();
- handle->IncludeString = includeString;
- handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
- handle->SourceFile = std::move(uiFileHandle);
- handle->OutputFile += Gen()->AbsoluteIncludePath(includeString);
- // Register mapping
- Includes.emplace(includeString, std::move(handle));
- }
- return true;
- }
- cmQtAutoMocUic::SourceFileHandleT
- cmQtAutoMocUic::JobEvaluateT::UicFindIncludedUi(
- std::string const& sourceFile, std::string const& sourceDir,
- IncludeKeyT const& incKey) const
- {
- std::string searchFileName = cmStrCat(incKey.Base, ".ui");
- // Collect search paths list
- std::vector<std::string> testFiles;
- {
- auto& searchPaths = UicConst().SearchPaths;
- testFiles.reserve((searchPaths.size() + 1) * 2);
- // Vicinity of the source
- testFiles.emplace_back(sourceDir + searchFileName);
- if (!incKey.Dir.empty()) {
- testFiles.emplace_back(cmStrCat(sourceDir, incKey.Dir, searchFileName));
- }
- // AUTOUIC search paths
- if (!searchPaths.empty()) {
- for (std::string const& sPath : searchPaths) {
- testFiles.emplace_back(cmStrCat(sPath, '/', searchFileName));
- }
- if (!incKey.Dir.empty()) {
- for (std::string const& sPath : searchPaths) {
- testFiles.emplace_back(
- cmStrCat(sPath, '/', incKey.Dir, searchFileName));
- }
- }
- }
- }
- // Search for the .ui file!
- for (std::string const& testFile : testFiles) {
- cmFileTime fileTime;
- if (fileTime.Load(testFile)) {
- // .ui file found in files system!
- std::string realPath = cmSystemTools::GetRealPath(testFile);
- // Get or create .ui file handle
- SourceFileHandleT& handle = Gen()->UicEval().UiFiles[realPath];
- if (!handle) {
- // The file wasn't registered, yet
- handle = std::make_shared<SourceFileT>(realPath);
- handle->FileTime = fileTime;
- }
- return handle;
- }
- }
- // Log error
- {
- std::string msg =
- cmStrCat("The file includes the uic file ", Quoted(incKey.Key),
- ",\nbut the user interface file ", Quoted(searchFileName),
- "\ncould not be found in the following locations\n");
- for (std::string const& testFile : testFiles) {
- msg += " ";
- msg += Quoted(testFile);
- msg += '\n';
- }
- LogFileError(GenT::UIC, sourceFile, msg);
- }
- return SourceFileHandleT();
- }
- void cmQtAutoMocUic::JobGenerateT::Process()
- {
- // Add moc compile jobs
- if (MocConst().Enabled) {
- for (auto const& pair : MocEval().HeaderMappings) {
- // Register if this mapping is a candidate for mocs_compilation.cpp
- bool const compFile = pair.second->IncludeString.empty();
- if (compFile) {
- MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
- }
- if (!MocGenerate(pair.second, compFile)) {
- return;
- }
- }
- for (auto const& pair : MocEval().SourceMappings) {
- if (!MocGenerate(pair.second, false)) {
- return;
- }
- }
- // Add mocs compilations job on demand
- Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
- }
- // Add uic compile jobs
- if (UicConst().Enabled) {
- for (auto const& pair : Gen()->UicEval().Includes) {
- if (!UicGenerate(pair.second)) {
- return;
- }
- }
- }
- // Add finish job
- Gen()->WorkerPool().EmplaceJob<JobFinishT>();
- }
- bool cmQtAutoMocUic::JobGenerateT::MocGenerate(MappingHandleT const& mapping,
- bool compFile) const
- {
- std::unique_ptr<std::string> reason;
- if (Log().Verbose()) {
- reason = cm::make_unique<std::string>();
- }
- if (MocUpdate(*mapping, reason.get())) {
- // Create the parent directory
- if (!MakeParentDirectory(mapping->OutputFile)) {
- LogFileError(GenT::MOC, mapping->OutputFile,
- "Could not create parent directory.");
- return false;
- }
- // Add moc job
- Gen()->WorkerPool().EmplaceJob<JobMocT>(mapping, std::move(reason));
- // Check if a moc job for a mocs_compilation.cpp entry was generated
- if (compFile) {
- MocEval().CompUpdated = true;
- }
- }
- return true;
- }
- bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
- std::string* reason) const
- {
- std::string const& sourceFile = mapping.SourceFile->FileName;
- std::string const& outputFile = mapping.OutputFile;
- // Test if the output file exists
- cmFileTime outputFileTime;
- if (!outputFileTime.Load(outputFile)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because it doesn't exist, from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- // Test if any setting changed
- if (MocConst().SettingsChanged) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because the uic settings changed, from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- // Test if the source file is newer
- if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because it's older than its source file, from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- // Test if the moc_predefs file is newer
- if (!MocConst().PredefsFileAbs.empty()) {
- if (outputFileTime.Older(MocEval().PredefsTime)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because it's older than ";
- *reason += Quoted(MocConst().PredefsFileAbs);
- *reason += ", from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- }
- // Test if the moc executable is newer
- if (outputFileTime.Older(MocConst().ExecutableTime)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because it's older than the moc executable, from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- // Test if a dependency file is newer
- {
- // Check dependency timestamps
- std::string const sourceDir = SubDirPrefix(sourceFile);
- for (std::string const& dep : mapping.SourceFile->ParseData->Moc.Depends) {
- // Find dependency file
- auto const depMatch = MocFindDependency(sourceDir, dep);
- if (depMatch.first.empty()) {
- Log().WarningFile(GenT::MOC, sourceFile,
- "Could not find dependency file " + Quoted(dep));
- continue;
- }
- // Test if dependency file is older
- if (outputFileTime.Older(depMatch.second)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because it's older than its dependency file ";
- *reason += Quoted(depMatch.first);
- *reason += ", from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- }
- }
- return false;
- }
- std::pair<std::string, cmFileTime>
- cmQtAutoMocUic::JobGenerateT::MocFindDependency(
- std::string const& sourceDir, std::string const& includeString) const
- {
- typedef std::pair<std::string, cmFileTime> ResPair;
- // Search in vicinity of the source
- {
- ResPair res{ sourceDir + includeString, {} };
- if (res.second.Load(res.first)) {
- return res;
- }
- }
- // Search in include directories
- for (std::string const& includePath : MocConst().IncludePaths) {
- ResPair res{ includePath, {} };
- res.first += '/';
- res.first += includeString;
- if (res.second.Load(res.first)) {
- return res;
- }
- }
- // Return empty
- return ResPair();
- }
- bool cmQtAutoMocUic::JobGenerateT::UicGenerate(
- MappingHandleT const& mapping) const
- {
- std::unique_ptr<std::string> reason;
- if (Log().Verbose()) {
- reason = cm::make_unique<std::string>();
- }
- if (UicUpdate(*mapping, reason.get())) {
- // Create the parent directory
- if (!MakeParentDirectory(mapping->OutputFile)) {
- LogFileError(GenT::UIC, mapping->OutputFile,
- "Could not create parent directory.");
- return false;
- }
- // Add uic job
- Gen()->WorkerPool().EmplaceJob<JobUicT>(mapping, std::move(reason));
- }
- return true;
- }
- bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
- std::string* reason) const
- {
- std::string const& sourceFile = mapping.SourceFile->FileName;
- std::string const& outputFile = mapping.OutputFile;
- // Test if the build file exists
- cmFileTime outputFileTime;
- if (!outputFileTime.Load(outputFile)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because it doesn't exist, from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- // Test if the uic settings changed
- if (UicConst().SettingsChanged) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because the uic settings changed, from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- // Test if the source file is newer
- if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += " because it's older than the source file ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- // Test if the uic executable is newer
- if (outputFileTime.Older(UicConst().ExecutableTime)) {
- if (reason != nullptr) {
- *reason = "Generating ";
- *reason += Quoted(outputFile);
- *reason += ", because it's older than the uic executable, from ";
- *reason += Quoted(sourceFile);
- }
- return true;
- }
- return false;
- }
- void cmQtAutoMocUic::JobMocT::Process()
- {
- std::string const& sourceFile = Mapping->SourceFile->FileName;
- std::string const& outputFile = Mapping->OutputFile;
- // Compose moc command
- std::vector<std::string> cmd;
- cmd.push_back(MocConst().Executable);
- // Add options
- cmAppend(cmd, MocConst().AllOptions);
- // Add predefs include
- if (!MocConst().PredefsFileAbs.empty()) {
- cmd.emplace_back("--include");
- cmd.push_back(MocConst().PredefsFileAbs);
- }
- cmd.emplace_back("-o");
- cmd.push_back(outputFile);
- cmd.push_back(sourceFile);
- // Execute moc command
- cmWorkerPool::ProcessResultT result;
- if (RunProcess(GenT::MOC, result, cmd, Reason.get())) {
- // Moc command success. Print moc output.
- if (!result.StdOut.empty()) {
- Log().Info(GenT::MOC, result.StdOut);
- }
- } else {
- // Moc command failed
- std::string msg =
- cmStrCat("The moc process failed to compile\n ", Quoted(sourceFile),
- "\ninto\n ", Quoted(outputFile));
- if (Mapping->IncluderFiles.empty()) {
- msg += ".\n";
- } else {
- msg += "\nincluded by\n";
- for (auto const& item : Mapping->IncluderFiles) {
- msg += " ";
- msg += Quoted(item->FileName);
- msg += '\n';
- }
- }
- msg += result.ErrorMessage;
- LogCommandError(GenT::MOC, msg, cmd, result.StdOut);
- }
- }
- void cmQtAutoMocUic::JobUicT::Process()
- {
- std::string const& sourceFile = Mapping->SourceFile->FileName;
- std::string const& outputFile = Mapping->OutputFile;
- // Compose uic command
- std::vector<std::string> cmd;
- cmd.push_back(UicConst().Executable);
- {
- std::vector<std::string> allOpts = UicConst().TargetOptions;
- auto optionIt = UicConst().Options.find(sourceFile);
- if (optionIt != UicConst().Options.end()) {
- UicMergeOptions(allOpts, optionIt->second,
- (BaseConst().QtVersionMajor == 5));
- }
- cmAppend(cmd, allOpts);
- }
- cmd.emplace_back("-o");
- cmd.emplace_back(outputFile);
- cmd.emplace_back(sourceFile);
- cmWorkerPool::ProcessResultT result;
- if (RunProcess(GenT::UIC, result, cmd, Reason.get())) {
- // Uic command success
- // Print uic output
- if (!result.StdOut.empty()) {
- Log().Info(GenT::UIC, result.StdOut);
- }
- } else {
- // Uic command failed
- std::string msg =
- cmStrCat("The uic process failed to compile\n ", Quoted(sourceFile),
- "\ninto\n ", Quoted(outputFile), "\nincluded by\n");
- for (auto const& item : Mapping->IncluderFiles) {
- msg += " ";
- msg += Quoted(item->FileName);
- msg += '\n';
- }
- msg += result.ErrorMessage;
- LogCommandError(GenT::UIC, msg, cmd, result.StdOut);
- }
- }
- void cmQtAutoMocUic::JobMocsCompilationT::Process()
- {
- // Compose mocs compilation file content
- std::string content =
- "// This file is autogenerated. Changes will be overwritten.\n";
- if (MocEval().CompFiles.empty()) {
- // Placeholder content
- content += "// No files found that require moc or the moc files are "
- "included\n";
- content += "enum some_compilers { need_more_than_nothing };\n";
- } else {
- // Valid content
- char const clampB = BaseConst().MultiConfig ? '<' : '"';
- char const clampE = BaseConst().MultiConfig ? '>' : '"';
- for (std::string const& mocfile : MocEval().CompFiles) {
- content += "#include ";
- content += clampB;
- content += mocfile;
- content += clampE;
- content += '\n';
- }
- }
- std::string const& compAbs = MocConst().CompFileAbs;
- if (cmQtAutoGenerator::FileDiffers(compAbs, content)) {
- // Actually write mocs compilation file
- if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Generating MOC compilation " + compAbs);
- }
- if (!FileWrite(compAbs, content)) {
- LogFileError(GenT::MOC, compAbs,
- "mocs compilation file writing failed.");
- }
- } else if (MocEval().CompUpdated) {
- // Only touch mocs compilation file
- if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Touching mocs compilation " + compAbs);
- }
- if (!cmSystemTools::Touch(compAbs, false)) {
- LogFileError(GenT::MOC, compAbs,
- "mocs compilation file touching failed.");
- }
- }
- }
- void cmQtAutoMocUic::JobFinishT::Process()
- {
- Gen()->AbortSuccess();
- }
- cmQtAutoMocUic::cmQtAutoMocUic() = default;
- cmQtAutoMocUic::~cmQtAutoMocUic() = default;
- bool cmQtAutoMocUic::Init(cmMakefile* makefile)
- {
- // Utility lambdas
- auto InfoGet = [makefile](const char* key) {
- return makefile->GetSafeDefinition(key);
- };
- auto InfoGetBool = [makefile](const char* key) {
- return makefile->IsOn(key);
- };
- auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
- return list;
- };
- auto InfoGetLists =
- [makefile](const char* key) -> std::vector<std::vector<std::string>> {
- std::vector<std::vector<std::string>> lists;
- {
- std::string const value = makefile->GetSafeDefinition(key);
- std::string::size_type pos = 0;
- while (pos < value.size()) {
- std::string::size_type next = value.find(ListSep, pos);
- std::string::size_type length =
- (next != std::string::npos) ? next - pos : value.size() - pos;
- // Remove enclosing braces
- if (length >= 2) {
- std::string::const_iterator itBeg = value.begin() + (pos + 1);
- std::string::const_iterator itEnd = itBeg + (length - 2);
- lists.emplace_back(
- cmSystemTools::ExpandedListArgument(std::string(itBeg, itEnd)));
- }
- pos += length;
- pos += ListSep.size();
- }
- }
- return lists;
- };
- auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
- const char* valueConf = nullptr;
- {
- std::string keyConf = cmStrCat(key, '_', InfoConfig());
- valueConf = makefile->GetDefinition(keyConf);
- }
- if (valueConf == nullptr) {
- return makefile->GetSafeDefinition(key);
- }
- return std::string(valueConf);
- };
- auto InfoGetConfigList =
- [&InfoGetConfig](const char* key) -> std::vector<std::string> {
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
- return list;
- };
- auto LogInfoError = [this](std::string const& msg) -> bool {
- std::ostringstream err;
- err << "In " << Quoted(this->InfoFile()) << ":\n" << msg;
- this->Log().Error(GenT::GEN, err.str());
- return false;
- };
- auto MatchSizes = [&LogInfoError](const char* keyA, const char* keyB,
- std::size_t sizeA,
- std::size_t sizeB) -> bool {
- if (sizeA == sizeB) {
- return true;
- }
- std::ostringstream err;
- err << "Lists sizes mismatch " << keyA << '(' << sizeA << ") " << keyB
- << '(' << sizeB << ')';
- return LogInfoError(err.str());
- };
- // -- Read info file
- if (!makefile->ReadListFile(InfoFile())) {
- return LogInfoError("File processing failed");
- }
- // -- Meta
- Logger_.RaiseVerbosity(InfoGet("AM_VERBOSITY"));
- BaseConst_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
- {
- unsigned long num = 1;
- if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL").c_str(), &num)) {
- num = std::max<unsigned long>(num, 1);
- num = std::min<unsigned long>(num, ParallelMax);
- }
- WorkerPool_.SetThreadCount(static_cast<unsigned int>(num));
- }
- BaseConst_.HeaderExtensions =
- makefile->GetCMakeInstance()->GetHeaderExtensions();
- // - Files and directories
- BaseConst_.IncludeProjectDirsBefore =
- InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
- BaseConst_.ProjectSourceDir = InfoGet("AM_CMAKE_SOURCE_DIR");
- BaseConst_.ProjectBinaryDir = InfoGet("AM_CMAKE_BINARY_DIR");
- BaseConst_.CurrentSourceDir = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
- BaseConst_.CurrentBinaryDir = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
- BaseConst_.AutogenBuildDir = InfoGet("AM_BUILD_DIR");
- if (BaseConst_.AutogenBuildDir.empty()) {
- return LogInfoError("Autogen build directory missing.");
- }
- BaseConst_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR");
- if (BaseConst_.AutogenIncludeDir.empty()) {
- return LogInfoError("Autogen include directory missing.");
- }
- BaseConst_.CMakeExecutable = InfoGetConfig("AM_CMAKE_EXECUTABLE");
- if (BaseConst_.CMakeExecutable.empty()) {
- return LogInfoError("CMake executable file name missing.");
- }
- if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
- std::string error =
- cmStrCat("The CMake executable ", Quoted(BaseConst_.CMakeExecutable),
- " does not exist.");
- return LogInfoError(error);
- }
- BaseConst_.ParseCacheFile = InfoGetConfig("AM_PARSE_CACHE_FILE");
- if (BaseConst_.ParseCacheFile.empty()) {
- return LogInfoError("Parse cache file name missing.");
- }
- // - Settings file
- SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
- if (SettingsFile_.empty()) {
- return LogInfoError("Settings file name missing.");
- }
- // - Qt environment
- {
- unsigned long qtv = BaseConst_.QtVersionMajor;
- if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR").c_str(),
- &qtv)) {
- BaseConst_.QtVersionMajor = static_cast<unsigned int>(qtv);
- }
- }
- // - Moc
- MocConst_.Executable = InfoGet("AM_QT_MOC_EXECUTABLE");
- if (!MocConst().Executable.empty()) {
- MocConst_.Enabled = true;
- // Load the executable file time
- if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
- std::string error =
- cmStrCat("The moc executable ", Quoted(MocConst_.Executable),
- " does not exist.");
- return LogInfoError(error);
- }
- for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) {
- MocConst_.SkipList.insert(std::move(sfl));
- }
- MocConst_.Definitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
- MocConst_.IncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
- MocConst_.Options = InfoGetList("AM_MOC_OPTIONS");
- MocConst_.RelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
- for (std::string const& item : InfoGetList("AM_MOC_MACRO_NAMES")) {
- MocConst_.MacroFilters.emplace_back(
- item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
- }
- {
- auto addFilter = [this, &LogInfoError](std::string const& key,
- std::string const& exp) -> bool {
- auto filterErr = [&LogInfoError, &key, &exp](const char* err) -> bool {
- std::ostringstream ferr;
- ferr << "AUTOMOC_DEPEND_FILTERS: " << err << '\n';
- ferr << " Key: " << Quoted(key) << '\n';
- ferr << " Exp: " << Quoted(exp) << '\n';
- return LogInfoError(ferr.str());
- };
- if (key.empty()) {
- return filterErr("Key is empty");
- }
- if (exp.empty()) {
- return filterErr("Regular expression is empty");
- }
- this->MocConst_.DependFilters.emplace_back(key, exp);
- if (!this->MocConst_.DependFilters.back().Exp.is_valid()) {
- return filterErr("Regular expression compiling failed");
- }
- return true;
- };
- // Insert default filter for Q_PLUGIN_METADATA
- if (BaseConst().QtVersionMajor != 4) {
- if (!addFilter("Q_PLUGIN_METADATA",
- "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
- "[^\\)]*FILE[ \t]*\"([^\"]+)\"")) {
- return false;
- }
- }
- // Insert user defined dependency filters
- std::vector<std::string> flts = InfoGetList("AM_MOC_DEPEND_FILTERS");
- if ((flts.size() % 2) != 0) {
- return LogInfoError(
- "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
- }
- for (auto itC = flts.begin(), itE = flts.end(); itC != itE; itC += 2) {
- if (!addFilter(*itC, *(itC + 1))) {
- return false;
- }
- }
- }
- MocConst_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
- }
- // - Uic
- UicConst_.Executable = InfoGet("AM_QT_UIC_EXECUTABLE");
- if (!UicConst().Executable.empty()) {
- UicConst_.Enabled = true;
- // Load the executable file time
- if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
- std::string error =
- cmStrCat("The uic executable ", Quoted(UicConst_.Executable),
- " does not exist.");
- return LogInfoError(error);
- }
- for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) {
- UicConst_.SkipList.insert(std::move(sfl));
- }
- UicConst_.SearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
- UicConst_.TargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
- {
- const char* keyFiles = "AM_UIC_OPTIONS_FILES";
- const char* keyOpts = "AM_UIC_OPTIONS_OPTIONS";
- auto sources = InfoGetList(keyFiles);
- auto options = InfoGetLists(keyOpts);
- if (!MatchSizes(keyFiles, keyOpts, sources.size(), options.size())) {
- return false;
- }
- auto fitEnd = sources.cend();
- auto fit = sources.begin();
- auto oit = options.begin();
- while (fit != fitEnd) {
- UicConst_.Options[*fit] = std::move(*oit);
- ++fit;
- ++oit;
- }
- }
- }
- // - Headers and sources
- {
- auto makeSource =
- [&LogInfoError](std::string const& fileName,
- std::string const& fileFlags) -> SourceFileHandleT {
- if (fileFlags.size() != 2) {
- LogInfoError("Invalid file flags string size");
- return SourceFileHandleT();
- }
- cmFileTime fileTime;
- if (!fileTime.Load(fileName)) {
- LogInfoError("The source file " + cmQtAutoGen::Quoted(fileName) +
- " does not exist.");
- return SourceFileHandleT();
- }
- SourceFileHandleT sfh = std::make_shared<SourceFileT>(fileName);
- sfh->FileTime = fileTime;
- sfh->Moc = (fileFlags[0] == 'M');
- sfh->Uic = (fileFlags[1] == 'U');
- return sfh;
- };
- // Headers
- {
- // Get file lists
- const char *keyFiles = "AM_HEADERS", *keyFlags = "AM_HEADERS_FLAGS";
- std::vector<std::string> files = InfoGetList(keyFiles);
- std::vector<std::string> flags = InfoGetList(keyFlags);
- std::vector<std::string> builds;
- if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
- return false;
- }
- if (MocConst().Enabled) {
- const char* keyPaths = "AM_HEADERS_BUILD_PATHS";
- builds = InfoGetList(keyPaths);
- if (!MatchSizes(keyFiles, keyPaths, files.size(), builds.size())) {
- return false;
- }
- }
- // Process file lists
- for (std::size_t ii = 0; ii != files.size(); ++ii) {
- std::string& fileName(files[ii]);
- SourceFileHandleT sfh = makeSource(fileName, flags[ii]);
- if (!sfh) {
- return false;
- }
- if (MocConst().Enabled) {
- sfh->BuildPath = std::move(builds[ii]);
- if (sfh->BuildPath.empty()) {
- Log().ErrorFile(GenT::GEN, this->InfoFile(),
- "Header file build path is empty");
- return false;
- }
- }
- BaseEval().Headers.emplace(std::move(fileName), std::move(sfh));
- }
- }
- // Sources
- {
- const char *keyFiles = "AM_SOURCES", *keyFlags = "AM_SOURCES_FLAGS";
- std::vector<std::string> files = InfoGetList(keyFiles);
- std::vector<std::string> flags = InfoGetList(keyFlags);
- if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
- return false;
- }
- // Process file lists
- for (std::size_t ii = 0; ii != files.size(); ++ii) {
- std::string& fileName(files[ii]);
- SourceFileHandleT sfh = makeSource(fileName, flags[ii]);
- if (!sfh) {
- return false;
- }
- BaseEval().Sources.emplace(std::move(fileName), std::move(sfh));
- }
- }
- }
- // Init derived information
- // ------------------------
- // Moc variables
- if (MocConst().Enabled) {
- // Mocs compilation file
- MocConst_.CompFileAbs = AbsoluteBuildPath("mocs_compilation.cpp");
- // Moc predefs file
- if (!MocConst_.PredefsCmd.empty()) {
- MocConst_.PredefsFileRel = "moc_predefs";
- if (BaseConst_.MultiConfig) {
- MocConst_.PredefsFileRel += '_';
- MocConst_.PredefsFileRel += InfoConfig();
- }
- MocConst_.PredefsFileRel += ".h";
- MocConst_.PredefsFileAbs = AbsoluteBuildPath(MocConst().PredefsFileRel);
- }
- // Sort include directories on demand
- if (BaseConst().IncludeProjectDirsBefore) {
- // Move strings to temporary list
- std::list<std::string> includes(MocConst().IncludePaths.begin(),
- MocConst().IncludePaths.end());
- MocConst_.IncludePaths.clear();
- MocConst_.IncludePaths.reserve(includes.size());
- // Append project directories only
- {
- std::array<std::string const*, 2> const movePaths = {
- { &BaseConst().ProjectBinaryDir, &BaseConst().ProjectSourceDir }
- };
- for (std::string const* ppath : movePaths) {
- std::list<std::string>::iterator it = includes.begin();
- while (it != includes.end()) {
- std::string const& path = *it;
- if (cmHasPrefix(path, *ppath)) {
- MocConst_.IncludePaths.push_back(path);
- it = includes.erase(it);
- } else {
- ++it;
- }
- }
- }
- }
- // Append remaining directories
- MocConst_.IncludePaths.insert(MocConst_.IncludePaths.end(),
- includes.begin(), includes.end());
- }
- // Compose moc includes list
- {
- std::set<std::string> frameworkPaths;
- for (std::string const& path : MocConst().IncludePaths) {
- MocConst_.Includes.push_back("-I" + path);
- // Extract framework path
- if (cmHasLiteralSuffix(path, ".framework/Headers")) {
- // Go up twice to get to the framework root
- std::vector<std::string> pathComponents;
- cmSystemTools::SplitPath(path, pathComponents);
- frameworkPaths.emplace(cmSystemTools::JoinPath(
- pathComponents.begin(), pathComponents.end() - 2));
- }
- }
- // Append framework includes
- for (std::string const& path : frameworkPaths) {
- MocConst_.Includes.emplace_back("-F");
- MocConst_.Includes.push_back(path);
- }
- }
- // Setup single list with all options
- {
- // Add includes
- MocConst_.AllOptions.insert(MocConst_.AllOptions.end(),
- MocConst().Includes.begin(),
- MocConst().Includes.end());
- // Add definitions
- for (std::string const& def : MocConst().Definitions) {
- MocConst_.AllOptions.push_back("-D" + def);
- }
- // Add options
- MocConst_.AllOptions.insert(MocConst_.AllOptions.end(),
- MocConst().Options.begin(),
- MocConst().Options.end());
- }
- }
- return true;
- }
- template <class JOBTYPE>
- void cmQtAutoMocUic::CreateParseJobs(SourceFileMapT const& sourceMap)
- {
- cmFileTime const parseCacheTime = BaseEval().ParseCacheTime;
- ParseCacheT& parseCache = BaseEval().ParseCache;
- for (auto& src : sourceMap) {
- // Get or create the file parse data reference
- ParseCacheT::GetOrInsertT cacheEntry = parseCache.GetOrInsert(src.first);
- src.second->ParseData = std::move(cacheEntry.first);
- // Create a parse job if the cache file was missing or is older
- if (cacheEntry.second || src.second->FileTime.Newer(parseCacheTime)) {
- BaseEval().ParseCacheChanged = true;
- WorkerPool().EmplaceJob<JOBTYPE>(src.second);
- }
- }
- }
- void cmQtAutoMocUic::InitJobs()
- {
- // Add moc_predefs.h job
- if (MocConst().Enabled && !MocConst().PredefsCmd.empty()) {
- WorkerPool().EmplaceJob<JobMocPredefsT>();
- }
- // Add header parse jobs
- CreateParseJobs<JobParseHeaderT>(BaseEval().Headers);
- // Add source parse jobs
- CreateParseJobs<JobParseSourceT>(BaseEval().Sources);
- // Add evaluate job
- WorkerPool().EmplaceJob<JobEvaluateT>();
- }
- bool cmQtAutoMocUic::Process()
- {
- SettingsFileRead();
- ParseCacheRead();
- if (!CreateDirectories()) {
- return false;
- }
- InitJobs();
- if (!WorkerPool_.Process(this)) {
- return false;
- }
- if (JobError_) {
- return false;
- }
- if (!ParseCacheWrite()) {
- return false;
- }
- if (!SettingsFileWrite()) {
- return false;
- }
- return true;
- }
- void cmQtAutoMocUic::SettingsFileRead()
- {
- // Compose current settings strings
- {
- cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256);
- std::string const sep(";");
- auto cha = [&cryptoHash, &sep](std::string const& value) {
- cryptoHash.Append(value);
- cryptoHash.Append(sep);
- };
- if (MocConst_.Enabled) {
- cryptoHash.Initialize();
- cha(MocConst().Executable);
- for (auto const& value : MocConst().AllOptions) {
- cha(value);
- }
- cha(BaseConst().IncludeProjectDirsBefore ? "TRUE" : "FALSE");
- for (auto const& value : MocConst().PredefsCmd) {
- cha(value);
- }
- for (auto const& filter : MocConst().DependFilters) {
- cha(filter.Key);
- }
- for (auto const& filter : MocConst().MacroFilters) {
- cha(filter.Key);
- }
- SettingsStringMoc_ = cryptoHash.FinalizeHex();
- }
- if (UicConst().Enabled) {
- cryptoHash.Initialize();
- cha(UicConst().Executable);
- for (auto const& value : UicConst().TargetOptions) {
- cha(value);
- }
- for (const auto& item : UicConst().Options) {
- cha(item.first);
- for (auto const& svalue : item.second) {
- cha(svalue);
- }
- }
- SettingsStringUic_ = cryptoHash.FinalizeHex();
- }
- }
- // Read old settings and compare
- {
- std::string content;
- if (cmQtAutoGenerator::FileRead(content, SettingsFile_)) {
- if (MocConst().Enabled) {
- if (SettingsStringMoc_ != SettingsFind(content, "moc")) {
- MocConst_.SettingsChanged = true;
- }
- }
- if (UicConst().Enabled) {
- if (SettingsStringUic_ != SettingsFind(content, "uic")) {
- UicConst_.SettingsChanged = true;
- }
- }
- // In case any setting changed remove the old settings file.
- // This triggers a full rebuild on the next run if the current
- // build is aborted before writing the current settings in the end.
- if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
- cmSystemTools::RemoveFile(SettingsFile_);
- }
- } else {
- // Settings file read failed
- if (MocConst().Enabled) {
- MocConst_.SettingsChanged = true;
- }
- if (UicConst().Enabled) {
- UicConst_.SettingsChanged = true;
- }
- }
- }
- }
- bool cmQtAutoMocUic::SettingsFileWrite()
- {
- // Only write if any setting changed
- if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
- if (Log().Verbose()) {
- Log().Info(GenT::GEN, "Writing settings file " + Quoted(SettingsFile_));
- }
- // Compose settings file content
- std::string content;
- {
- auto SettingAppend = [&content](const char* key,
- std::string const& value) {
- if (!value.empty()) {
- content += key;
- content += ':';
- content += value;
- content += '\n';
- }
- };
- SettingAppend("moc", SettingsStringMoc_);
- SettingAppend("uic", SettingsStringUic_);
- }
- // Write settings file
- std::string error;
- if (!cmQtAutoGenerator::FileWrite(SettingsFile_, content, &error)) {
- Log().ErrorFile(GenT::GEN, SettingsFile_,
- "Settings file writing failed. " + error);
- // Remove old settings file to trigger a full rebuild on the next run
- cmSystemTools::RemoveFile(SettingsFile_);
- return false;
- }
- }
- return true;
- }
- void cmQtAutoMocUic::ParseCacheRead()
- {
- const char* reason = nullptr;
- // Don't read the cache if it is invalid
- if (!BaseEval().ParseCacheTime.Load(BaseConst().ParseCacheFile)) {
- reason = "Refreshing parse cache because it doesn't exist.";
- } else if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
- reason = "Refreshing parse cache because the settings changed.";
- } else if (BaseEval().ParseCacheTime.Older(
- BaseConst().CMakeExecutableTime)) {
- reason =
- "Refreshing parse cache because it is older than the CMake executable.";
- }
- if (reason != nullptr) {
- // Don't read but refresh the complete parse cache
- if (Log().Verbose()) {
- Log().Info(GenT::GEN, reason);
- }
- BaseEval().ParseCacheChanged = true;
- } else {
- // Read parse cache
- BaseEval().ParseCache.ReadFromFile(BaseConst().ParseCacheFile);
- }
- }
- bool cmQtAutoMocUic::ParseCacheWrite()
- {
- if (BaseEval().ParseCacheChanged) {
- if (Log().Verbose()) {
- Log().Info(GenT::GEN,
- "Writing parse cache file " +
- Quoted(BaseConst().ParseCacheFile));
- }
- if (!BaseEval().ParseCache.WriteToFile(BaseConst().ParseCacheFile)) {
- Log().ErrorFile(GenT::GEN, BaseConst().ParseCacheFile,
- "Parse cache file writing failed.");
- return false;
- }
- }
- return true;
- }
- bool cmQtAutoMocUic::CreateDirectories()
- {
- // Create AUTOGEN include directory
- if (!cmSystemTools::MakeDirectory(BaseConst().AutogenIncludeDir)) {
- Log().ErrorFile(GenT::GEN, BaseConst().AutogenIncludeDir,
- "Could not create directory.");
- return false;
- }
- return true;
- }
- void cmQtAutoMocUic::Abort(bool error)
- {
- if (error) {
- JobError_.store(true);
- }
- WorkerPool_.Abort();
- }
- std::string cmQtAutoMocUic::AbsoluteBuildPath(
- std::string const& relativePath) const
- {
- std::string res(BaseConst().AutogenBuildDir);
- res += '/';
- res += relativePath;
- return res;
- }
- std::string cmQtAutoMocUic::AbsoluteIncludePath(
- std::string const& relativePath) const
- {
- std::string res(BaseConst().AutogenIncludeDir);
- res += '/';
- res += relativePath;
- return res;
- }
|