cmQtAutoGenerators.cxx 66 KB

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