cmQtAutoGenerators.cxx 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2004-2011 Kitware, Inc.
  4. Copyright 2011 Alexander Neundorf ([email protected])
  5. Distributed under the OSI-approved BSD License (the "License");
  6. see accompanying file Copyright.txt for details.
  7. This software is distributed WITHOUT ANY WARRANTY; without even the
  8. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. See the License for more information.
  10. ============================================================================*/
  11. #include "cmGlobalGenerator.h"
  12. #include "cmLocalGenerator.h"
  13. #include "cmMakefile.h"
  14. #include "cmSourceFile.h"
  15. #include "cmSystemTools.h"
  16. #if defined(_WIN32) && !defined(__CYGWIN__)
  17. # include "cmLocalVisualStudioGenerator.h"
  18. #endif
  19. #include <cmsys/Terminal.h>
  20. #include <cmsys/ios/sstream>
  21. #include <cmsys/FStream.hxx>
  22. #include <assert.h>
  23. #include <string.h>
  24. #if defined(__APPLE__)
  25. #include <unistd.h>
  26. #endif
  27. #include "cmQtAutoGenerators.h"
  28. static bool requiresMocing(const std::string& text, std::string &macroName)
  29. {
  30. // this simple check is much much faster than the regexp
  31. if (strstr(text.c_str(), "Q_OBJECT") == NULL
  32. && strstr(text.c_str(), "Q_GADGET") == NULL)
  33. {
  34. return false;
  35. }
  36. cmsys::RegularExpression qObjectRegExp("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
  37. if (qObjectRegExp.find(text))
  38. {
  39. macroName = "Q_OBJECT";
  40. return true;
  41. }
  42. cmsys::RegularExpression qGadgetRegExp("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]");
  43. if (qGadgetRegExp.find(text))
  44. {
  45. macroName = "Q_GADGET";
  46. return true;
  47. }
  48. return false;
  49. }
  50. static std::string findMatchingHeader(const std::string& absPath,
  51. const std::string& mocSubDir,
  52. const std::string& basename,
  53. const std::vector<std::string>& headerExtensions)
  54. {
  55. std::string header;
  56. for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
  57. ext != headerExtensions.end();
  58. ++ext)
  59. {
  60. std::string sourceFilePath = absPath + basename + "." + (*ext);
  61. if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
  62. {
  63. header = sourceFilePath;
  64. break;
  65. }
  66. if (!mocSubDir.empty())
  67. {
  68. sourceFilePath = mocSubDir + basename + "." + (*ext);
  69. if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
  70. {
  71. header = sourceFilePath;
  72. break;
  73. }
  74. }
  75. }
  76. return header;
  77. }
  78. static std::string extractSubDir(const std::string& absPath,
  79. const std::string& currentMoc)
  80. {
  81. std::string subDir;
  82. if (currentMoc.find_first_of('/') != std::string::npos)
  83. {
  84. subDir = absPath
  85. + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/';
  86. }
  87. return subDir;
  88. }
  89. static void copyTargetProperty(cmTarget* destinationTarget,
  90. cmTarget* sourceTarget,
  91. const std::string& propertyName)
  92. {
  93. const char* propertyValue = sourceTarget->GetProperty(propertyName);
  94. if (propertyValue)
  95. {
  96. destinationTarget->SetProperty(propertyName, propertyValue);
  97. }
  98. }
  99. static std::string ReadAll(const std::string& filename)
  100. {
  101. cmsys::ifstream file(filename.c_str());
  102. cmsys_ios::stringstream stream;
  103. stream << file.rdbuf();
  104. file.close();
  105. return stream.str();
  106. }
  107. cmQtAutoGenerators::cmQtAutoGenerators()
  108. :Verbose(cmsys::SystemTools::GetEnv("VERBOSE") != 0)
  109. ,ColorOutput(true)
  110. ,RunMocFailed(false)
  111. ,RunUicFailed(false)
  112. ,RunRccFailed(false)
  113. ,GenerateAll(false)
  114. {
  115. std::string colorEnv = "";
  116. cmsys::SystemTools::GetEnv("COLOR", colorEnv);
  117. if(!colorEnv.empty())
  118. {
  119. if(cmSystemTools::IsOn(colorEnv.c_str()))
  120. {
  121. this->ColorOutput = true;
  122. }
  123. else
  124. {
  125. this->ColorOutput = false;
  126. }
  127. }
  128. }
  129. static std::string getAutogenTargetName(cmTarget const* target)
  130. {
  131. std::string autogenTargetName = target->GetName();
  132. autogenTargetName += "_automoc";
  133. return autogenTargetName;
  134. }
  135. static std::string getAutogenTargetDir(cmTarget const* target)
  136. {
  137. cmMakefile* makefile = target->GetMakefile();
  138. std::string targetDir = makefile->GetCurrentOutputDirectory();
  139. targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
  140. targetDir += "/";
  141. targetDir += getAutogenTargetName(target);
  142. targetDir += ".dir/";
  143. return targetDir;
  144. }
  145. std::string cmQtAutoGenerators::ListQt5RccInputs(cmSourceFile* sf,
  146. cmTarget const* target,
  147. std::vector<std::string>& depends)
  148. {
  149. std::string rccCommand = this->GetRccExecutable(target);
  150. std::vector<std::string> qrcEntries;
  151. std::vector<std::string> command;
  152. command.push_back(rccCommand);
  153. command.push_back("--list");
  154. std::string absFile = cmsys::SystemTools::GetRealPath(
  155. sf->GetFullPath());
  156. command.push_back(absFile);
  157. std::string output;
  158. int retVal = 0;
  159. bool result = cmSystemTools::RunSingleCommand(command, &output,
  160. &retVal, 0,
  161. cmSystemTools::OUTPUT_NONE);
  162. if (!result || retVal)
  163. {
  164. std::cerr << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath()
  165. << " failed:\n" << output << std::endl;
  166. return std::string();
  167. }
  168. std::istringstream ostr(output);
  169. std::string oline;
  170. while(std::getline(ostr, oline))
  171. {
  172. if (oline.empty())
  173. {
  174. // The output of rcc --list contains many empty lines.
  175. continue;
  176. }
  177. if (cmHasLiteralPrefix(oline, "RCC: Error in"))
  178. {
  179. static std::string searchString = "Cannot find file '";
  180. std::string::size_type pos = oline.find(searchString);
  181. if (pos == std::string::npos)
  182. {
  183. std::cerr << "AUTOGEN: error: Rcc lists unparsable output "
  184. << oline << std::endl;
  185. return std::string();
  186. }
  187. pos += searchString.length();
  188. std::string::size_type sz = oline.size() - pos - 1;
  189. qrcEntries.push_back(oline.substr(pos, sz));
  190. }
  191. else
  192. {
  193. qrcEntries.push_back(oline);
  194. }
  195. }
  196. depends.insert(depends.end(), qrcEntries.begin(), qrcEntries.end());
  197. std::string entriesList;
  198. const char* sep = "";
  199. for(std::vector<std::string>::const_iterator it = qrcEntries.begin();
  200. it != qrcEntries.end(); ++it)
  201. {
  202. entriesList += sep;
  203. entriesList += *it;
  204. sep = "@list_sep@";
  205. }
  206. return entriesList;
  207. }
  208. std::string cmQtAutoGenerators::ListQt4RccInputs(cmSourceFile* sf,
  209. std::vector<std::string>& depends)
  210. {
  211. const std::string qrcContents = ReadAll(sf->GetFullPath());
  212. cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
  213. std::string entriesList;
  214. const char* sep = "";
  215. size_t offset = 0;
  216. while (fileMatchRegex.find(qrcContents.c_str() + offset))
  217. {
  218. std::string qrcEntry = fileMatchRegex.match(1);
  219. offset += qrcEntry.size();
  220. cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
  221. fileReplaceRegex.find(qrcEntry);
  222. std::string tag = fileReplaceRegex.match(1);
  223. qrcEntry = qrcEntry.substr(tag.size());
  224. if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str()))
  225. {
  226. qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry;
  227. }
  228. entriesList += sep;
  229. entriesList += qrcEntry;
  230. sep = "@list_sep@";
  231. depends.push_back(qrcEntry);
  232. }
  233. return entriesList;
  234. }
  235. bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
  236. {
  237. cmMakefile* makefile = target->GetMakefile();
  238. // don't do anything if there is no Qt4 or Qt5Core (which contains moc):
  239. std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
  240. if (qtMajorVersion == "")
  241. {
  242. qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
  243. }
  244. if (qtMajorVersion != "4" && qtMajorVersion != "5")
  245. {
  246. return false;
  247. }
  248. if (target->GetPropertyAsBool("AUTOMOC"))
  249. {
  250. std::string automocTargetName = getAutogenTargetName(target);
  251. std::string mocCppFile = makefile->GetCurrentOutputDirectory();
  252. mocCppFile += "/";
  253. mocCppFile += automocTargetName;
  254. mocCppFile += ".cpp";
  255. makefile->GetOrCreateSource(mocCppFile, true);
  256. makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
  257. mocCppFile.c_str(), false);
  258. target->AddSource(mocCppFile);
  259. }
  260. // create a custom target for running generators at buildtime:
  261. std::string autogenTargetName = getAutogenTargetName(target);
  262. std::string targetDir = getAutogenTargetDir(target);
  263. cmCustomCommandLine currentLine;
  264. currentLine.push_back(makefile->GetSafeDefinition("CMAKE_COMMAND"));
  265. currentLine.push_back("-E");
  266. currentLine.push_back("cmake_autogen");
  267. currentLine.push_back(targetDir);
  268. currentLine.push_back("$<CONFIGURATION>");
  269. cmCustomCommandLines commandLines;
  270. commandLines.push_back(currentLine);
  271. std::string workingDirectory = cmSystemTools::CollapseFullPath(
  272. "", makefile->GetCurrentOutputDirectory());
  273. std::vector<std::string> depends;
  274. if (const char *autogenDepends =
  275. target->GetProperty("AUTOGEN_TARGET_DEPENDS"))
  276. {
  277. cmSystemTools::ExpandListArgument(autogenDepends, depends);
  278. }
  279. std::vector<std::string> toolNames;
  280. if (target->GetPropertyAsBool("AUTOMOC"))
  281. {
  282. toolNames.push_back("moc");
  283. }
  284. if (target->GetPropertyAsBool("AUTOUIC"))
  285. {
  286. toolNames.push_back("uic");
  287. }
  288. if (target->GetPropertyAsBool("AUTORCC"))
  289. {
  290. toolNames.push_back("rcc");
  291. }
  292. std::string tools = toolNames[0];
  293. toolNames.erase(toolNames.begin());
  294. while (toolNames.size() > 1)
  295. {
  296. tools += ", " + toolNames[0];
  297. toolNames.erase(toolNames.begin());
  298. }
  299. if (toolNames.size() == 1)
  300. {
  301. tools += " and " + toolNames[0];
  302. }
  303. std::string autogenComment = "Automatic " + tools + " for target ";
  304. autogenComment += target->GetName();
  305. #if defined(_WIN32) && !defined(__CYGWIN__)
  306. bool usePRE_BUILD = false;
  307. cmLocalGenerator* localGen = makefile->GetLocalGenerator();
  308. cmGlobalGenerator* gg = localGen->GetGlobalGenerator();
  309. if(gg->GetName().find("Visual Studio") != std::string::npos)
  310. {
  311. cmLocalVisualStudioGenerator* vslg =
  312. static_cast<cmLocalVisualStudioGenerator*>(localGen);
  313. // Under VS >= 7 use a PRE_BUILD event instead of a separate target to
  314. // reduce the number of targets loaded into the IDE.
  315. // This also works around a VS 11 bug that may skip updating the target:
  316. // https://connect.microsoft.com/VisualStudio/feedback/details/769495
  317. usePRE_BUILD = vslg->GetVersion() >= cmLocalVisualStudioGenerator::VS7;
  318. if(usePRE_BUILD)
  319. {
  320. for (std::vector<std::string>::iterator it = depends.begin();
  321. it != depends.end(); ++it)
  322. {
  323. if(!makefile->FindTargetToUse(it->c_str()))
  324. {
  325. usePRE_BUILD = false;
  326. break;
  327. }
  328. }
  329. }
  330. }
  331. #endif
  332. std::vector<std::string> rcc_output;
  333. if(makefile->GetLocalGenerator()->GetGlobalGenerator()->GetName() == "Ninja"
  334. #if defined(_WIN32) && !defined(__CYGWIN__)
  335. || usePRE_BUILD
  336. #endif
  337. )
  338. {
  339. std::vector<cmSourceFile*> srcFiles;
  340. target->GetConfigCommonSourceFiles(srcFiles);
  341. for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
  342. fileIt != srcFiles.end();
  343. ++fileIt)
  344. {
  345. cmSourceFile* sf = *fileIt;
  346. std::string absFile = cmsys::SystemTools::GetRealPath(
  347. sf->GetFullPath());
  348. std::string ext = sf->GetExtension();
  349. if (target->GetPropertyAsBool("AUTORCC"))
  350. {
  351. if (ext == "qrc"
  352. && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")))
  353. {
  354. std::string basename = cmsys::SystemTools::
  355. GetFilenameWithoutLastExtension(absFile);
  356. std::string rcc_output_dir = target->GetSupportDirectory();
  357. cmSystemTools::MakeDirectory(rcc_output_dir.c_str());
  358. std::string rcc_output_file = rcc_output_dir;
  359. rcc_output_file += "/qrc_" + basename + ".cpp";
  360. rcc_output.push_back(rcc_output_file);
  361. if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")))
  362. {
  363. if (qtMajorVersion == "5")
  364. {
  365. this->ListQt5RccInputs(sf, target, depends);
  366. }
  367. else
  368. {
  369. this->ListQt4RccInputs(sf, depends);
  370. }
  371. #if defined(_WIN32) && !defined(__CYGWIN__)
  372. usePRE_BUILD = false;
  373. #endif
  374. }
  375. }
  376. }
  377. }
  378. }
  379. #if defined(_WIN32) && !defined(__CYGWIN__)
  380. if(usePRE_BUILD)
  381. {
  382. // Add the pre-build command directly to bypass the OBJECT_LIBRARY
  383. // rejection in cmMakefile::AddCustomCommandToTarget because we know
  384. // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
  385. std::vector<std::string> no_output;
  386. cmCustomCommand cc(makefile, no_output, depends,
  387. commandLines, autogenComment.c_str(),
  388. workingDirectory.c_str());
  389. cc.SetEscapeOldStyle(false);
  390. cc.SetEscapeAllowMakeVars(true);
  391. target->AddPreBuildCommand(cc);
  392. }
  393. else
  394. #endif
  395. {
  396. cmTarget* autogenTarget = 0;
  397. if (!rcc_output.empty())
  398. {
  399. makefile->AddCustomCommandToOutput(rcc_output, depends, "",
  400. commandLines, 0,
  401. workingDirectory.c_str(),
  402. false, false);
  403. cmCustomCommandLines no_commands;
  404. autogenTarget = makefile->AddUtilityCommand(
  405. autogenTargetName, true,
  406. workingDirectory.c_str(), rcc_output,
  407. no_commands, false, autogenComment.c_str());
  408. }
  409. else
  410. {
  411. autogenTarget = makefile->AddUtilityCommand(
  412. autogenTargetName, true,
  413. workingDirectory.c_str(), depends,
  414. commandLines, false, autogenComment.c_str());
  415. }
  416. // Set target folder
  417. const char* autogenFolder = makefile->GetCMakeInstance()->GetProperty(
  418. "AUTOMOC_TARGETS_FOLDER");
  419. if (!autogenFolder)
  420. {
  421. autogenFolder = makefile->GetCMakeInstance()->GetProperty(
  422. "AUTOGEN_TARGETS_FOLDER");
  423. }
  424. if (autogenFolder && *autogenFolder)
  425. {
  426. autogenTarget->SetProperty("FOLDER", autogenFolder);
  427. }
  428. else
  429. {
  430. // inherit FOLDER property from target (#13688)
  431. copyTargetProperty(autogenTarget, target, "FOLDER");
  432. }
  433. target->AddUtility(autogenTargetName);
  434. }
  435. return true;
  436. }
  437. static void GetCompileDefinitionsAndDirectories(cmTarget const* target,
  438. const std::string& config,
  439. std::string &incs,
  440. std::string &defs)
  441. {
  442. cmMakefile* makefile = target->GetMakefile();
  443. cmLocalGenerator* localGen = makefile->GetLocalGenerator();
  444. std::vector<std::string> includeDirs;
  445. cmGeneratorTarget *gtgt = target->GetMakefile()->GetLocalGenerator()
  446. ->GetGlobalGenerator()
  447. ->GetGeneratorTarget(target);
  448. // Get the include dirs for this target, without stripping the implicit
  449. // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667
  450. localGen->GetIncludeDirectories(includeDirs, gtgt, "CXX", config, false);
  451. const char* sep = "";
  452. incs = "";
  453. for(std::vector<std::string>::const_iterator incDirIt = includeDirs.begin();
  454. incDirIt != includeDirs.end();
  455. ++incDirIt)
  456. {
  457. incs += sep;
  458. sep = ";";
  459. incs += *incDirIt;
  460. }
  461. std::set<std::string> defines;
  462. localGen->AddCompileDefinitions(defines, target, config);
  463. sep = "";
  464. for(std::set<std::string>::const_iterator defIt = defines.begin();
  465. defIt != defines.end();
  466. ++defIt)
  467. {
  468. defs += sep;
  469. sep = ";";
  470. defs += *defIt;
  471. }
  472. }
  473. void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target)
  474. {
  475. cmMakefile* makefile = target->GetMakefile();
  476. // forget the variables added here afterwards again:
  477. cmMakefile::ScopePushPop varScope(makefile);
  478. static_cast<void>(varScope);
  479. // create a custom target for running generators at buildtime:
  480. std::string autogenTargetName = getAutogenTargetName(target);
  481. makefile->AddDefinition("_moc_target_name",
  482. cmLocalGenerator::EscapeForCMake(autogenTargetName).c_str());
  483. makefile->AddDefinition("_origin_target_name",
  484. cmLocalGenerator::EscapeForCMake(target->GetName()).c_str());
  485. std::string targetDir = getAutogenTargetDir(target);
  486. const char *qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR");
  487. if (!qtVersion)
  488. {
  489. qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
  490. }
  491. if (const char *targetQtVersion =
  492. target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""))
  493. {
  494. qtVersion = targetQtVersion;
  495. }
  496. if (qtVersion)
  497. {
  498. makefile->AddDefinition("_target_qt_version", qtVersion);
  499. }
  500. std::map<std::string, std::string> configIncludes;
  501. std::map<std::string, std::string> configDefines;
  502. std::map<std::string, std::string> configUicOptions;
  503. if (target->GetPropertyAsBool("AUTOMOC")
  504. || target->GetPropertyAsBool("AUTOUIC")
  505. || target->GetPropertyAsBool("AUTORCC"))
  506. {
  507. this->SetupSourceFiles(target);
  508. }
  509. makefile->AddDefinition("_cpp_files",
  510. cmLocalGenerator::EscapeForCMake(this->Sources).c_str());
  511. if (target->GetPropertyAsBool("AUTOMOC"))
  512. {
  513. this->SetupAutoMocTarget(target, autogenTargetName,
  514. configIncludes, configDefines);
  515. }
  516. if (target->GetPropertyAsBool("AUTOUIC"))
  517. {
  518. this->SetupAutoUicTarget(target, configUicOptions);
  519. }
  520. if (target->GetPropertyAsBool("AUTORCC"))
  521. {
  522. this->SetupAutoRccTarget(target);
  523. }
  524. const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT");
  525. std::string inputFile = cmakeRoot;
  526. inputFile += "/Modules/AutogenInfo.cmake.in";
  527. std::string outputFile = targetDir;
  528. outputFile += "/AutogenInfo.cmake";
  529. makefile->AddDefinition("_qt_rcc_inputs",
  530. makefile->GetDefinition("_qt_rcc_inputs_" + target->GetName()));
  531. makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(),
  532. false, true, false);
  533. if (!configDefines.empty()
  534. || !configIncludes.empty()
  535. || !configUicOptions.empty())
  536. {
  537. cmsys::ofstream infoFile(outputFile.c_str(), std::ios::app);
  538. if ( !infoFile )
  539. {
  540. std::string error = "Internal CMake error when trying to open file: ";
  541. error += outputFile.c_str();
  542. error += " for writing.";
  543. cmSystemTools::Error(error.c_str());
  544. return;
  545. }
  546. if (!configDefines.empty())
  547. {
  548. for (std::map<std::string, std::string>::iterator
  549. it = configDefines.begin(), end = configDefines.end();
  550. it != end; ++it)
  551. {
  552. infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first <<
  553. " " << it->second << ")\n";
  554. }
  555. }
  556. if (!configIncludes.empty())
  557. {
  558. for (std::map<std::string, std::string>::iterator
  559. it = configIncludes.begin(), end = configIncludes.end();
  560. it != end; ++it)
  561. {
  562. infoFile << "set(AM_MOC_INCLUDES_" << it->first <<
  563. " " << it->second << ")\n";
  564. }
  565. }
  566. if (!configUicOptions.empty())
  567. {
  568. for (std::map<std::string, std::string>::iterator
  569. it = configUicOptions.begin(), end = configUicOptions.end();
  570. it != end; ++it)
  571. {
  572. infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first <<
  573. " " << it->second << ")\n";
  574. }
  575. }
  576. }
  577. }
  578. void cmQtAutoGenerators::SetupSourceFiles(cmTarget const* target)
  579. {
  580. cmMakefile* makefile = target->GetMakefile();
  581. const char* sepFiles = "";
  582. const char* sepHeaders = "";
  583. std::vector<cmSourceFile*> srcFiles;
  584. target->GetConfigCommonSourceFiles(srcFiles);
  585. const char *skipMocSep = "";
  586. const char *skipUicSep = "";
  587. std::vector<std::string> newRccFiles;
  588. for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
  589. fileIt != srcFiles.end();
  590. ++fileIt)
  591. {
  592. cmSourceFile* sf = *fileIt;
  593. std::string absFile = cmsys::SystemTools::GetRealPath(
  594. sf->GetFullPath());
  595. bool skipMoc = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"));
  596. bool generated = cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"));
  597. if(cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC")))
  598. {
  599. this->SkipUic += skipUicSep;
  600. this->SkipUic += absFile;
  601. skipUicSep = ";";
  602. }
  603. std::string ext = sf->GetExtension();
  604. if (target->GetPropertyAsBool("AUTORCC"))
  605. {
  606. if (ext == "qrc"
  607. && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")))
  608. {
  609. std::string basename = cmsys::SystemTools::
  610. GetFilenameWithoutLastExtension(absFile);
  611. std::string rcc_output_dir = target->GetSupportDirectory();
  612. cmSystemTools::MakeDirectory(rcc_output_dir.c_str());
  613. std::string rcc_output_file = rcc_output_dir;
  614. rcc_output_file += "/qrc_" + basename + ".cpp";
  615. makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
  616. rcc_output_file.c_str(), false);
  617. makefile->GetOrCreateSource(rcc_output_file, true);
  618. newRccFiles.push_back(rcc_output_file);
  619. }
  620. }
  621. if (!generated)
  622. {
  623. if (skipMoc)
  624. {
  625. this->SkipMoc += skipMocSep;
  626. this->SkipMoc += absFile;
  627. skipMocSep = ";";
  628. }
  629. else
  630. {
  631. cmSystemTools::FileFormat fileType = cmSystemTools::GetFileFormat(
  632. ext.c_str());
  633. if (fileType == cmSystemTools::CXX_FILE_FORMAT)
  634. {
  635. this->Sources += sepFiles;
  636. this->Sources += absFile;
  637. sepFiles = ";";
  638. }
  639. else if (fileType == cmSystemTools::HEADER_FILE_FORMAT)
  640. {
  641. this->Headers += sepHeaders;
  642. this->Headers += absFile;
  643. sepHeaders = ";";
  644. }
  645. }
  646. }
  647. }
  648. for(std::vector<std::string>::const_iterator fileIt = newRccFiles.begin();
  649. fileIt != newRccFiles.end();
  650. ++fileIt)
  651. {
  652. const_cast<cmTarget*>(target)->AddSource(*fileIt);
  653. }
  654. }
  655. void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target,
  656. const std::string &autogenTargetName,
  657. std::map<std::string, std::string> &configIncludes,
  658. std::map<std::string, std::string> &configDefines)
  659. {
  660. cmMakefile* makefile = target->GetMakefile();
  661. const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS");
  662. std::string _moc_options = (tmp!=0 ? tmp : "");
  663. makefile->AddDefinition("_moc_options",
  664. cmLocalGenerator::EscapeForCMake(_moc_options).c_str());
  665. makefile->AddDefinition("_skip_moc",
  666. cmLocalGenerator::EscapeForCMake(this->SkipMoc).c_str());
  667. makefile->AddDefinition("_moc_headers",
  668. cmLocalGenerator::EscapeForCMake(this->Headers).c_str());
  669. bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE");
  670. makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE");
  671. std::string _moc_incs;
  672. std::string _moc_compile_defs;
  673. std::vector<std::string> configs;
  674. const std::string& config = makefile->GetConfigurations(configs);
  675. GetCompileDefinitionsAndDirectories(target, config,
  676. _moc_incs, _moc_compile_defs);
  677. makefile->AddDefinition("_moc_incs",
  678. cmLocalGenerator::EscapeForCMake(_moc_incs).c_str());
  679. makefile->AddDefinition("_moc_compile_defs",
  680. cmLocalGenerator::EscapeForCMake(_moc_compile_defs).c_str());
  681. for (std::vector<std::string>::const_iterator li = configs.begin();
  682. li != configs.end(); ++li)
  683. {
  684. std::string config_moc_incs;
  685. std::string config_moc_compile_defs;
  686. GetCompileDefinitionsAndDirectories(target, *li,
  687. config_moc_incs,
  688. config_moc_compile_defs);
  689. if (config_moc_incs != _moc_incs)
  690. {
  691. configIncludes[*li] =
  692. cmLocalGenerator::EscapeForCMake(config_moc_incs);
  693. if(_moc_incs.empty())
  694. {
  695. _moc_incs = config_moc_incs;
  696. }
  697. }
  698. if (config_moc_compile_defs != _moc_compile_defs)
  699. {
  700. configDefines[*li] =
  701. cmLocalGenerator::EscapeForCMake(config_moc_compile_defs);
  702. if(_moc_compile_defs.empty())
  703. {
  704. _moc_compile_defs = config_moc_compile_defs;
  705. }
  706. }
  707. }
  708. const char *qtVersion = makefile->GetDefinition("_target_qt_version");
  709. if (strcmp(qtVersion, "5") == 0)
  710. {
  711. cmTarget *qt5Moc = makefile->FindTargetToUse("Qt5::moc");
  712. if (!qt5Moc)
  713. {
  714. cmSystemTools::Error("Qt5::moc target not found ",
  715. autogenTargetName.c_str());
  716. return;
  717. }
  718. makefile->AddDefinition("_qt_moc_executable", qt5Moc->GetLocation(""));
  719. }
  720. else if (strcmp(qtVersion, "4") == 0)
  721. {
  722. cmTarget *qt4Moc = makefile->FindTargetToUse("Qt4::moc");
  723. if (!qt4Moc)
  724. {
  725. cmSystemTools::Error("Qt4::moc target not found ",
  726. autogenTargetName.c_str());
  727. return;
  728. }
  729. makefile->AddDefinition("_qt_moc_executable", qt4Moc->GetLocation(""));
  730. }
  731. else
  732. {
  733. cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and "
  734. "Qt 5 ", autogenTargetName.c_str());
  735. }
  736. }
  737. void cmQtAutoGenerators::MergeUicOptions(std::vector<std::string> &opts,
  738. const std::vector<std::string> &fileOpts,
  739. bool isQt5)
  740. {
  741. static const char* valueOptions[] = {
  742. "tr",
  743. "translate",
  744. "postfix",
  745. "generator",
  746. "include", // Since Qt 5.3
  747. "g"
  748. };
  749. std::vector<std::string> extraOpts;
  750. for(std::vector<std::string>::const_iterator it = fileOpts.begin();
  751. it != fileOpts.end(); ++it)
  752. {
  753. std::vector<std::string>::iterator existingIt
  754. = std::find(opts.begin(), opts.end(), *it);
  755. if (existingIt != opts.end())
  756. {
  757. const char *o = it->c_str();
  758. if (*o == '-')
  759. {
  760. ++o;
  761. }
  762. if (isQt5 && *o == '-')
  763. {
  764. ++o;
  765. }
  766. if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
  767. cmStrCmp(*it)) != cmArrayEnd(valueOptions))
  768. {
  769. assert(existingIt + 1 != opts.end());
  770. *(existingIt + 1) = *(it + 1);
  771. ++it;
  772. }
  773. }
  774. else
  775. {
  776. extraOpts.push_back(*it);
  777. }
  778. }
  779. opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
  780. }
  781. static void GetUicOpts(cmTarget const* target, const std::string& config,
  782. std::string &optString)
  783. {
  784. std::vector<std::string> opts;
  785. target->GetAutoUicOptions(opts, config);
  786. const char* sep = "";
  787. for(std::vector<std::string>::const_iterator optIt = opts.begin();
  788. optIt != opts.end();
  789. ++optIt)
  790. {
  791. optString += sep;
  792. sep = ";";
  793. optString += *optIt;
  794. }
  795. }
  796. void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target,
  797. std::map<std::string, std::string> &configUicOptions)
  798. {
  799. cmMakefile *makefile = target->GetMakefile();
  800. std::set<std::string> skipped;
  801. std::vector<std::string> skipVec;
  802. cmSystemTools::ExpandListArgument(this->SkipUic, skipVec);
  803. for (std::vector<std::string>::const_iterator li = skipVec.begin();
  804. li != skipVec.end(); ++li)
  805. {
  806. skipped.insert(*li);
  807. }
  808. makefile->AddDefinition("_skip_uic",
  809. cmLocalGenerator::EscapeForCMake(this->SkipUic).c_str());
  810. std::vector<cmSourceFile*> uiFilesWithOptions
  811. = makefile->GetQtUiFilesWithOptions();
  812. const char *qtVersion = makefile->GetDefinition("_target_qt_version");
  813. std::string _uic_opts;
  814. std::vector<std::string> configs;
  815. const std::string& config = makefile->GetConfigurations(configs);
  816. GetUicOpts(target, config, _uic_opts);
  817. if (!_uic_opts.empty())
  818. {
  819. _uic_opts = cmLocalGenerator::EscapeForCMake(_uic_opts);
  820. makefile->AddDefinition("_uic_target_options", _uic_opts.c_str());
  821. }
  822. for (std::vector<std::string>::const_iterator li = configs.begin();
  823. li != configs.end(); ++li)
  824. {
  825. std::string config_uic_opts;
  826. GetUicOpts(target, *li, config_uic_opts);
  827. if (config_uic_opts != _uic_opts)
  828. {
  829. configUicOptions[*li] =
  830. cmLocalGenerator::EscapeForCMake(config_uic_opts);
  831. if(_uic_opts.empty())
  832. {
  833. _uic_opts = config_uic_opts;
  834. }
  835. }
  836. }
  837. std::string uiFileFiles;
  838. std::string uiFileOptions;
  839. const char* sep = "";
  840. for(std::vector<cmSourceFile*>::const_iterator fileIt =
  841. uiFilesWithOptions.begin();
  842. fileIt != uiFilesWithOptions.end();
  843. ++fileIt)
  844. {
  845. cmSourceFile* sf = *fileIt;
  846. std::string absFile = cmsys::SystemTools::GetRealPath(
  847. sf->GetFullPath());
  848. if (!skipped.insert(absFile).second)
  849. {
  850. continue;
  851. }
  852. uiFileFiles += sep;
  853. uiFileFiles += absFile;
  854. uiFileOptions += sep;
  855. std::string opts = sf->GetProperty("AUTOUIC_OPTIONS");
  856. cmSystemTools::ReplaceString(opts, ";", "@list_sep@");
  857. uiFileOptions += opts;
  858. sep = ";";
  859. }
  860. makefile->AddDefinition("_qt_uic_options_files",
  861. cmLocalGenerator::EscapeForCMake(uiFileFiles).c_str());
  862. makefile->AddDefinition("_qt_uic_options_options",
  863. cmLocalGenerator::EscapeForCMake(uiFileOptions).c_str());
  864. std::string targetName = target->GetName();
  865. if (strcmp(qtVersion, "5") == 0)
  866. {
  867. cmTarget *qt5Uic = makefile->FindTargetToUse("Qt5::uic");
  868. if (!qt5Uic)
  869. {
  870. // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
  871. }
  872. else
  873. {
  874. makefile->AddDefinition("_qt_uic_executable", qt5Uic->GetLocation(""));
  875. }
  876. }
  877. else if (strcmp(qtVersion, "4") == 0)
  878. {
  879. cmTarget *qt4Uic = makefile->FindTargetToUse("Qt4::uic");
  880. if (!qt4Uic)
  881. {
  882. cmSystemTools::Error("Qt4::uic target not found ",
  883. targetName.c_str());
  884. return;
  885. }
  886. makefile->AddDefinition("_qt_uic_executable", qt4Uic->GetLocation(""));
  887. }
  888. else
  889. {
  890. cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and "
  891. "Qt 5 ", targetName.c_str());
  892. }
  893. }
  894. void cmQtAutoGenerators::MergeRccOptions(std::vector<std::string> &opts,
  895. const std::vector<std::string> &fileOpts,
  896. bool isQt5)
  897. {
  898. static const char* valueOptions[] = {
  899. "name",
  900. "root",
  901. "compress",
  902. "threshold"
  903. };
  904. std::vector<std::string> extraOpts;
  905. for(std::vector<std::string>::const_iterator it = fileOpts.begin();
  906. it != fileOpts.end(); ++it)
  907. {
  908. std::vector<std::string>::iterator existingIt
  909. = std::find(opts.begin(), opts.end(), *it);
  910. if (existingIt != opts.end())
  911. {
  912. const char *o = it->c_str();
  913. if (*o == '-')
  914. {
  915. ++o;
  916. }
  917. if (isQt5 && *o == '-')
  918. {
  919. ++o;
  920. }
  921. if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
  922. cmStrCmp(*it)) != cmArrayEnd(valueOptions))
  923. {
  924. assert(existingIt + 1 != opts.end());
  925. *(existingIt + 1) = *(it + 1);
  926. ++it;
  927. }
  928. }
  929. else
  930. {
  931. extraOpts.push_back(*it);
  932. }
  933. }
  934. opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
  935. }
  936. void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
  937. {
  938. std::string _rcc_files;
  939. const char* sepRccFiles = "";
  940. cmMakefile *makefile = target->GetMakefile();
  941. std::vector<cmSourceFile*> srcFiles;
  942. target->GetConfigCommonSourceFiles(srcFiles);
  943. std::string qrcInputs;
  944. const char* qrcInputsSep = "";
  945. std::string rccFileFiles;
  946. std::string rccFileOptions;
  947. const char *optionSep = "";
  948. const char *qtVersion = makefile->GetDefinition("_target_qt_version");
  949. std::vector<std::string> rccOptions;
  950. if (const char* opts = target->GetProperty("AUTORCC_OPTIONS"))
  951. {
  952. cmSystemTools::ExpandListArgument(opts, rccOptions);
  953. }
  954. std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
  955. if (qtMajorVersion == "")
  956. {
  957. qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
  958. }
  959. for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
  960. fileIt != srcFiles.end();
  961. ++fileIt)
  962. {
  963. cmSourceFile* sf = *fileIt;
  964. std::string ext = sf->GetExtension();
  965. if (ext == "qrc")
  966. {
  967. std::string absFile = cmsys::SystemTools::GetRealPath(
  968. sf->GetFullPath());
  969. bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"));
  970. if (!skip)
  971. {
  972. _rcc_files += sepRccFiles;
  973. _rcc_files += absFile;
  974. sepRccFiles = ";";
  975. if (const char *prop = sf->GetProperty("AUTORCC_OPTIONS"))
  976. {
  977. std::vector<std::string> optsVec;
  978. cmSystemTools::ExpandListArgument(prop, optsVec);
  979. this->MergeRccOptions(rccOptions, optsVec,
  980. strcmp(qtVersion, "5") == 0);
  981. }
  982. if (!rccOptions.empty())
  983. {
  984. rccFileFiles += optionSep;
  985. rccFileFiles += absFile;
  986. rccFileOptions += optionSep;
  987. }
  988. const char *listSep = "";
  989. for(std::vector<std::string>::const_iterator it = rccOptions.begin();
  990. it != rccOptions.end();
  991. ++it)
  992. {
  993. rccFileOptions += listSep;
  994. rccFileOptions += *it;
  995. listSep = "@list_sep@";
  996. }
  997. optionSep = ";";
  998. std::vector<std::string> depends;
  999. std::string entriesList;
  1000. if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")))
  1001. {
  1002. if (qtMajorVersion == "5")
  1003. {
  1004. entriesList = this->ListQt5RccInputs(sf, target, depends);
  1005. }
  1006. else
  1007. {
  1008. entriesList = this->ListQt4RccInputs(sf, depends);
  1009. }
  1010. if (entriesList.empty())
  1011. {
  1012. return;
  1013. }
  1014. }
  1015. qrcInputs += qrcInputsSep;
  1016. qrcInputs += entriesList;
  1017. qrcInputsSep = ";";
  1018. }
  1019. }
  1020. }
  1021. makefile->AddDefinition("_qt_rcc_inputs_" + target->GetName(),
  1022. cmLocalGenerator::EscapeForCMake(qrcInputs).c_str());
  1023. makefile->AddDefinition("_rcc_files",
  1024. cmLocalGenerator::EscapeForCMake(_rcc_files).c_str());
  1025. makefile->AddDefinition("_qt_rcc_options_files",
  1026. cmLocalGenerator::EscapeForCMake(rccFileFiles).c_str());
  1027. makefile->AddDefinition("_qt_rcc_options_options",
  1028. cmLocalGenerator::EscapeForCMake(rccFileOptions).c_str());
  1029. makefile->AddDefinition("_qt_rcc_executable",
  1030. this->GetRccExecutable(target).c_str());
  1031. }
  1032. std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target)
  1033. {
  1034. cmMakefile *makefile = target->GetMakefile();
  1035. const char *qtVersion = makefile->GetDefinition("_target_qt_version");
  1036. if (!qtVersion)
  1037. {
  1038. qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR");
  1039. if (!qtVersion)
  1040. {
  1041. qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
  1042. }
  1043. if (const char *targetQtVersion =
  1044. target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
  1045. ""))
  1046. {
  1047. qtVersion = targetQtVersion;
  1048. }
  1049. }
  1050. std::string targetName = target->GetName();
  1051. if (strcmp(qtVersion, "5") == 0)
  1052. {
  1053. cmTarget *qt5Rcc = makefile->FindTargetToUse("Qt5::rcc");
  1054. if (!qt5Rcc)
  1055. {
  1056. cmSystemTools::Error("Qt5::rcc target not found ",
  1057. targetName.c_str());
  1058. return std::string();
  1059. }
  1060. return qt5Rcc->GetLocation("");
  1061. }
  1062. else if (strcmp(qtVersion, "4") == 0)
  1063. {
  1064. cmTarget *qt4Rcc = makefile->FindTargetToUse("Qt4::rcc");
  1065. if (!qt4Rcc)
  1066. {
  1067. cmSystemTools::Error("Qt4::rcc target not found ",
  1068. targetName.c_str());
  1069. return std::string();
  1070. }
  1071. return qt4Rcc->GetLocation("");
  1072. }
  1073. cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and "
  1074. "Qt 5 ", targetName.c_str());
  1075. return std::string();
  1076. }
  1077. static cmGlobalGenerator* CreateGlobalGenerator(cmake* cm,
  1078. const std::string& targetDirectory)
  1079. {
  1080. cmGlobalGenerator* gg = new cmGlobalGenerator();
  1081. gg->SetCMakeInstance(cm);
  1082. cmLocalGenerator* lg = gg->CreateLocalGenerator();
  1083. lg->GetMakefile()->SetHomeOutputDirectory(targetDirectory);
  1084. lg->GetMakefile()->SetStartOutputDirectory(targetDirectory);
  1085. lg->GetMakefile()->SetHomeDirectory(targetDirectory);
  1086. lg->GetMakefile()->SetStartDirectory(targetDirectory);
  1087. gg->SetCurrentLocalGenerator(lg);
  1088. return gg;
  1089. }
  1090. bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
  1091. const std::string& config)
  1092. {
  1093. bool success = true;
  1094. cmake cm;
  1095. cmGlobalGenerator* gg = CreateGlobalGenerator(&cm, targetDirectory);
  1096. cmMakefile* makefile = gg->GetCurrentLocalGenerator()->GetMakefile();
  1097. this->ReadAutogenInfoFile(makefile, targetDirectory, config);
  1098. this->ReadOldMocDefinitionsFile(makefile, targetDirectory);
  1099. this->Init();
  1100. if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5")
  1101. {
  1102. success = this->RunAutogen(makefile);
  1103. }
  1104. this->WriteOldMocDefinitionsFile(targetDirectory);
  1105. delete gg->GetCurrentLocalGenerator();
  1106. delete gg;
  1107. gg = NULL;
  1108. makefile = NULL;
  1109. return success;
  1110. }
  1111. bool cmQtAutoGenerators::ReadAutogenInfoFile(cmMakefile* makefile,
  1112. const std::string& targetDirectory,
  1113. const std::string& config)
  1114. {
  1115. std::string filename(
  1116. cmSystemTools::CollapseFullPath(targetDirectory));
  1117. cmSystemTools::ConvertToUnixSlashes(filename);
  1118. filename += "/AutogenInfo.cmake";
  1119. if (!makefile->ReadListFile(0, filename.c_str()))
  1120. {
  1121. cmSystemTools::Error("Error processing file: ", filename.c_str());
  1122. return false;
  1123. }
  1124. this->QtMajorVersion = makefile->GetSafeDefinition("AM_QT_VERSION_MAJOR");
  1125. if (this->QtMajorVersion == "")
  1126. {
  1127. this->QtMajorVersion = makefile->GetSafeDefinition(
  1128. "AM_Qt5Core_VERSION_MAJOR");
  1129. }
  1130. this->Sources = makefile->GetSafeDefinition("AM_SOURCES");
  1131. {
  1132. std::string rccSources = makefile->GetSafeDefinition("AM_RCC_SOURCES");
  1133. cmSystemTools::ExpandListArgument(rccSources, this->RccSources);
  1134. }
  1135. this->SkipMoc = makefile->GetSafeDefinition("AM_SKIP_MOC");
  1136. this->SkipUic = makefile->GetSafeDefinition("AM_SKIP_UIC");
  1137. this->Headers = makefile->GetSafeDefinition("AM_HEADERS");
  1138. this->IncludeProjectDirsBefore = makefile->IsOn(
  1139. "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
  1140. this->Srcdir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR");
  1141. this->Builddir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR");
  1142. this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE");
  1143. this->UicExecutable = makefile->GetSafeDefinition("AM_QT_UIC_EXECUTABLE");
  1144. this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE");
  1145. {
  1146. std::string compileDefsPropOrig = "AM_MOC_COMPILE_DEFINITIONS";
  1147. std::string compileDefsProp = compileDefsPropOrig;
  1148. if(!config.empty())
  1149. {
  1150. compileDefsProp += "_";
  1151. compileDefsProp += config;
  1152. }
  1153. const char *compileDefs = makefile->GetDefinition(compileDefsProp);
  1154. this->MocCompileDefinitionsStr = compileDefs ? compileDefs
  1155. : makefile->GetSafeDefinition(compileDefsPropOrig);
  1156. }
  1157. {
  1158. std::string includesPropOrig = "AM_MOC_INCLUDES";
  1159. std::string includesProp = includesPropOrig;
  1160. if(!config.empty())
  1161. {
  1162. includesProp += "_";
  1163. includesProp += config;
  1164. }
  1165. const char *includes = makefile->GetDefinition(includesProp);
  1166. this->MocIncludesStr = includes ? includes
  1167. : makefile->GetSafeDefinition(includesPropOrig);
  1168. }
  1169. this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS");
  1170. this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR");
  1171. this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR");
  1172. this->TargetName = makefile->GetSafeDefinition("AM_TARGET_NAME");
  1173. this->OriginTargetName
  1174. = makefile->GetSafeDefinition("AM_ORIGIN_TARGET_NAME");
  1175. {
  1176. const char *uicOptionsFiles
  1177. = makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES");
  1178. std::string uicOptionsPropOrig = "AM_UIC_TARGET_OPTIONS";
  1179. std::string uicOptionsProp = uicOptionsPropOrig;
  1180. if(!config.empty())
  1181. {
  1182. uicOptionsProp += "_";
  1183. uicOptionsProp += config;
  1184. }
  1185. const char *uicTargetOptions
  1186. = makefile->GetSafeDefinition(uicOptionsProp);
  1187. cmSystemTools::ExpandListArgument(
  1188. uicTargetOptions ? uicTargetOptions
  1189. : makefile->GetSafeDefinition(uicOptionsPropOrig),
  1190. this->UicTargetOptions);
  1191. const char *uicOptionsOptions
  1192. = makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS");
  1193. std::vector<std::string> uicFilesVec;
  1194. cmSystemTools::ExpandListArgument(uicOptionsFiles, uicFilesVec);
  1195. std::vector<std::string> uicOptionsVec;
  1196. cmSystemTools::ExpandListArgument(uicOptionsOptions, uicOptionsVec);
  1197. if (uicFilesVec.size() != uicOptionsVec.size())
  1198. {
  1199. return false;
  1200. }
  1201. for (std::vector<std::string>::iterator fileIt = uicFilesVec.begin(),
  1202. optionIt = uicOptionsVec.begin();
  1203. fileIt != uicFilesVec.end();
  1204. ++fileIt, ++optionIt)
  1205. {
  1206. cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
  1207. this->UicOptions[*fileIt] = *optionIt;
  1208. }
  1209. }
  1210. {
  1211. const char *rccOptionsFiles
  1212. = makefile->GetSafeDefinition("AM_RCC_OPTIONS_FILES");
  1213. const char *rccOptionsOptions
  1214. = makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS");
  1215. std::vector<std::string> rccFilesVec;
  1216. cmSystemTools::ExpandListArgument(rccOptionsFiles, rccFilesVec);
  1217. std::vector<std::string> rccOptionsVec;
  1218. cmSystemTools::ExpandListArgument(rccOptionsOptions, rccOptionsVec);
  1219. if (rccFilesVec.size() != rccOptionsVec.size())
  1220. {
  1221. return false;
  1222. }
  1223. for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(),
  1224. optionIt = rccOptionsVec.begin();
  1225. fileIt != rccFilesVec.end();
  1226. ++fileIt, ++optionIt)
  1227. {
  1228. cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
  1229. this->RccOptions[*fileIt] = *optionIt;
  1230. }
  1231. const char *rccInputs = makefile->GetSafeDefinition("AM_RCC_INPUTS");
  1232. std::vector<std::string> rccInputLists;
  1233. cmSystemTools::ExpandListArgument(rccInputs, rccInputLists);
  1234. if (this->RccSources.size() != rccInputLists.size())
  1235. {
  1236. cmSystemTools::Error("Error processing file: ", filename.c_str());
  1237. return false;
  1238. }
  1239. for (std::vector<std::string>::iterator fileIt = this->RccSources.begin(),
  1240. inputIt = rccInputLists.begin();
  1241. fileIt != this->RccSources.end();
  1242. ++fileIt, ++inputIt)
  1243. {
  1244. cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";");
  1245. std::vector<std::string> rccInputFiles;
  1246. cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
  1247. this->RccInputs[*fileIt] = rccInputFiles;
  1248. }
  1249. }
  1250. this->CurrentCompileSettingsStr = this->MakeCompileSettingsString(makefile);
  1251. this->RelaxedMode = makefile->IsOn("AM_RELAXED_MODE");
  1252. return true;
  1253. }
  1254. std::string cmQtAutoGenerators::MakeCompileSettingsString(cmMakefile* makefile)
  1255. {
  1256. std::string s;
  1257. s += makefile->GetSafeDefinition("AM_MOC_COMPILE_DEFINITIONS");
  1258. s += " ~~~ ";
  1259. s += makefile->GetSafeDefinition("AM_MOC_INCLUDES");
  1260. s += " ~~~ ";
  1261. s += makefile->GetSafeDefinition("AM_MOC_OPTIONS");
  1262. s += " ~~~ ";
  1263. s += makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE") ? "TRUE"
  1264. : "FALSE";
  1265. s += " ~~~ ";
  1266. return s;
  1267. }
  1268. bool cmQtAutoGenerators::ReadOldMocDefinitionsFile(cmMakefile* makefile,
  1269. const std::string& targetDirectory)
  1270. {
  1271. std::string filename(
  1272. cmSystemTools::CollapseFullPath(targetDirectory));
  1273. cmSystemTools::ConvertToUnixSlashes(filename);
  1274. filename += "/AutomocOldMocDefinitions.cmake";
  1275. if (makefile->ReadListFile(0, filename.c_str()))
  1276. {
  1277. this->OldCompileSettingsStr =
  1278. makefile->GetSafeDefinition("AM_OLD_COMPILE_SETTINGS");
  1279. }
  1280. return true;
  1281. }
  1282. void
  1283. cmQtAutoGenerators::WriteOldMocDefinitionsFile(
  1284. const std::string& targetDirectory)
  1285. {
  1286. std::string filename(
  1287. cmSystemTools::CollapseFullPath(targetDirectory));
  1288. cmSystemTools::ConvertToUnixSlashes(filename);
  1289. filename += "/AutomocOldMocDefinitions.cmake";
  1290. cmsys::ofstream outfile;
  1291. outfile.open(filename.c_str(),
  1292. std::ios::trunc);
  1293. outfile << "set(AM_OLD_COMPILE_SETTINGS "
  1294. << cmLocalGenerator::EscapeForCMake(
  1295. this->CurrentCompileSettingsStr) << ")\n";
  1296. outfile.close();
  1297. }
  1298. void cmQtAutoGenerators::Init()
  1299. {
  1300. this->OutMocCppFilename = this->Builddir;
  1301. this->OutMocCppFilename += this->TargetName;
  1302. this->OutMocCppFilename += ".cpp";
  1303. std::vector<std::string> cdefList;
  1304. cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
  1305. for(std::vector<std::string>::const_iterator it = cdefList.begin();
  1306. it != cdefList.end();
  1307. ++it)
  1308. {
  1309. this->MocDefinitions.push_back("-D" + (*it));
  1310. }
  1311. cmSystemTools::ExpandListArgument(this->MocOptionsStr, this->MocOptions);
  1312. std::vector<std::string> incPaths;
  1313. cmSystemTools::ExpandListArgument(this->MocIncludesStr, incPaths);
  1314. std::set<std::string> frameworkPaths;
  1315. for(std::vector<std::string>::const_iterator it = incPaths.begin();
  1316. it != incPaths.end();
  1317. ++it)
  1318. {
  1319. const std::string &path = *it;
  1320. this->MocIncludes.push_back("-I" + path);
  1321. if (this->EndsWith(path, ".framework/Headers"))
  1322. {
  1323. // Go up twice to get to the framework root
  1324. std::vector<std::string> pathComponents;
  1325. cmsys::SystemTools::SplitPath(path, pathComponents);
  1326. std::string frameworkPath =cmsys::SystemTools::JoinPath(
  1327. pathComponents.begin(), pathComponents.end() - 2);
  1328. frameworkPaths.insert(frameworkPath);
  1329. }
  1330. }
  1331. for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
  1332. it != frameworkPaths.end(); ++it)
  1333. {
  1334. this->MocIncludes.push_back("-F");
  1335. this->MocIncludes.push_back(*it);
  1336. }
  1337. if (this->IncludeProjectDirsBefore)
  1338. {
  1339. const std::string &binDir = "-I" + this->ProjectBinaryDir;
  1340. const std::string srcDir = "-I" + this->ProjectSourceDir;
  1341. std::list<std::string> sortedMocIncludes;
  1342. std::list<std::string>::iterator it = this->MocIncludes.begin();
  1343. while (it != this->MocIncludes.end())
  1344. {
  1345. if (this->StartsWith(*it, binDir))
  1346. {
  1347. sortedMocIncludes.push_back(*it);
  1348. it = this->MocIncludes.erase(it);
  1349. }
  1350. else
  1351. {
  1352. ++it;
  1353. }
  1354. }
  1355. it = this->MocIncludes.begin();
  1356. while (it != this->MocIncludes.end())
  1357. {
  1358. if (this->StartsWith(*it, srcDir))
  1359. {
  1360. sortedMocIncludes.push_back(*it);
  1361. it = this->MocIncludes.erase(it);
  1362. }
  1363. else
  1364. {
  1365. ++it;
  1366. }
  1367. }
  1368. sortedMocIncludes.insert(sortedMocIncludes.end(),
  1369. this->MocIncludes.begin(), this->MocIncludes.end());
  1370. this->MocIncludes = sortedMocIncludes;
  1371. }
  1372. }
  1373. bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
  1374. {
  1375. if (!cmsys::SystemTools::FileExists(this->OutMocCppFilename.c_str())
  1376. || (this->OldCompileSettingsStr != this->CurrentCompileSettingsStr))
  1377. {
  1378. this->GenerateAll = true;
  1379. }
  1380. // the program goes through all .cpp files to see which moc files are
  1381. // included. It is not really interesting how the moc file is named, but
  1382. // what file the moc is created from. Once a moc is included the same moc
  1383. // may not be included in the _automoc.cpp file anymore. OTOH if there's a
  1384. // header containing Q_OBJECT where no corresponding moc file is included
  1385. // anywhere a moc_<filename>.cpp file is created and included in
  1386. // the _automoc.cpp file.
  1387. // key = moc source filepath, value = moc output filepath
  1388. std::map<std::string, std::string> includedMocs;
  1389. // collect all headers which may need to be mocced
  1390. std::set<std::string> headerFiles;
  1391. std::vector<std::string> sourceFiles;
  1392. cmSystemTools::ExpandListArgument(this->Sources, sourceFiles);
  1393. const std::vector<std::string>& headerExtensions =
  1394. makefile->GetHeaderExtensions();
  1395. std::map<std::string, std::vector<std::string> > includedUis;
  1396. std::map<std::string, std::vector<std::string> > skippedUis;
  1397. std::vector<std::string> uicSkipped;
  1398. cmSystemTools::ExpandListArgument(this->SkipUic, uicSkipped);
  1399. for (std::vector<std::string>::const_iterator it = sourceFiles.begin();
  1400. it != sourceFiles.end();
  1401. ++it)
  1402. {
  1403. const bool skipUic = std::find(uicSkipped.begin(), uicSkipped.end(), *it)
  1404. != uicSkipped.end();
  1405. std::map<std::string, std::vector<std::string> >& uiFiles
  1406. = skipUic ? skippedUis : includedUis;
  1407. const std::string &absFilename = *it;
  1408. if (this->Verbose)
  1409. {
  1410. std::cout << "AUTOGEN: Checking " << absFilename << std::endl;
  1411. }
  1412. if (this->RelaxedMode)
  1413. {
  1414. this->ParseCppFile(absFilename, headerExtensions, includedMocs,
  1415. uiFiles);
  1416. }
  1417. else
  1418. {
  1419. this->StrictParseCppFile(absFilename, headerExtensions, includedMocs,
  1420. uiFiles);
  1421. }
  1422. this->SearchHeadersForCppFile(absFilename, headerExtensions, headerFiles);
  1423. }
  1424. {
  1425. std::vector<std::string> mocSkipped;
  1426. cmSystemTools::ExpandListArgument(this->SkipMoc, mocSkipped);
  1427. for (std::vector<std::string>::const_iterator it = mocSkipped.begin();
  1428. it != mocSkipped.end();
  1429. ++it)
  1430. {
  1431. if (std::find(uicSkipped.begin(), uicSkipped.end(), *it)
  1432. != uicSkipped.end())
  1433. {
  1434. const std::string &absFilename = *it;
  1435. if (this->Verbose)
  1436. {
  1437. std::cout << "AUTOGEN: Checking " << absFilename << std::endl;
  1438. }
  1439. this->ParseForUic(absFilename, includedUis);
  1440. }
  1441. }
  1442. }
  1443. std::vector<std::string> headerFilesVec;
  1444. cmSystemTools::ExpandListArgument(this->Headers, headerFilesVec);
  1445. for (std::vector<std::string>::const_iterator it = headerFilesVec.begin();
  1446. it != headerFilesVec.end();
  1447. ++it)
  1448. {
  1449. headerFiles.insert(*it);
  1450. }
  1451. // key = moc source filepath, value = moc output filename
  1452. std::map<std::string, std::string> notIncludedMocs;
  1453. this->ParseHeaders(headerFiles, includedMocs, notIncludedMocs, includedUis);
  1454. // run moc on all the moc's that are #included in source files
  1455. for(std::map<std::string, std::string>::const_iterator
  1456. it = includedMocs.begin();
  1457. it != includedMocs.end();
  1458. ++it)
  1459. {
  1460. this->GenerateMoc(it->first, it->second);
  1461. }
  1462. for(std::map<std::string, std::vector<std::string> >::const_iterator
  1463. it = includedUis.begin();
  1464. it != includedUis.end();
  1465. ++it)
  1466. {
  1467. for (std::vector<std::string>::const_iterator nit = it->second.begin();
  1468. nit != it->second.end();
  1469. ++nit)
  1470. {
  1471. this->GenerateUi(it->first, *nit);
  1472. }
  1473. }
  1474. if(!this->RccExecutable.empty())
  1475. {
  1476. this->GenerateQrc();
  1477. }
  1478. cmsys_ios::stringstream outStream;
  1479. outStream << "/* This file is autogenerated, do not edit*/\n";
  1480. bool automocCppChanged = false;
  1481. if (notIncludedMocs.empty())
  1482. {
  1483. outStream << "enum some_compilers { need_more_than_nothing };\n";
  1484. }
  1485. else
  1486. {
  1487. // run moc on the remaining headers and include them in
  1488. // the _automoc.cpp file
  1489. for(std::map<std::string, std::string>::const_iterator
  1490. it = notIncludedMocs.begin();
  1491. it != notIncludedMocs.end();
  1492. ++it)
  1493. {
  1494. bool mocSuccess = this->GenerateMoc(it->first, it->second);
  1495. if (mocSuccess)
  1496. {
  1497. automocCppChanged = true;
  1498. }
  1499. outStream << "#include \"" << it->second << "\"\n";
  1500. }
  1501. }
  1502. if (this->RunMocFailed)
  1503. {
  1504. std::cerr << "moc failed..." << std::endl;
  1505. return false;
  1506. }
  1507. if (this->RunUicFailed)
  1508. {
  1509. std::cerr << "uic failed..." << std::endl;
  1510. return false;
  1511. }
  1512. if (this->RunRccFailed)
  1513. {
  1514. std::cerr << "rcc failed..." << std::endl;
  1515. return false;
  1516. }
  1517. outStream.flush();
  1518. std::string automocSource = outStream.str();
  1519. if (!automocCppChanged)
  1520. {
  1521. // compare contents of the _automoc.cpp file
  1522. const std::string oldContents = ReadAll(this->OutMocCppFilename);
  1523. if (oldContents == automocSource)
  1524. {
  1525. // nothing changed: don't touch the _automoc.cpp file
  1526. return true;
  1527. }
  1528. }
  1529. // source file that includes all remaining moc files (_automoc.cpp file)
  1530. cmsys::ofstream outfile;
  1531. outfile.open(this->OutMocCppFilename.c_str(),
  1532. std::ios::trunc);
  1533. outfile << automocSource;
  1534. outfile.close();
  1535. return true;
  1536. }
  1537. void cmQtAutoGenerators::ParseCppFile(const std::string& absFilename,
  1538. const std::vector<std::string>& headerExtensions,
  1539. std::map<std::string, std::string>& includedMocs,
  1540. std::map<std::string, std::vector<std::string> > &includedUis)
  1541. {
  1542. cmsys::RegularExpression mocIncludeRegExp(
  1543. "[\n][ \t]*#[ \t]*include[ \t]+"
  1544. "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
  1545. const std::string contentsString = ReadAll(absFilename);
  1546. if (contentsString.empty())
  1547. {
  1548. std::cerr << "AUTOGEN: warning: " << absFilename << ": file is empty\n"
  1549. << std::endl;
  1550. return;
  1551. }
  1552. this->ParseForUic(absFilename, contentsString, includedUis);
  1553. if (this->MocExecutable.empty())
  1554. {
  1555. return;
  1556. }
  1557. const std::string absPath = cmsys::SystemTools::GetFilenamePath(
  1558. cmsys::SystemTools::GetRealPath(absFilename)) + '/';
  1559. const std::string scannedFileBasename = cmsys::SystemTools::
  1560. GetFilenameWithoutLastExtension(absFilename);
  1561. std::string macroName;
  1562. const bool requiresMoc = requiresMocing(contentsString, macroName);
  1563. bool dotMocIncluded = false;
  1564. bool mocUnderscoreIncluded = false;
  1565. std::string ownMocUnderscoreFile;
  1566. std::string ownDotMocFile;
  1567. std::string ownMocHeaderFile;
  1568. std::string::size_type matchOffset = 0;
  1569. // first a simple string check for "moc" is *much* faster than the regexp,
  1570. // and if the string search already fails, we don't have to try the
  1571. // expensive regexp
  1572. if ((strstr(contentsString.c_str(), "moc") != NULL)
  1573. && (mocIncludeRegExp.find(contentsString)))
  1574. {
  1575. // for every moc include in the file
  1576. do
  1577. {
  1578. const std::string currentMoc = mocIncludeRegExp.match(1);
  1579. //std::cout << "found moc include: " << currentMoc << std::endl;
  1580. std::string basename = cmsys::SystemTools::
  1581. GetFilenameWithoutLastExtension(currentMoc);
  1582. const bool moc_style = this->StartsWith(basename, "moc_");
  1583. // If the moc include is of the moc_foo.cpp style we expect
  1584. // the Q_OBJECT class declaration in a header file.
  1585. // If the moc include is of the foo.moc style we need to look for
  1586. // a Q_OBJECT macro in the current source file, if it contains the
  1587. // macro we generate the moc file from the source file.
  1588. // Q_OBJECT
  1589. if (moc_style)
  1590. {
  1591. // basename should be the part of the moc filename used for
  1592. // finding the correct header, so we need to remove the moc_ part
  1593. basename = basename.substr(4);
  1594. std::string mocSubDir = extractSubDir(absPath, currentMoc);
  1595. std::string headerToMoc = findMatchingHeader(
  1596. absPath, mocSubDir, basename, headerExtensions);
  1597. if (!headerToMoc.empty())
  1598. {
  1599. includedMocs[headerToMoc] = currentMoc;
  1600. if (basename == scannedFileBasename)
  1601. {
  1602. mocUnderscoreIncluded = true;
  1603. ownMocUnderscoreFile = currentMoc;
  1604. ownMocHeaderFile = headerToMoc;
  1605. }
  1606. }
  1607. else
  1608. {
  1609. std::cerr << "AUTOGEN: error: " << absFilename << ": The file "
  1610. << "includes the moc file \"" << currentMoc << "\", "
  1611. << "but could not find header \"" << basename
  1612. << '{' << this->Join(headerExtensions, ',') << "}\" ";
  1613. if (mocSubDir.empty())
  1614. {
  1615. std::cerr << "in " << absPath << "\n" << std::endl;
  1616. }
  1617. else
  1618. {
  1619. std::cerr << "neither in " << absPath
  1620. << " nor in " << mocSubDir << "\n" << std::endl;
  1621. }
  1622. ::exit(EXIT_FAILURE);
  1623. }
  1624. }
  1625. else
  1626. {
  1627. std::string fileToMoc = absFilename;
  1628. if ((basename != scannedFileBasename) || (requiresMoc==false))
  1629. {
  1630. std::string mocSubDir = extractSubDir(absPath, currentMoc);
  1631. std::string headerToMoc = findMatchingHeader(
  1632. absPath, mocSubDir, basename, headerExtensions);
  1633. if (!headerToMoc.empty())
  1634. {
  1635. // this is for KDE4 compatibility:
  1636. fileToMoc = headerToMoc;
  1637. if ((requiresMoc==false) &&(basename==scannedFileBasename))
  1638. {
  1639. std::cerr << "AUTOGEN: warning: " << absFilename << ": The file "
  1640. "includes the moc file \"" << currentMoc <<
  1641. "\", but does not contain a " << macroName
  1642. << " macro. Running moc on "
  1643. << "\"" << headerToMoc << "\" ! Include \"moc_"
  1644. << basename << ".cpp\" for a compatiblity with "
  1645. "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
  1646. << std::endl;
  1647. }
  1648. else
  1649. {
  1650. std::cerr << "AUTOGEN: warning: " << absFilename << ": The file "
  1651. "includes the moc file \"" << currentMoc <<
  1652. "\" instead of \"moc_" << basename << ".cpp\". "
  1653. "Running moc on "
  1654. << "\"" << headerToMoc << "\" ! Include \"moc_"
  1655. << basename << ".cpp\" for compatiblity with "
  1656. "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
  1657. << std::endl;
  1658. }
  1659. }
  1660. else
  1661. {
  1662. std::cerr <<"AUTOGEN: error: " << absFilename << ": The file "
  1663. "includes the moc file \"" << currentMoc <<
  1664. "\", which seems to be the moc file from a different "
  1665. "source file. CMake also could not find a matching "
  1666. "header.\n" << std::endl;
  1667. ::exit(EXIT_FAILURE);
  1668. }
  1669. }
  1670. else
  1671. {
  1672. dotMocIncluded = true;
  1673. ownDotMocFile = currentMoc;
  1674. }
  1675. includedMocs[fileToMoc] = currentMoc;
  1676. }
  1677. matchOffset += mocIncludeRegExp.end();
  1678. } while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
  1679. }
  1680. // In this case, check whether the scanned file itself contains a Q_OBJECT.
  1681. // If this is the case, the moc_foo.cpp should probably be generated from
  1682. // foo.cpp instead of foo.h, because otherwise it won't build.
  1683. // But warn, since this is not how it is supposed to be used.
  1684. if ((dotMocIncluded == false) && (requiresMoc == true))
  1685. {
  1686. if (mocUnderscoreIncluded == true)
  1687. {
  1688. // this is for KDE4 compatibility:
  1689. std::cerr << "AUTOGEN: warning: " << absFilename << ": The file "
  1690. << "contains a " << macroName << " macro, but does not "
  1691. "include "
  1692. << "\"" << scannedFileBasename << ".moc\", but instead "
  1693. "includes "
  1694. << "\"" << ownMocUnderscoreFile << "\". Running moc on "
  1695. << "\"" << absFilename << "\" ! Better include \""
  1696. << scannedFileBasename << ".moc\" for compatiblity with "
  1697. "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
  1698. << std::endl;
  1699. includedMocs[absFilename] = ownMocUnderscoreFile;
  1700. includedMocs.erase(ownMocHeaderFile);
  1701. }
  1702. else
  1703. {
  1704. // otherwise always error out since it will not compile:
  1705. std::cerr << "AUTOGEN: error: " << absFilename << ": The file "
  1706. << "contains a " << macroName << " macro, but does not "
  1707. "include "
  1708. << "\"" << scannedFileBasename << ".moc\" !\n"
  1709. << std::endl;
  1710. ::exit(EXIT_FAILURE);
  1711. }
  1712. }
  1713. }
  1714. void cmQtAutoGenerators::StrictParseCppFile(const std::string& absFilename,
  1715. const std::vector<std::string>& headerExtensions,
  1716. std::map<std::string, std::string>& includedMocs,
  1717. std::map<std::string, std::vector<std::string> >& includedUis)
  1718. {
  1719. cmsys::RegularExpression mocIncludeRegExp(
  1720. "[\n][ \t]*#[ \t]*include[ \t]+"
  1721. "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
  1722. const std::string contentsString = ReadAll(absFilename);
  1723. if (contentsString.empty())
  1724. {
  1725. std::cerr << "AUTOGEN: warning: " << absFilename << ": file is empty\n"
  1726. << std::endl;
  1727. return;
  1728. }
  1729. this->ParseForUic(absFilename, contentsString, includedUis);
  1730. if (this->MocExecutable.empty())
  1731. {
  1732. return;
  1733. }
  1734. const std::string absPath = cmsys::SystemTools::GetFilenamePath(
  1735. cmsys::SystemTools::GetRealPath(absFilename)) + '/';
  1736. const std::string scannedFileBasename = cmsys::SystemTools::
  1737. GetFilenameWithoutLastExtension(absFilename);
  1738. bool dotMocIncluded = false;
  1739. std::string::size_type matchOffset = 0;
  1740. // first a simple string check for "moc" is *much* faster than the regexp,
  1741. // and if the string search already fails, we don't have to try the
  1742. // expensive regexp
  1743. if ((strstr(contentsString.c_str(), "moc") != NULL)
  1744. && (mocIncludeRegExp.find(contentsString)))
  1745. {
  1746. // for every moc include in the file
  1747. do
  1748. {
  1749. const std::string currentMoc = mocIncludeRegExp.match(1);
  1750. std::string basename = cmsys::SystemTools::
  1751. GetFilenameWithoutLastExtension(currentMoc);
  1752. const bool mocUnderscoreStyle = this->StartsWith(basename, "moc_");
  1753. // If the moc include is of the moc_foo.cpp style we expect
  1754. // the Q_OBJECT class declaration in a header file.
  1755. // If the moc include is of the foo.moc style we need to look for
  1756. // a Q_OBJECT macro in the current source file, if it contains the
  1757. // macro we generate the moc file from the source file.
  1758. if (mocUnderscoreStyle)
  1759. {
  1760. // basename should be the part of the moc filename used for
  1761. // finding the correct header, so we need to remove the moc_ part
  1762. basename = basename.substr(4);
  1763. std::string mocSubDir = extractSubDir(absPath, currentMoc);
  1764. std::string headerToMoc = findMatchingHeader(
  1765. absPath, mocSubDir, basename, headerExtensions);
  1766. if (!headerToMoc.empty())
  1767. {
  1768. includedMocs[headerToMoc] = currentMoc;
  1769. }
  1770. else
  1771. {
  1772. std::cerr << "AUTOGEN: error: " << absFilename << " The file "
  1773. << "includes the moc file \"" << currentMoc << "\", "
  1774. << "but could not find header \"" << basename
  1775. << '{' << this->Join(headerExtensions, ',') << "}\" ";
  1776. if (mocSubDir.empty())
  1777. {
  1778. std::cerr << "in " << absPath << "\n" << std::endl;
  1779. }
  1780. else
  1781. {
  1782. std::cerr << "neither in " << absPath
  1783. << " nor in " << mocSubDir << "\n" << std::endl;
  1784. }
  1785. ::exit(EXIT_FAILURE);
  1786. }
  1787. }
  1788. else
  1789. {
  1790. if (basename != scannedFileBasename)
  1791. {
  1792. std::cerr <<"AUTOGEN: error: " << absFilename << ": The file "
  1793. "includes the moc file \"" << currentMoc <<
  1794. "\", which seems to be the moc file from a different "
  1795. "source file. This is not supported. "
  1796. "Include \"" << scannedFileBasename << ".moc\" to run "
  1797. "moc on this source file.\n" << std::endl;
  1798. ::exit(EXIT_FAILURE);
  1799. }
  1800. dotMocIncluded = true;
  1801. includedMocs[absFilename] = currentMoc;
  1802. }
  1803. matchOffset += mocIncludeRegExp.end();
  1804. } while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
  1805. }
  1806. // In this case, check whether the scanned file itself contains a Q_OBJECT.
  1807. // If this is the case, the moc_foo.cpp should probably be generated from
  1808. // foo.cpp instead of foo.h, because otherwise it won't build.
  1809. // But warn, since this is not how it is supposed to be used.
  1810. std::string macroName;
  1811. if ((dotMocIncluded == false) && (requiresMocing(contentsString,
  1812. macroName)))
  1813. {
  1814. // otherwise always error out since it will not compile:
  1815. std::cerr << "AUTOGEN: error: " << absFilename << ": The file "
  1816. << "contains a " << macroName << " macro, but does not include "
  1817. << "\"" << scannedFileBasename << ".moc\" !\n"
  1818. << std::endl;
  1819. ::exit(EXIT_FAILURE);
  1820. }
  1821. }
  1822. void cmQtAutoGenerators::ParseForUic(const std::string& absFilename,
  1823. std::map<std::string, std::vector<std::string> >& includedUis)
  1824. {
  1825. if (this->UicExecutable.empty())
  1826. {
  1827. return;
  1828. }
  1829. const std::string contentsString = ReadAll(absFilename);
  1830. if (contentsString.empty())
  1831. {
  1832. std::cerr << "AUTOGEN: warning: " << absFilename << ": file is empty\n"
  1833. << std::endl;
  1834. return;
  1835. }
  1836. this->ParseForUic(absFilename, contentsString, includedUis);
  1837. }
  1838. void cmQtAutoGenerators::ParseForUic(const std::string& absFilename,
  1839. const std::string& contentsString,
  1840. std::map<std::string, std::vector<std::string> >& includedUis)
  1841. {
  1842. if (this->UicExecutable.empty())
  1843. {
  1844. return;
  1845. }
  1846. cmsys::RegularExpression uiIncludeRegExp(
  1847. "[\n][ \t]*#[ \t]*include[ \t]+"
  1848. "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
  1849. std::string::size_type matchOffset = 0;
  1850. const std::string realName =
  1851. cmsys::SystemTools::GetRealPath(absFilename);
  1852. matchOffset = 0;
  1853. if ((strstr(contentsString.c_str(), "ui_") != NULL)
  1854. && (uiIncludeRegExp.find(contentsString)))
  1855. {
  1856. do
  1857. {
  1858. const std::string currentUi = uiIncludeRegExp.match(1);
  1859. std::string basename = cmsys::SystemTools::
  1860. GetFilenameWithoutLastExtension(currentUi);
  1861. // basename should be the part of the ui filename used for
  1862. // finding the correct header, so we need to remove the ui_ part
  1863. basename = basename.substr(3);
  1864. includedUis[realName].push_back(basename);
  1865. matchOffset += uiIncludeRegExp.end();
  1866. } while(uiIncludeRegExp.find(contentsString.c_str() + matchOffset));
  1867. }
  1868. }
  1869. void
  1870. cmQtAutoGenerators::SearchHeadersForCppFile(const std::string& absFilename,
  1871. const std::vector<std::string>& headerExtensions,
  1872. std::set<std::string>& absHeaders)
  1873. {
  1874. // search for header files and private header files we may need to moc:
  1875. const std::string basename =
  1876. cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
  1877. const std::string absPath = cmsys::SystemTools::GetFilenamePath(
  1878. cmsys::SystemTools::GetRealPath(absFilename)) + '/';
  1879. for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
  1880. ext != headerExtensions.end();
  1881. ++ext)
  1882. {
  1883. const std::string headerName = absPath + basename + "." + (*ext);
  1884. if (cmsys::SystemTools::FileExists(headerName.c_str()))
  1885. {
  1886. absHeaders.insert(headerName);
  1887. break;
  1888. }
  1889. }
  1890. for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
  1891. ext != headerExtensions.end();
  1892. ++ext)
  1893. {
  1894. const std::string privateHeaderName = absPath+basename+"_p."+(*ext);
  1895. if (cmsys::SystemTools::FileExists(privateHeaderName.c_str()))
  1896. {
  1897. absHeaders.insert(privateHeaderName);
  1898. break;
  1899. }
  1900. }
  1901. }
  1902. void cmQtAutoGenerators::ParseHeaders(const std::set<std::string>& absHeaders,
  1903. const std::map<std::string, std::string>& includedMocs,
  1904. std::map<std::string, std::string>& notIncludedMocs,
  1905. std::map<std::string, std::vector<std::string> >& includedUis)
  1906. {
  1907. for(std::set<std::string>::const_iterator hIt=absHeaders.begin();
  1908. hIt!=absHeaders.end();
  1909. ++hIt)
  1910. {
  1911. const std::string& headerName = *hIt;
  1912. const std::string contents = ReadAll(headerName);
  1913. if (!this->MocExecutable.empty()
  1914. && includedMocs.find(headerName) == includedMocs.end())
  1915. {
  1916. if (this->Verbose)
  1917. {
  1918. std::cout << "AUTOGEN: Checking " << headerName << std::endl;
  1919. }
  1920. const std::string basename = cmsys::SystemTools::
  1921. GetFilenameWithoutLastExtension(headerName);
  1922. const std::string currentMoc = "moc_" + basename + ".cpp";
  1923. std::string macroName;
  1924. if (requiresMocing(contents, macroName))
  1925. {
  1926. //std::cout << "header contains Q_OBJECT macro";
  1927. notIncludedMocs[headerName] = currentMoc;
  1928. }
  1929. }
  1930. this->ParseForUic(headerName, contents, includedUis);
  1931. }
  1932. }
  1933. bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile,
  1934. const std::string& mocFileName)
  1935. {
  1936. const std::string mocFilePath = this->Builddir + mocFileName;
  1937. int sourceNewerThanMoc = 0;
  1938. bool success = cmsys::SystemTools::FileTimeCompare(sourceFile,
  1939. mocFilePath,
  1940. &sourceNewerThanMoc);
  1941. if (this->GenerateAll || !success || sourceNewerThanMoc >= 0)
  1942. {
  1943. // make sure the directory for the resulting moc file exists
  1944. std::string mocDir = mocFilePath.substr(0, mocFilePath.rfind('/'));
  1945. if (!cmsys::SystemTools::FileExists(mocDir.c_str(), false))
  1946. {
  1947. cmsys::SystemTools::MakeDirectory(mocDir.c_str());
  1948. }
  1949. std::string msg = "Generating ";
  1950. msg += mocFileName;
  1951. cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue
  1952. |cmsysTerminal_Color_ForegroundBold,
  1953. msg.c_str(), true, this->ColorOutput);
  1954. std::vector<std::string> command;
  1955. command.push_back(this->MocExecutable);
  1956. for (std::list<std::string>::const_iterator it = this->MocIncludes.begin();
  1957. it != this->MocIncludes.end();
  1958. ++it)
  1959. {
  1960. command.push_back(*it);
  1961. }
  1962. for(std::list<std::string>::const_iterator it=this->MocDefinitions.begin();
  1963. it != this->MocDefinitions.end();
  1964. ++it)
  1965. {
  1966. command.push_back(*it);
  1967. }
  1968. for(std::vector<std::string>::const_iterator it=this->MocOptions.begin();
  1969. it != this->MocOptions.end();
  1970. ++it)
  1971. {
  1972. command.push_back(*it);
  1973. }
  1974. #ifdef _WIN32
  1975. command.push_back("-DWIN32");
  1976. #endif
  1977. command.push_back("-o");
  1978. command.push_back(mocFilePath);
  1979. command.push_back(sourceFile);
  1980. if (this->Verbose)
  1981. {
  1982. for(std::vector<std::string>::const_iterator cmdIt = command.begin();
  1983. cmdIt != command.end();
  1984. ++cmdIt)
  1985. {
  1986. std::cout << *cmdIt << " ";
  1987. }
  1988. std::cout << std::endl;
  1989. }
  1990. std::string output;
  1991. int retVal = 0;
  1992. bool result = cmSystemTools::RunSingleCommand(command, &output, &retVal);
  1993. if (!result || retVal)
  1994. {
  1995. std::cerr << "AUTOGEN: error: process for " << mocFilePath <<" failed:\n"
  1996. << output << std::endl;
  1997. this->RunMocFailed = true;
  1998. cmSystemTools::RemoveFile(mocFilePath);
  1999. }
  2000. return true;
  2001. }
  2002. return false;
  2003. }
  2004. bool cmQtAutoGenerators::GenerateUi(const std::string& realName,
  2005. const std::string& uiFileName)
  2006. {
  2007. if (!cmsys::SystemTools::FileExists(this->Builddir.c_str(), false))
  2008. {
  2009. cmsys::SystemTools::MakeDirectory(this->Builddir.c_str());
  2010. }
  2011. const std::string path = cmsys::SystemTools::GetFilenamePath(
  2012. realName) + '/';
  2013. std::string ui_output_file = "ui_" + uiFileName + ".h";
  2014. std::string ui_input_file = path + uiFileName + ".ui";
  2015. int sourceNewerThanUi = 0;
  2016. bool success = cmsys::SystemTools::FileTimeCompare(ui_input_file,
  2017. this->Builddir + ui_output_file,
  2018. &sourceNewerThanUi);
  2019. if (this->GenerateAll || !success || sourceNewerThanUi >= 0)
  2020. {
  2021. std::string msg = "Generating ";
  2022. msg += ui_output_file;
  2023. cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue
  2024. |cmsysTerminal_Color_ForegroundBold,
  2025. msg.c_str(), true, this->ColorOutput);
  2026. std::vector<std::string> command;
  2027. command.push_back(this->UicExecutable);
  2028. std::vector<std::string> opts = this->UicTargetOptions;
  2029. std::map<std::string, std::string>::const_iterator optionIt
  2030. = this->UicOptions.find(ui_input_file);
  2031. if (optionIt != this->UicOptions.end())
  2032. {
  2033. std::vector<std::string> fileOpts;
  2034. cmSystemTools::ExpandListArgument(optionIt->second, fileOpts);
  2035. this->MergeUicOptions(opts, fileOpts, this->QtMajorVersion == "5");
  2036. }
  2037. for(std::vector<std::string>::const_iterator optIt = opts.begin();
  2038. optIt != opts.end();
  2039. ++optIt)
  2040. {
  2041. command.push_back(*optIt);
  2042. }
  2043. command.push_back("-o");
  2044. command.push_back(this->Builddir + ui_output_file);
  2045. command.push_back(ui_input_file);
  2046. if (this->Verbose)
  2047. {
  2048. for(std::vector<std::string>::const_iterator cmdIt = command.begin();
  2049. cmdIt != command.end();
  2050. ++cmdIt)
  2051. {
  2052. std::cout << *cmdIt << " ";
  2053. }
  2054. std::cout << std::endl;
  2055. }
  2056. std::string output;
  2057. int retVal = 0;
  2058. bool result = cmSystemTools::RunSingleCommand(command, &output, &retVal);
  2059. if (!result || retVal)
  2060. {
  2061. std::cerr << "AUTOUIC: error: process for " << ui_output_file <<
  2062. " failed:\n" << output << std::endl;
  2063. this->RunUicFailed = true;
  2064. cmSystemTools::RemoveFile(ui_output_file);
  2065. return false;
  2066. }
  2067. return true;
  2068. }
  2069. return false;
  2070. }
  2071. bool cmQtAutoGenerators::InputFilesNewerThanQrc(const std::string& qrcFile,
  2072. const std::string& rccOutput)
  2073. {
  2074. std::vector<std::string> const& files = this->RccInputs[qrcFile];
  2075. for (std::vector<std::string>::const_iterator it = files.begin();
  2076. it != files.end(); ++it)
  2077. {
  2078. int inputNewerThanQrc = 0;
  2079. bool success = cmsys::SystemTools::FileTimeCompare(*it,
  2080. rccOutput,
  2081. &inputNewerThanQrc);
  2082. if (!success || inputNewerThanQrc >= 0)
  2083. {
  2084. return true;
  2085. }
  2086. }
  2087. return false;
  2088. }
  2089. bool cmQtAutoGenerators::GenerateQrc()
  2090. {
  2091. for(std::vector<std::string>::const_iterator si = this->RccSources.begin();
  2092. si != this->RccSources.end(); ++si)
  2093. {
  2094. std::string ext = cmsys::SystemTools::GetFilenameLastExtension(*si);
  2095. if (ext != ".qrc")
  2096. {
  2097. continue;
  2098. }
  2099. std::vector<std::string> command;
  2100. command.push_back(this->RccExecutable);
  2101. std::string basename = cmsys::SystemTools::
  2102. GetFilenameWithoutLastExtension(*si);
  2103. std::string rcc_output_file = this->Builddir
  2104. + "CMakeFiles/" + this->OriginTargetName
  2105. + ".dir/qrc_" + basename + ".cpp";
  2106. int sourceNewerThanQrc = 0;
  2107. bool generateQrc = !cmsys::SystemTools::FileTimeCompare(*si,
  2108. rcc_output_file,
  2109. &sourceNewerThanQrc);
  2110. generateQrc = generateQrc || (sourceNewerThanQrc >= 0);
  2111. generateQrc = generateQrc || this->InputFilesNewerThanQrc(*si,
  2112. rcc_output_file);
  2113. if (this->GenerateAll || generateQrc)
  2114. {
  2115. std::map<std::string, std::string>::const_iterator optionIt
  2116. = this->RccOptions.find(*si);
  2117. if (optionIt != this->RccOptions.end())
  2118. {
  2119. std::vector<std::string> opts;
  2120. cmSystemTools::ExpandListArgument(optionIt->second, opts);
  2121. for(std::vector<std::string>::const_iterator optIt = opts.begin();
  2122. optIt != opts.end();
  2123. ++optIt)
  2124. {
  2125. command.push_back(*optIt);
  2126. }
  2127. }
  2128. command.push_back("-name");
  2129. command.push_back(basename);
  2130. command.push_back("-o");
  2131. command.push_back(rcc_output_file);
  2132. command.push_back(*si);
  2133. if (this->Verbose)
  2134. {
  2135. for(std::vector<std::string>::const_iterator cmdIt = command.begin();
  2136. cmdIt != command.end();
  2137. ++cmdIt)
  2138. {
  2139. std::cout << *cmdIt << " ";
  2140. }
  2141. std::cout << std::endl;
  2142. }
  2143. std::string output;
  2144. int retVal = 0;
  2145. bool result = cmSystemTools::RunSingleCommand(command, &output, &retVal);
  2146. if (!result || retVal)
  2147. {
  2148. std::cerr << "AUTORCC: error: process for " << rcc_output_file <<
  2149. " failed:\n" << output << std::endl;
  2150. this->RunRccFailed = true;
  2151. cmSystemTools::RemoveFile(rcc_output_file);
  2152. return false;
  2153. }
  2154. }
  2155. }
  2156. return true;
  2157. }
  2158. std::string cmQtAutoGenerators::Join(const std::vector<std::string>& lst,
  2159. char separator)
  2160. {
  2161. if (lst.empty())
  2162. {
  2163. return "";
  2164. }
  2165. std::string result;
  2166. for (std::vector<std::string>::const_iterator it = lst.begin();
  2167. it != lst.end();
  2168. ++it)
  2169. {
  2170. result += "." + (*it) + separator;
  2171. }
  2172. result.erase(result.end() - 1);
  2173. return result;
  2174. }
  2175. bool cmQtAutoGenerators::StartsWith(const std::string& str,
  2176. const std::string& with)
  2177. {
  2178. return (str.substr(0, with.length()) == with);
  2179. }
  2180. bool cmQtAutoGenerators::EndsWith(const std::string& str,
  2181. const std::string& with)
  2182. {
  2183. if (with.length() > (str.length()))
  2184. {
  2185. return false;
  2186. }
  2187. return (str.substr(str.length() - with.length(), with.length()) == with);
  2188. }