| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088 |
- /* 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 <initializer_list>
- #include <list>
- #include <set>
- #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,
- cm::string_view message) const
- {
- Gen()->AbortError();
- Gen()->Log().Error(genType, message);
- }
- void cmQtAutoMocUic::JobT::LogFileError(GenT genType, cm::string_view filename,
- cm::string_view message) const
- {
- Gen()->AbortError();
- Gen()->Log().ErrorFile(genType, filename, message);
- }
- void cmQtAutoMocUic::JobT::LogCommandError(
- GenT genType, cm::string_view 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()) {
- cm::string_view info;
- if (infoMessage != nullptr) {
- info = *infoMessage;
- }
- Log().Info(genType,
- cmStrCat(info,
- info.empty() || cmHasSuffix(info, '\n') ? "" : "\n",
- QuotedCommand(command), '\n'));
- }
- 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())) {
- LogCommandError(GenT::MOC,
- cmStrCat("The content generation command for ",
- Quoted(predefsFileRel), " failed.\n",
- result.ErrorMessage),
- cmd, result.StdOut);
- return;
- }
- }
- // (Re)write predefs file only on demand
- if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) {
- if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) {
- LogFileError(GenT::MOC, predefsFileAbs,
- cmStrCat("Writing ", Quoted(predefsFileRel), " failed."));
- return;
- }
- } else {
- // Touch to update the time stamp
- if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Touching " + Quoted(predefsFileRel));
- }
- if (!cmSystemTools::Touch(predefsFileAbs, false)) {
- LogFileError(
- GenT::MOC, predefsFileAbs,
- cmStrCat("Touching ", Quoted(predefsFileAbs), " failed."));
- 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 = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
- ", because it doesn't exist.");
- }
- return true;
- }
- // Test if the settings changed
- if (MocConst().SettingsChanged) {
- if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
- ", 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 = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
- " because it is older than ", Quoted(exec), '.');
- }
- 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)) {
- LogFileError(GenT::MOC, sourceFile.FileName,
- 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"));
- 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) {
- LogFileError(GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ",
- Quoted(incKey.Key),
- ",\nbut the header could not be found "
- "in the following locations\n",
- MocMessageTestHeaders(headerBase)));
- 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
- Log().WarningFile(
- GenT::MOC, sourceFile.FileName,
- 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"));
- // 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) {
- LogFileError(
- GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
- ",\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",
- MocMessageTestHeaders(headerBase)));
- return false;
- }
- // Check if header is skipped
- if (MocConst().skipped(header->FileName)) {
- continue;
- }
- // Issue a warning
- if (ownMoc && parseData.Macro.empty()) {
- Log().WarningFile(
- GenT::MOC, sourceFile.FileName,
- 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"));
- } else {
- Log().WarningFile(
- GenT::MOC, sourceFile.FileName,
- 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"));
- }
- // 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
- LogFileError(
- GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
- ",\nwhich seems to be the moc file from a different "
- "source file.\nThis is not supported. Include ",
- Quoted(sourceBase + ".moc"),
- " to run moc on this source file."));
- return false;
- }
- // Accept but issue a warning if moc isn't required
- if (parseData.Macro.empty()) {
- Log().WarningFile(GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ",
- Quoted(incKey.Key),
- ", but does not contain a ",
- MocConst().MacrosString(), " macro."));
- }
- // 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::CollapseFullPath(testPath,
- BaseConst().CurrentSourceDir);
- // 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(
- cm::string_view fileBase) const
- {
- std::string const exts =
- cmStrCat(".{", cmJoin(BaseConst().HeaderExtensions, ","), '}');
- // Compose result string
- std::string res = cmStrCat(" ", fileBase, exts, '\n');
- for (std::string const& path : MocConst().IncludePaths) {
- res += cmStrCat(" ", path, '/', fileBase, exts, '\n');
- }
- return res;
- }
- 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 files =
- cmStrCat(" ", Quoted(includerFileHandle->FileName), '\n');
- for (auto const& item : handle->IncluderFiles) {
- files += cmStrCat(" ", Quoted(item->FileName), '\n');
- }
- LogError(
- GenT::MOC,
- cmStrCat("The source files\n", files,
- "contain the same include string ", Quoted(includeString),
- ", but\nthe moc file would be generated from different "
- "source files\n ",
- Quoted(sourceFileHandle->FileName), " and\n ",
- Quoted(handle->SourceFile->FileName),
- ".\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"));
- 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 const& 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),
- 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 files =
- cmStrCat(" ", Quoted(includerFileHandle->FileName), '\n');
- for (auto const& item : handle->IncluderFiles) {
- files += cmStrCat(" ", Quoted(item->FileName), '\n');
- }
- LogError(
- GenT::UIC,
- cmStrCat(
- "The source files\n", files, "contain the same include string ",
- Quoted(includeString),
- ", but\nthe uic file would be generated from different "
- "user interface files\n ",
- Quoted(uiFileHandle->FileName), " and\n ",
- Quoted(handle->SourceFile->FileName),
- ".\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"));
- 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 fullPath = cmSystemTools::CollapseFullPath(
- testFile, BaseConst().CurrentSourceDir);
- // Get or create .ui file handle
- SourceFileHandleT& handle = Gen()->UicEval().UiFiles[fullPath];
- if (!handle) {
- // The file wasn't registered, yet
- handle = std::make_shared<SourceFileT>(fullPath);
- handle->FileTime = fileTime;
- }
- return handle;
- }
- }
- // Log error
- {
- std::string files;
- for (std::string const& testFile : testFiles) {
- files += cmStrCat(" ", Quoted(testFile), '\n');
- }
- LogFileError(
- GenT::UIC, sourceFile,
- 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", files));
- }
- 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 =
- cmStrCat("Generating ", Quoted(outputFile),
- ", because it doesn't exist, from ", Quoted(sourceFile));
- }
- return true;
- }
- // Test if any setting changed
- if (MocConst().SettingsChanged) {
- if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
- ", because the uic settings changed, from ",
- Quoted(sourceFile));
- }
- return true;
- }
- // Test if the source file is newer
- if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
- if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
- ", because it's older than its source file, from ",
- 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 = cmStrCat(
- "Generating ", Quoted(outputFile), ", because it's older than ",
- Quoted(MocConst().PredefsFileAbs), ", from ", Quoted(sourceFile));
- }
- return true;
- }
- }
- // Test if the moc executable is newer
- if (outputFileTime.Older(MocConst().ExecutableTime)) {
- if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
- ", because it's older than the moc executable, from ",
- 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 =
- cmStrCat("Generating ", Quoted(outputFile),
- ", because it's older than its dependency file ",
- Quoted(depMatch.first), ", from ", Quoted(sourceFile));
- }
- return true;
- }
- }
- }
- return false;
- }
- std::pair<std::string, cmFileTime>
- cmQtAutoMocUic::JobGenerateT::MocFindDependency(
- std::string const& sourceDir, std::string const& includeString) const
- {
- using ResPair = std::pair<std::string, cmFileTime>;
- // 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{ cmStrCat(includePath, '/', 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 =
- cmStrCat("Generating ", Quoted(outputFile),
- ", because it doesn't exist, from ", Quoted(sourceFile));
- }
- return true;
- }
- // Test if the uic settings changed
- if (UicConst().SettingsChanged) {
- if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
- ", because the uic settings changed, from ",
- Quoted(sourceFile));
- }
- return true;
- }
- // Test if the source file is newer
- if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
- if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
- " because it's older than the source file ",
- Quoted(sourceFile));
- }
- return true;
- }
- // Test if the uic executable is newer
- if (outputFileTime.Older(UicConst().ExecutableTime)) {
- if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
- ", because it's older than the uic executable, from ",
- 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 includers;
- if (!Mapping->IncluderFiles.empty()) {
- includers = "included by\n";
- for (auto const& item : Mapping->IncluderFiles) {
- includers += cmStrCat(" ", Quoted(item->FileName), '\n');
- }
- }
- LogCommandError(GenT::MOC,
- cmStrCat("The moc process failed to compile\n ",
- Quoted(sourceFile), "\ninto\n ",
- Quoted(outputFile), '\n', includers,
- result.ErrorMessage),
- 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 includers;
- for (auto const& item : Mapping->IncluderFiles) {
- includers += cmStrCat(" ", Quoted(item->FileName), '\n');
- }
- LogCommandError(GenT::UIC,
- cmStrCat("The uic process failed to compile\n ",
- Quoted(sourceFile), "\ninto\n ",
- Quoted(outputFile), "\nincluded by\n", includers,
- result.ErrorMessage),
- 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"
- "enum some_compilers { need_more_than_nothing };\n";
- } else {
- // Valid content
- const bool mc = BaseConst().MultiConfig;
- cm::string_view const wrapFront = mc ? "#include <" : "#include \"";
- cm::string_view const wrapBack = mc ? ">\n" : "\"\n";
- content += cmWrap(wrapFront, MocEval().CompFiles, wrapBack, "");
- }
- 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](cm::string_view key) {
- return makefile->GetSafeDefinition(std::string(key));
- };
- auto InfoGetBool = [makefile](cm::string_view key) {
- return makefile->IsOn(std::string(key));
- };
- auto InfoGetList =
- [makefile](cm::string_view key) -> std::vector<std::string> {
- return cmExpandedList(makefile->GetSafeDefinition(std::string(key)));
- };
- auto InfoGetLists =
- [makefile](cm::string_view key) -> std::vector<std::vector<std::string>> {
- std::vector<std::vector<std::string>> lists;
- {
- std::string const value = makefile->GetSafeDefinition(std::string(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(cmExpandedList(std::string(itBeg, itEnd)));
- }
- pos += length;
- pos += ListSep.size();
- }
- }
- return lists;
- };
- auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string {
- if (const char* valueConf =
- makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) {
- return std::string(valueConf);
- }
- return makefile->GetSafeDefinition(std::string(key));
- };
- auto InfoGetConfigList =
- [&InfoGetConfig](cm::string_view key) -> std::vector<std::string> {
- return cmExpandedList(InfoGetConfig(key));
- };
- auto LogInfoError = [this](cm::string_view msg) -> bool {
- this->Log().Error(GenT::GEN,
- cmStrCat("In ", Quoted(this->InfoFile()), ":\n", msg));
- return false;
- };
- auto MatchSizes = [&LogInfoError](cm::string_view keyA, cm::string_view keyB,
- std::size_t sizeA,
- std::size_t sizeB) -> bool {
- if (sizeA == sizeB) {
- return true;
- }
- return LogInfoError(cmStrCat("Lists sizes mismatch ", keyA, '(', sizeA,
- ") ", keyB, '(', sizeB, ')'));
- };
- // -- 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 (cmStrToULong(InfoGet("AM_PARALLEL"), &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)) {
- return LogInfoError(cmStrCat("The CMake executable ",
- Quoted(BaseConst_.CMakeExecutable),
- " does not exist."));
- }
- 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 (cmStrToULong(InfoGet("AM_QT_VERSION_MAJOR"), &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)) {
- return LogInfoError(cmStrCat("The moc executable ",
- Quoted(MocConst_.Executable),
- " does not exist."));
- }
- 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](cm::string_view err) -> bool {
- return LogInfoError(cmStrCat("AUTOMOC_DEPEND_FILTERS: ", err, '\n',
- " Key: ", Quoted(key), '\n',
- " Exp: ", Quoted(exp), '\n'));
- };
- 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)) {
- return LogInfoError(cmStrCat("The uic executable ",
- Quoted(UicConst_.Executable),
- " does not exist."));
- }
- 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");
- {
- cm::string_view const keyFiles = "AM_UIC_OPTIONS_FILES";
- cm::string_view const 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
- cm::string_view const keyFiles = "AM_HEADERS";
- cm::string_view const 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) {
- cm::string_view const 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
- {
- cm::string_view const keyFiles = "AM_SOURCES";
- cm::string_view const 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()) {
- if (BaseConst_.MultiConfig) {
- MocConst_.PredefsFileRel =
- cmStrCat("moc_predefs_", InfoConfig(), ".h");
- } else {
- MocConst_.PredefsFileRel = "moc_predefs.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::initializer_list<cm::string_view> const movePaths = {
- BaseConst().ProjectBinaryDir, BaseConst().ProjectSourceDir
- };
- for (cm::string_view const& ppath : movePaths) {
- auto 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);
- auto cha = [&cryptoHash](cm::string_view value) {
- cryptoHash.Append(value);
- cryptoHash.Append(";");
- };
- if (MocConst_.Enabled) {
- cryptoHash.Initialize();
- cha(MocConst().Executable);
- std::for_each(MocConst().AllOptions.begin(), MocConst().AllOptions.end(),
- cha);
- cha(BaseConst().IncludeProjectDirsBefore ? "TRUE" : "FALSE");
- std::for_each(MocConst().PredefsCmd.begin(), MocConst().PredefsCmd.end(),
- cha);
- 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);
- std::for_each(UicConst().TargetOptions.begin(),
- UicConst().TargetOptions.end(), cha);
- for (const auto& item : UicConst().Options) {
- cha(item.first);
- std::for_each(item.second.begin(), item.second.end(), cha);
- }
- 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](cm::string_view key,
- cm::string_view value) {
- if (!value.empty()) {
- content += cmStrCat(key, ':', value, '\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()
- {
- cm::string_view reason;
- // 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.empty()) {
- // 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(
- cm::string_view relativePath) const
- {
- return cmStrCat(BaseConst().AutogenBuildDir, '/', relativePath);
- }
- std::string cmQtAutoMocUic::AbsoluteIncludePath(
- cm::string_view relativePath) const
- {
- return cmStrCat(BaseConst().AutogenIncludeDir, '/', relativePath);
- }
|