cmQtAutoGeneratorInitializer.cxx 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmQtAutoGeneratorInitializer.h"
  4. #include "cmQtAutoGeneratorCommon.h"
  5. #include "cmAlgorithms.h"
  6. #include "cmCustomCommand.h"
  7. #include "cmCustomCommandLines.h"
  8. #include "cmFilePathChecksum.h"
  9. #include "cmGeneratorTarget.h"
  10. #include "cmGlobalGenerator.h"
  11. #include "cmLocalGenerator.h"
  12. #include "cmMakefile.h"
  13. #include "cmOutputConverter.h"
  14. #include "cmPolicies.h"
  15. #include "cmSourceFile.h"
  16. #include "cmSourceGroup.h"
  17. #include "cmState.h"
  18. #include "cmSystemTools.h"
  19. #include "cmTarget.h"
  20. #include "cm_sys_stat.h"
  21. #include "cmake.h"
  22. #include "cmsys/FStream.hxx"
  23. #include <algorithm>
  24. #include <map>
  25. #include <set>
  26. #include <sstream>
  27. #include <string>
  28. #include <utility>
  29. #include <vector>
  30. inline static const char* SafeString(const char* value)
  31. {
  32. return (value != nullptr) ? value : "";
  33. }
  34. static std::string GetSafeProperty(cmGeneratorTarget const* target,
  35. const char* key)
  36. {
  37. return std::string(SafeString(target->GetProperty(key)));
  38. }
  39. inline static bool AutogenMultiConfig(cmGlobalGenerator* globalGen)
  40. {
  41. return globalGen->IsMultiConfig();
  42. }
  43. static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
  44. {
  45. std::string autogenTargetName = target->GetName();
  46. autogenTargetName += "_autogen";
  47. return autogenTargetName;
  48. }
  49. static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target)
  50. {
  51. cmMakefile* makefile = target->Target->GetMakefile();
  52. std::string targetDir = makefile->GetCurrentBinaryDirectory();
  53. targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
  54. targetDir += "/";
  55. targetDir += GetAutogenTargetName(target);
  56. targetDir += ".dir";
  57. return targetDir;
  58. }
  59. static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
  60. {
  61. std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR");
  62. if (targetDir.empty()) {
  63. cmMakefile* makefile = target->Target->GetMakefile();
  64. targetDir = makefile->GetCurrentBinaryDirectory();
  65. targetDir += "/";
  66. targetDir += GetAutogenTargetName(target);
  67. }
  68. return targetDir;
  69. }
  70. static std::string GetQtMajorVersion(cmGeneratorTarget const* target)
  71. {
  72. cmMakefile* makefile = target->Target->GetMakefile();
  73. std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
  74. if (qtMajorVersion.empty()) {
  75. qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
  76. }
  77. const char* targetQtVersion =
  78. target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
  79. if (targetQtVersion != nullptr) {
  80. qtMajorVersion = targetQtVersion;
  81. }
  82. return qtMajorVersion;
  83. }
  84. static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
  85. const std::string& qtMajorVersion)
  86. {
  87. cmMakefile* makefile = target->Target->GetMakefile();
  88. std::string qtMinorVersion;
  89. if (qtMajorVersion == "5") {
  90. qtMinorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
  91. }
  92. if (qtMinorVersion.empty()) {
  93. qtMinorVersion = makefile->GetSafeDefinition("QT_VERSION_MINOR");
  94. }
  95. const char* targetQtVersion =
  96. target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
  97. if (targetQtVersion != nullptr) {
  98. qtMinorVersion = targetQtVersion;
  99. }
  100. return qtMinorVersion;
  101. }
  102. static bool QtVersionGreaterOrEqual(const std::string& major,
  103. const std::string& minor,
  104. unsigned long requestMajor,
  105. unsigned long requestMinor)
  106. {
  107. unsigned long majorUL(0);
  108. unsigned long minorUL(0);
  109. if (cmSystemTools::StringToULong(major.c_str(), &majorUL) &&
  110. cmSystemTools::StringToULong(minor.c_str(), &minorUL)) {
  111. return (majorUL > requestMajor) ||
  112. (majorUL == requestMajor && minorUL >= requestMinor);
  113. }
  114. return false;
  115. }
  116. static void GetCompileDefinitionsAndDirectories(
  117. cmGeneratorTarget const* target, const std::string& config,
  118. std::string& incs, std::string& defs)
  119. {
  120. cmLocalGenerator* localGen = target->GetLocalGenerator();
  121. {
  122. std::vector<std::string> includeDirs;
  123. // Get the include dirs for this target, without stripping the implicit
  124. // include dirs off, see
  125. // https://gitlab.kitware.com/cmake/cmake/issues/13667
  126. localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false);
  127. incs = cmJoin(includeDirs, ";");
  128. }
  129. {
  130. std::set<std::string> defines;
  131. localGen->AddCompileDefinitions(defines, target, config, "CXX");
  132. defs += cmJoin(defines, ";");
  133. }
  134. }
  135. static std::vector<std::string> GetConfigurations(
  136. cmMakefile* makefile, std::string* config = nullptr)
  137. {
  138. std::vector<std::string> configs;
  139. {
  140. std::string cfg = makefile->GetConfigurations(configs);
  141. if (config != nullptr) {
  142. *config = cfg;
  143. }
  144. }
  145. // Add empty configuration on demand
  146. if (configs.empty()) {
  147. configs.push_back("");
  148. }
  149. return configs;
  150. }
  151. static std::vector<std::string> GetConfigurationSuffixes(cmMakefile* makefile)
  152. {
  153. std::vector<std::string> suffixes;
  154. if (AutogenMultiConfig(makefile->GetGlobalGenerator())) {
  155. makefile->GetConfigurations(suffixes);
  156. for (std::vector<std::string>::iterator it = suffixes.begin();
  157. it != suffixes.end(); ++it) {
  158. it->insert(0, "_");
  159. }
  160. }
  161. if (suffixes.empty()) {
  162. suffixes.push_back("");
  163. }
  164. return suffixes;
  165. }
  166. static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
  167. const std::string& value)
  168. {
  169. makefile->AddDefinition(key,
  170. cmOutputConverter::EscapeForCMake(value).c_str());
  171. }
  172. static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
  173. const std::vector<std::string>& values)
  174. {
  175. makefile->AddDefinition(
  176. key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
  177. }
  178. static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
  179. const std::set<std::string>& values)
  180. {
  181. makefile->AddDefinition(
  182. key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
  183. }
  184. static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName,
  185. cmQtAutoGeneratorCommon::GeneratorType genType)
  186. {
  187. cmSourceGroup* sourceGroup = nullptr;
  188. // Acquire source group
  189. {
  190. const char* groupName = nullptr;
  191. // Use generator specific group name
  192. switch (genType) {
  193. case cmQtAutoGeneratorCommon::MOC:
  194. groupName =
  195. makefile->GetState()->GetGlobalProperty("AUTOMOC_SOURCE_GROUP");
  196. break;
  197. case cmQtAutoGeneratorCommon::RCC:
  198. groupName =
  199. makefile->GetState()->GetGlobalProperty("AUTORCC_SOURCE_GROUP");
  200. break;
  201. default:
  202. break;
  203. }
  204. // Use default group name on demand
  205. if ((groupName == nullptr) || (*groupName == 0)) {
  206. groupName =
  207. makefile->GetState()->GetGlobalProperty("AUTOGEN_SOURCE_GROUP");
  208. }
  209. // Generate a source group on demand
  210. if ((groupName != nullptr) && (*groupName != 0)) {
  211. {
  212. const char* delimiter =
  213. makefile->GetDefinition("SOURCE_GROUP_DELIMITER");
  214. if (delimiter == nullptr) {
  215. delimiter = "\\";
  216. }
  217. std::vector<std::string> folders =
  218. cmSystemTools::tokenize(groupName, delimiter);
  219. sourceGroup = makefile->GetSourceGroup(folders);
  220. if (sourceGroup == nullptr) {
  221. makefile->AddSourceGroup(folders);
  222. sourceGroup = makefile->GetSourceGroup(folders);
  223. }
  224. }
  225. if (sourceGroup == nullptr) {
  226. cmSystemTools::Error(
  227. "Autogen: Could not create or find source group: ",
  228. cmQtAutoGeneratorCommon::Quoted(groupName).c_str());
  229. return false;
  230. }
  231. }
  232. }
  233. if (sourceGroup != nullptr) {
  234. sourceGroup->AddGroupFile(fileName);
  235. }
  236. return true;
  237. }
  238. static void AddCleanFile(cmMakefile* makefile, const std::string& fileName)
  239. {
  240. makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fileName.c_str(),
  241. false);
  242. }
  243. static void AddGeneratedSource(cmGeneratorTarget* target,
  244. const std::string& filename,
  245. cmQtAutoGeneratorCommon::GeneratorType genType)
  246. {
  247. cmMakefile* makefile = target->Target->GetMakefile();
  248. {
  249. cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
  250. gFile->SetProperty("GENERATED", "1");
  251. gFile->SetProperty("SKIP_AUTOGEN", "On");
  252. }
  253. target->AddSource(filename);
  254. AddToSourceGroup(makefile, filename, genType);
  255. }
  256. struct AutogenSetup
  257. {
  258. std::vector<std::string> sources;
  259. std::vector<std::string> headers;
  260. std::set<std::string> mocSkip;
  261. std::set<std::string> uicSkip;
  262. std::map<std::string, std::string> configSuffix;
  263. std::map<std::string, std::string> configMocIncludes;
  264. std::map<std::string, std::string> configMocDefines;
  265. std::map<std::string, std::string> configUicOptions;
  266. };
  267. static void SetupAcquireScanFiles(cmGeneratorTarget const* target,
  268. bool mocEnabled, bool uicEnabled,
  269. const std::vector<cmSourceFile*>& srcFiles,
  270. AutogenSetup& setup)
  271. {
  272. // Read skip files from makefile sources
  273. {
  274. const std::vector<cmSourceFile*>& allSources =
  275. target->Makefile->GetSourceFiles();
  276. for (std::vector<cmSourceFile*>::const_iterator fit = allSources.begin();
  277. fit != allSources.end(); ++fit) {
  278. cmSourceFile* sf = *fit;
  279. // sf->GetExtension() is only valid after sf->GetFullPath() ...
  280. const std::string& fPath = sf->GetFullPath();
  281. const cmSystemTools::FileFormat fileType =
  282. cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
  283. if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
  284. !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
  285. continue;
  286. }
  287. const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
  288. const bool mocSkip =
  289. mocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
  290. const bool uicSkip =
  291. uicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
  292. if (mocSkip || uicSkip) {
  293. const std::string absFile = cmsys::SystemTools::GetRealPath(fPath);
  294. if (mocSkip) {
  295. setup.mocSkip.insert(absFile);
  296. }
  297. if (uicSkip) {
  298. setup.uicSkip.insert(absFile);
  299. }
  300. }
  301. }
  302. }
  303. const cmPolicies::PolicyStatus CMP0071_status =
  304. target->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
  305. for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
  306. fileIt != srcFiles.end(); ++fileIt) {
  307. cmSourceFile* sf = *fileIt;
  308. // sf->GetExtension() is only valid after sf->GetFullPath() ...
  309. const std::string& fPath = sf->GetFullPath();
  310. const cmSystemTools::FileFormat fileType =
  311. cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
  312. if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
  313. !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
  314. continue;
  315. }
  316. // Real file path
  317. const std::string absFile = cmsys::SystemTools::GetRealPath(fPath);
  318. // Skip test
  319. const bool mocSkip = !mocEnabled || (setup.mocSkip.count(absFile) != 0);
  320. const bool uicSkip = !uicEnabled || (setup.uicSkip.count(absFile) != 0);
  321. if (mocSkip && uicSkip) {
  322. continue;
  323. }
  324. // For GENERATED files check status of policy CMP0071
  325. if (sf->GetPropertyAsBool("GENERATED")) {
  326. bool policyAccept = false;
  327. switch (CMP0071_status) {
  328. case cmPolicies::WARN: {
  329. std::ostringstream ost;
  330. ost << cmPolicies::GetPolicyWarning(cmPolicies::CMP0071) << "\n";
  331. ost << "AUTOMOC/AUTOUIC: Ignoring GENERATED source file:\n";
  332. ost << " " << cmQtAutoGeneratorCommon::Quoted(absFile) << "\n";
  333. target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, ost.str());
  334. }
  335. CM_FALLTHROUGH;
  336. case cmPolicies::OLD:
  337. // Ignore GENERATED file
  338. break;
  339. case cmPolicies::REQUIRED_IF_USED:
  340. case cmPolicies::REQUIRED_ALWAYS:
  341. case cmPolicies::NEW:
  342. // Process GENERATED file
  343. policyAccept = true;
  344. break;
  345. }
  346. if (!policyAccept) {
  347. continue;
  348. }
  349. }
  350. // Add file name to sources or headers list
  351. switch (fileType) {
  352. case cmSystemTools::CXX_FILE_FORMAT:
  353. setup.sources.push_back(absFile);
  354. break;
  355. case cmSystemTools::HEADER_FILE_FORMAT:
  356. setup.headers.push_back(absFile);
  357. break;
  358. default:
  359. break;
  360. }
  361. }
  362. }
  363. static void SetupAutoTargetMoc(cmGeneratorTarget const* target,
  364. std::string const& qtMajorVersion,
  365. std::string const& config,
  366. std::vector<std::string> const& configs,
  367. AutogenSetup& setup)
  368. {
  369. cmLocalGenerator* localGen = target->GetLocalGenerator();
  370. cmMakefile* makefile = target->Target->GetMakefile();
  371. AddDefinitionEscaped(makefile, "_moc_skip", setup.mocSkip);
  372. AddDefinitionEscaped(makefile, "_moc_options",
  373. GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));
  374. AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
  375. makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
  376. : "FALSE");
  377. AddDefinitionEscaped(makefile, "_moc_macro_names",
  378. GetSafeProperty(target, "AUTOMOC_MACRO_NAMES"));
  379. AddDefinitionEscaped(makefile, "_moc_depend_filters",
  380. GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
  381. if (QtVersionGreaterOrEqual(
  382. qtMajorVersion, GetQtMinorVersion(target, qtMajorVersion), 5, 8)) {
  383. AddDefinitionEscaped(
  384. makefile, "_moc_predefs_cmd",
  385. makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
  386. }
  387. // Moc includes and compile definitions
  388. {
  389. // Default settings
  390. std::string incs;
  391. std::string compileDefs;
  392. GetCompileDefinitionsAndDirectories(target, config, incs, compileDefs);
  393. AddDefinitionEscaped(makefile, "_moc_incs", incs);
  394. AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
  395. // Configuration specific settings
  396. for (std::vector<std::string>::const_iterator li = configs.begin();
  397. li != configs.end(); ++li) {
  398. std::string configIncs;
  399. std::string configCompileDefs;
  400. GetCompileDefinitionsAndDirectories(target, *li, configIncs,
  401. configCompileDefs);
  402. if (configIncs != incs) {
  403. setup.configMocIncludes[*li] = configIncs;
  404. }
  405. if (configCompileDefs != compileDefs) {
  406. setup.configMocDefines[*li] = configCompileDefs;
  407. }
  408. }
  409. }
  410. // Moc executable
  411. {
  412. std::string mocExec;
  413. std::string err;
  414. if (qtMajorVersion == "5") {
  415. cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
  416. if (tgt != nullptr) {
  417. mocExec = SafeString(tgt->ImportedGetLocation(""));
  418. } else {
  419. err = "AUTOMOC: Qt5::moc target not found";
  420. }
  421. } else if (qtMajorVersion == "4") {
  422. cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
  423. if (tgt != nullptr) {
  424. mocExec = SafeString(tgt->ImportedGetLocation(""));
  425. } else {
  426. err = "AUTOMOC: Qt4::moc target not found";
  427. }
  428. } else {
  429. err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
  430. }
  431. if (err.empty()) {
  432. AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
  433. } else {
  434. err += " (" + target->GetName() + ")";
  435. cmSystemTools::Error(err.c_str());
  436. }
  437. }
  438. }
  439. static void UicGetOpts(cmGeneratorTarget const* target,
  440. const std::string& config, std::string& optString)
  441. {
  442. std::vector<std::string> opts;
  443. target->GetAutoUicOptions(opts, config);
  444. optString = cmJoin(opts, ";");
  445. }
  446. static void SetupAutoTargetUic(cmGeneratorTarget const* target,
  447. std::string const& qtMajorVersion,
  448. std::string const& config,
  449. std::vector<std::string> const& configs,
  450. AutogenSetup& setup)
  451. {
  452. cmLocalGenerator* localGen = target->GetLocalGenerator();
  453. cmMakefile* makefile = target->Target->GetMakefile();
  454. AddDefinitionEscaped(makefile, "_uic_skip", setup.uicSkip);
  455. // Uic search paths
  456. {
  457. std::vector<std::string> uicSearchPaths;
  458. {
  459. const std::string usp = GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS");
  460. if (!usp.empty()) {
  461. cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
  462. const std::string srcDir = makefile->GetCurrentSourceDirectory();
  463. for (std::vector<std::string>::iterator it = uicSearchPaths.begin();
  464. it != uicSearchPaths.end(); ++it) {
  465. *it = cmSystemTools::CollapseFullPath(*it, srcDir);
  466. }
  467. }
  468. }
  469. AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
  470. }
  471. // Uic target options
  472. {
  473. // Default settings
  474. std::string uicOpts;
  475. UicGetOpts(target, config, uicOpts);
  476. AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
  477. // Configuration specific settings
  478. for (std::vector<std::string>::const_iterator li = configs.begin();
  479. li != configs.end(); ++li) {
  480. std::string configUicOpts;
  481. UicGetOpts(target, *li, configUicOpts);
  482. if (configUicOpts != uicOpts) {
  483. setup.configUicOptions[*li] = configUicOpts;
  484. }
  485. }
  486. }
  487. // Uic files options
  488. {
  489. std::vector<std::string> uiFileFiles;
  490. std::vector<std::string> uiFileOptions;
  491. {
  492. const std::string uiExt = "ui";
  493. const std::vector<cmSourceFile*>& srcFiles = makefile->GetSourceFiles();
  494. for (std::vector<cmSourceFile*>::const_iterator fit = srcFiles.begin();
  495. fit != srcFiles.end(); ++fit) {
  496. cmSourceFile* sf = *fit;
  497. // sf->GetExtension() is only valid after sf->GetFullPath() ...
  498. const std::string& fPath = sf->GetFullPath();
  499. if (sf->GetExtension() == uiExt) {
  500. // Check if the files has uic options
  501. std::string uicOpts = sf->GetProperty("AUTOUIC_OPTIONS");
  502. if (!uicOpts.empty()) {
  503. const std::string absFile = cmsys::SystemTools::GetRealPath(fPath);
  504. // Check if file isn't skipped
  505. if (setup.uicSkip.count(absFile) == 0) {
  506. uiFileFiles.push_back(absFile);
  507. cmSystemTools::ReplaceString(uicOpts, ";",
  508. cmQtAutoGeneratorCommon::listSep);
  509. uiFileOptions.push_back(uicOpts);
  510. }
  511. }
  512. }
  513. }
  514. }
  515. AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
  516. AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
  517. }
  518. // Uic executable
  519. {
  520. std::string err;
  521. std::string uicExec;
  522. if (qtMajorVersion == "5") {
  523. cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
  524. if (tgt != nullptr) {
  525. uicExec = SafeString(tgt->ImportedGetLocation(""));
  526. } else {
  527. // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
  528. }
  529. } else if (qtMajorVersion == "4") {
  530. cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
  531. if (tgt != nullptr) {
  532. uicExec = SafeString(tgt->ImportedGetLocation(""));
  533. } else {
  534. err = "AUTOUIC: Qt4::uic target not found";
  535. }
  536. } else {
  537. err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
  538. }
  539. if (err.empty()) {
  540. AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
  541. } else {
  542. err += " (" + target->GetName() + ")";
  543. cmSystemTools::Error(err.c_str());
  544. }
  545. }
  546. }
  547. static std::string RccGetExecutable(cmGeneratorTarget const* target,
  548. const std::string& qtMajorVersion)
  549. {
  550. std::string rccExec;
  551. std::string err;
  552. cmLocalGenerator* localGen = target->GetLocalGenerator();
  553. if (qtMajorVersion == "5") {
  554. cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc");
  555. if (tgt != nullptr) {
  556. rccExec = SafeString(tgt->ImportedGetLocation(""));
  557. } else {
  558. err = "AUTORCC: Qt5::rcc target not found";
  559. }
  560. } else if (qtMajorVersion == "4") {
  561. cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc");
  562. if (tgt != nullptr) {
  563. rccExec = SafeString(tgt->ImportedGetLocation(""));
  564. } else {
  565. err = "AUTORCC: Qt4::rcc target not found";
  566. }
  567. } else {
  568. err = "The AUTORCC feature supports only Qt 4 and Qt 5";
  569. }
  570. if (!err.empty()) {
  571. err += " (" + target->GetName() + ")";
  572. cmSystemTools::Error(err.c_str());
  573. }
  574. return rccExec;
  575. }
  576. static void RccMergeOptions(std::vector<std::string>& opts,
  577. const std::vector<std::string>& fileOpts,
  578. bool isQt5)
  579. {
  580. static const char* valueOptions[] = { "name", "root", "compress",
  581. "threshold" };
  582. std::vector<std::string> extraOpts;
  583. for (std::vector<std::string>::const_iterator fit = fileOpts.begin();
  584. fit != fileOpts.end(); ++fit) {
  585. std::vector<std::string>::iterator existingIt =
  586. std::find(opts.begin(), opts.end(), *fit);
  587. if (existingIt != opts.end()) {
  588. const char* optName = fit->c_str();
  589. if (*optName == '-') {
  590. ++optName;
  591. if (isQt5 && *optName == '-') {
  592. ++optName;
  593. }
  594. }
  595. // Test if this is a value option and change the existing value
  596. if ((optName != fit->c_str()) &&
  597. std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
  598. cmStrCmp(optName)) != cmArrayEnd(valueOptions)) {
  599. const std::vector<std::string>::iterator existValueIt(existingIt + 1);
  600. const std::vector<std::string>::const_iterator fileValueIt(fit + 1);
  601. if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) {
  602. *existValueIt = *fileValueIt;
  603. ++fit;
  604. }
  605. }
  606. } else {
  607. extraOpts.push_back(*fit);
  608. }
  609. }
  610. opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
  611. }
  612. static void SetupAutoTargetRcc(cmGeneratorTarget const* target,
  613. const std::string& qtMajorVersion,
  614. const std::vector<cmSourceFile*>& srcFiles)
  615. {
  616. cmMakefile* makefile = target->Target->GetMakefile();
  617. const bool qtMajorVersion5 = (qtMajorVersion == "5");
  618. const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
  619. std::vector<std::string> rccFiles;
  620. std::vector<std::string> rccInputs;
  621. std::vector<std::string> rccFileFiles;
  622. std::vector<std::string> rccFileOptions;
  623. std::vector<std::string> rccOptionsTarget;
  624. cmSystemTools::ExpandListArgument(GetSafeProperty(target, "AUTORCC_OPTIONS"),
  625. rccOptionsTarget);
  626. for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
  627. fileIt != srcFiles.end(); ++fileIt) {
  628. cmSourceFile* sf = *fileIt;
  629. // sf->GetExtension() is only valid after sf->GetFullPath() ...
  630. const std::string& fPath = sf->GetFullPath();
  631. if ((sf->GetExtension() == "qrc") &&
  632. !sf->GetPropertyAsBool("SKIP_AUTOGEN") &&
  633. !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
  634. const std::string absFile = cmsys::SystemTools::GetRealPath(fPath);
  635. // qrc file
  636. rccFiles.push_back(absFile);
  637. // qrc file entries
  638. {
  639. std::string entriesList = "{";
  640. // Read input file list only for non generated .qrc files.
  641. if (!sf->GetPropertyAsBool("GENERATED")) {
  642. std::string error;
  643. std::vector<std::string> files;
  644. if (cmQtAutoGeneratorCommon::RccListInputs(
  645. qtMajorVersion, rccCommand, absFile, files, &error)) {
  646. entriesList += cmJoin(files, cmQtAutoGeneratorCommon::listSep);
  647. } else {
  648. cmSystemTools::Error(error.c_str());
  649. }
  650. }
  651. entriesList += "}";
  652. rccInputs.push_back(entriesList);
  653. }
  654. // rcc options for this qrc file
  655. {
  656. // Merged target and file options
  657. std::vector<std::string> rccOptions(rccOptionsTarget);
  658. if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) {
  659. std::vector<std::string> optsVec;
  660. cmSystemTools::ExpandListArgument(prop, optsVec);
  661. RccMergeOptions(rccOptions, optsVec, qtMajorVersion5);
  662. }
  663. // Only store non empty options lists
  664. if (!rccOptions.empty()) {
  665. rccFileFiles.push_back(absFile);
  666. rccFileOptions.push_back(
  667. cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep));
  668. }
  669. }
  670. }
  671. }
  672. AddDefinitionEscaped(makefile, "_qt_rcc_executable", rccCommand);
  673. AddDefinitionEscaped(makefile, "_rcc_files", rccFiles);
  674. AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs);
  675. AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles);
  676. AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions);
  677. }
  678. void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
  679. cmLocalGenerator* localGen, cmGeneratorTarget* target)
  680. {
  681. cmMakefile* makefile = target->Target->GetMakefile();
  682. cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
  683. // Create a custom target for running generators at buildtime
  684. const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
  685. const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
  686. const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
  687. const bool multiConfig = AutogenMultiConfig(globalGen);
  688. const std::string autogenTargetName = GetAutogenTargetName(target);
  689. const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);
  690. const std::string workingDirectory =
  691. cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
  692. const std::vector<std::string> suffixes = GetConfigurationSuffixes(makefile);
  693. std::set<std::string> autogenDependsSet;
  694. std::vector<std::string> autogenProvides;
  695. bool usePRE_BUILD = false;
  696. if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
  697. // Under VS use a PRE_BUILD event instead of a separate target to
  698. // reduce the number of targets loaded into the IDE.
  699. // This also works around a VS 11 bug that may skip updating the target:
  700. // https://connect.microsoft.com/VisualStudio/feedback/details/769495
  701. usePRE_BUILD = true;
  702. }
  703. // Remove build directories on cleanup
  704. AddCleanFile(makefile, autogenBuildDir);
  705. // Remove old settings on cleanup
  706. {
  707. std::string base = GetAutogenTargetFilesDir(target);
  708. base += "/AutogenOldSettings";
  709. for (std::vector<std::string>::const_iterator it = suffixes.begin();
  710. it != suffixes.end(); ++it) {
  711. AddCleanFile(makefile, base + *it + ".cmake");
  712. }
  713. }
  714. // Compose command lines
  715. cmCustomCommandLines commandLines;
  716. {
  717. cmCustomCommandLine currentLine;
  718. currentLine.push_back(cmSystemTools::GetCMakeCommand());
  719. currentLine.push_back("-E");
  720. currentLine.push_back("cmake_autogen");
  721. currentLine.push_back(GetAutogenTargetFilesDir(target));
  722. currentLine.push_back("$<CONFIGURATION>");
  723. commandLines.push_back(currentLine);
  724. }
  725. // Compose target comment
  726. std::string autogenComment;
  727. {
  728. std::vector<std::string> toolNames;
  729. if (mocEnabled) {
  730. toolNames.push_back("MOC");
  731. }
  732. if (uicEnabled) {
  733. toolNames.push_back("UIC");
  734. }
  735. if (rccEnabled) {
  736. toolNames.push_back("RCC");
  737. }
  738. std::string tools = toolNames[0];
  739. toolNames.erase(toolNames.begin());
  740. while (toolNames.size() > 1) {
  741. tools += ", " + toolNames[0];
  742. toolNames.erase(toolNames.begin());
  743. }
  744. if (toolNames.size() == 1) {
  745. tools += " and " + toolNames[0];
  746. }
  747. autogenComment = "Automatic " + tools + " for target " + target->GetName();
  748. }
  749. // Add moc compilation to generated files list
  750. if (mocEnabled) {
  751. const std::string mocsComp = autogenBuildDir + "/mocs_compilation.cpp";
  752. AddGeneratedSource(target, mocsComp, cmQtAutoGeneratorCommon::MOC);
  753. autogenProvides.push_back(mocsComp);
  754. }
  755. // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
  756. if (mocEnabled || uicEnabled) {
  757. std::string includeDir = autogenBuildDir + "/include";
  758. if (multiConfig) {
  759. includeDir += "_$<CONFIG>";
  760. }
  761. target->AddIncludeDirectory(includeDir, true);
  762. }
  763. // Add user defined autogen target dependencies
  764. {
  765. const std::string deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS");
  766. if (!deps.empty()) {
  767. std::vector<std::string> extraDepends;
  768. cmSystemTools::ExpandListArgument(deps, extraDepends);
  769. autogenDependsSet.insert(extraDepends.begin(), extraDepends.end());
  770. }
  771. }
  772. // Add utility target dependencies to the autogen dependencies
  773. {
  774. const std::set<std::string>& utils = target->Target->GetUtilities();
  775. for (std::set<std::string>::const_iterator it = utils.begin();
  776. it != utils.end(); ++it) {
  777. const std::string& targetName = *it;
  778. if (makefile->FindTargetToUse(targetName) != nullptr) {
  779. autogenDependsSet.insert(targetName);
  780. }
  781. }
  782. }
  783. // Add link library target dependencies to the autogen dependencies
  784. {
  785. const cmTarget::LinkLibraryVectorType& libVec =
  786. target->Target->GetOriginalLinkLibraries();
  787. for (cmTarget::LinkLibraryVectorType::const_iterator it = libVec.begin();
  788. it != libVec.end(); ++it) {
  789. const std::string& libName = it->first;
  790. if (makefile->FindTargetToUse(libName) != nullptr) {
  791. autogenDependsSet.insert(libName);
  792. }
  793. }
  794. }
  795. // Extract relevant source files
  796. std::vector<std::string> generatedSources;
  797. std::vector<std::pair<std::string, bool>> qrcSources;
  798. {
  799. const std::string qrcExt = "qrc";
  800. std::vector<cmSourceFile*> srcFiles;
  801. target->GetConfigCommonSourceFiles(srcFiles);
  802. for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
  803. fileIt != srcFiles.end(); ++fileIt) {
  804. cmSourceFile* sf = *fileIt;
  805. if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
  806. continue;
  807. }
  808. // sf->GetExtension() is only valid after sf->GetFullPath() ...
  809. const std::string& fPath = sf->GetFullPath();
  810. const std::string& ext = sf->GetExtension();
  811. // Register generated files that will be scanned by moc or uic
  812. if (mocEnabled || uicEnabled) {
  813. const cmSystemTools::FileFormat fileType =
  814. cmSystemTools::GetFileFormat(ext.c_str());
  815. if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
  816. (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
  817. if (sf->GetPropertyAsBool("GENERATED")) {
  818. if ((mocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
  819. (uicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
  820. generatedSources.push_back(
  821. cmsys::SystemTools::GetRealPath(fPath));
  822. }
  823. }
  824. }
  825. }
  826. // Register rcc enabled files
  827. if (rccEnabled && (ext == qrcExt) &&
  828. !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
  829. qrcSources.push_back(
  830. std::pair<std::string, bool>(cmsys::SystemTools::GetRealPath(fPath),
  831. sf->GetPropertyAsBool("GENERATED")));
  832. }
  833. }
  834. // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
  835. // sources meta data cache. Clear it so that OBJECT library targets that
  836. // are AUTOGEN initialized after this target get their added
  837. // mocs_compilation.cpp source acknowledged by this target.
  838. target->ClearSourcesCache();
  839. }
  840. if (!generatedSources.empty()) {
  841. for (std::vector<std::string>::const_iterator it =
  842. generatedSources.begin();
  843. it != generatedSources.end(); ++it) {
  844. autogenDependsSet.insert(*it);
  845. }
  846. }
  847. if (!qrcSources.empty()) {
  848. const std::string qtMajorVersion = GetQtMajorVersion(target);
  849. const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
  850. const cmFilePathChecksum fpathCheckSum(makefile);
  851. for (std::vector<std::pair<std::string, bool>>::const_iterator it =
  852. qrcSources.begin();
  853. it != qrcSources.end(); ++it) {
  854. const std::string& absFile = it->first;
  855. // Compose rcc output file name
  856. {
  857. std::string rccBuildFile = autogenBuildDir + "/";
  858. rccBuildFile += fpathCheckSum.getPart(absFile);
  859. rccBuildFile += "/qrc_";
  860. rccBuildFile +=
  861. cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
  862. rccBuildFile += ".cpp";
  863. // Register rcc ouput file as generated
  864. AddGeneratedSource(target, rccBuildFile, cmQtAutoGeneratorCommon::RCC);
  865. // Register rcc ouput file as generated by the _autogen target
  866. autogenProvides.push_back(rccBuildFile);
  867. }
  868. if (it->second) {
  869. // Add generated qrc file to the dependencies
  870. autogenDependsSet.insert(absFile);
  871. } else {
  872. // Run cmake again when .qrc file changes
  873. makefile->AddCMakeDependFile(absFile);
  874. // Add the qrc input files to the dependencies
  875. {
  876. std::string error;
  877. std::vector<std::string> extraDepends;
  878. if (cmQtAutoGeneratorCommon::RccListInputs(
  879. qtMajorVersion, rccCommand, absFile, extraDepends, &error)) {
  880. autogenDependsSet.insert(extraDepends.begin(), extraDepends.end());
  881. } else {
  882. cmSystemTools::Error(error.c_str());
  883. }
  884. }
  885. }
  886. }
  887. }
  888. // Convert std::set to std::vector
  889. const std::vector<std::string> autogenDepends(autogenDependsSet.begin(),
  890. autogenDependsSet.end());
  891. // Disable PRE_BUILD on demand
  892. if (usePRE_BUILD) {
  893. if (!generatedSources.empty() || !qrcSources.empty()) {
  894. // - Cannot use PRE_BUILD with generated files
  895. // - Cannot use PRE_BUILD because the resource files themselves
  896. // may not be sources within the target so VS may not know the
  897. // target needs to re-build at all.
  898. usePRE_BUILD = false;
  899. }
  900. if (usePRE_BUILD) {
  901. // If the autogen target depends on an other target don't use PRE_BUILD
  902. for (std::vector<std::string>::const_iterator it =
  903. autogenDepends.begin();
  904. it != autogenDepends.end(); ++it) {
  905. if (makefile->FindTargetToUse(*it) != nullptr) {
  906. usePRE_BUILD = false;
  907. break;
  908. }
  909. }
  910. }
  911. }
  912. if (usePRE_BUILD) {
  913. // Add the pre-build command directly to bypass the OBJECT_LIBRARY
  914. // rejection in cmMakefile::AddCustomCommandToTarget because we know
  915. // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
  916. std::vector<std::string> no_output;
  917. cmCustomCommand cc(makefile, no_output, autogenProvides, autogenDepends,
  918. commandLines, autogenComment.c_str(),
  919. workingDirectory.c_str());
  920. cc.SetEscapeOldStyle(false);
  921. cc.SetEscapeAllowMakeVars(true);
  922. target->Target->AddPreBuildCommand(cc);
  923. } else {
  924. cmTarget* autogenTarget = makefile->AddUtilityCommand(
  925. autogenTargetName, true, workingDirectory.c_str(),
  926. /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
  927. autogenComment.c_str());
  928. localGen->AddGeneratorTarget(
  929. new cmGeneratorTarget(autogenTarget, localGen));
  930. // Set autogen target FOLDER
  931. {
  932. const char* autogenFolder =
  933. makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
  934. if (autogenFolder == nullptr) {
  935. autogenFolder =
  936. makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
  937. }
  938. // Inherit FOLDER property from target (#13688)
  939. if (autogenFolder == nullptr) {
  940. autogenFolder = target->Target->GetProperty("FOLDER");
  941. }
  942. if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {
  943. autogenTarget->SetProperty("FOLDER", autogenFolder);
  944. }
  945. }
  946. // Add autogen target to the origin target dependencies
  947. target->Target->AddUtility(autogenTargetName);
  948. }
  949. }
  950. void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
  951. cmGeneratorTarget const* target)
  952. {
  953. cmMakefile* makefile = target->Target->GetMakefile();
  954. // forget the variables added here afterwards again:
  955. cmMakefile::ScopePushPop varScope(makefile);
  956. static_cast<void>(varScope);
  957. // Get configurations
  958. std::string config;
  959. const std::vector<std::string> configs(GetConfigurations(makefile, &config));
  960. // Configuration suffixes
  961. std::map<std::string, std::string> configSuffix;
  962. if (AutogenMultiConfig(target->GetGlobalGenerator())) {
  963. for (std::vector<std::string>::const_iterator it = configs.begin();
  964. it != configs.end(); ++it) {
  965. configSuffix[*it] = "_" + *it;
  966. }
  967. }
  968. // Configurations settings buffers
  969. AutogenSetup setup;
  970. // Basic setup
  971. {
  972. const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
  973. const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
  974. const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
  975. const std::string qtMajorVersion = GetQtMajorVersion(target);
  976. {
  977. std::vector<cmSourceFile*> srcFiles;
  978. target->GetConfigCommonSourceFiles(srcFiles);
  979. if (mocEnabled || uicEnabled) {
  980. SetupAcquireScanFiles(target, mocEnabled, uicEnabled, srcFiles, setup);
  981. if (mocEnabled) {
  982. SetupAutoTargetMoc(target, qtMajorVersion, config, configs, setup);
  983. }
  984. if (uicEnabled) {
  985. SetupAutoTargetUic(target, qtMajorVersion, config, configs, setup);
  986. }
  987. }
  988. if (rccEnabled) {
  989. SetupAutoTargetRcc(target, qtMajorVersion, srcFiles);
  990. }
  991. }
  992. AddDefinitionEscaped(makefile, "_build_dir",
  993. GetAutogenTargetBuildDir(target));
  994. AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion);
  995. AddDefinitionEscaped(makefile, "_sources", setup.sources);
  996. AddDefinitionEscaped(makefile, "_headers", setup.headers);
  997. }
  998. // Generate info file
  999. std::string infoFile = GetAutogenTargetFilesDir(target);
  1000. infoFile += "/AutogenInfo.cmake";
  1001. {
  1002. std::string inf = cmSystemTools::GetCMakeRoot();
  1003. inf += "/Modules/AutogenInfo.cmake.in";
  1004. makefile->ConfigureFile(inf.c_str(), infoFile.c_str(), false, true, false);
  1005. }
  1006. // Append custom definitions to info file on demand
  1007. if (!configSuffix.empty() || !setup.configMocDefines.empty() ||
  1008. !setup.configMocIncludes.empty() || !setup.configUicOptions.empty()) {
  1009. // Ensure we have write permission in case .in was read-only.
  1010. mode_t perm = 0;
  1011. #if defined(_WIN32) && !defined(__CYGWIN__)
  1012. mode_t mode_write = S_IWRITE;
  1013. #else
  1014. mode_t mode_write = S_IWUSR;
  1015. #endif
  1016. cmSystemTools::GetPermissions(infoFile, perm);
  1017. if (!(perm & mode_write)) {
  1018. cmSystemTools::SetPermissions(infoFile, perm | mode_write);
  1019. }
  1020. // Open and write file
  1021. cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
  1022. if (ofs) {
  1023. ofs << "# Configuration specific options\n";
  1024. for (std::map<std::string, std::string>::iterator
  1025. it = configSuffix.begin(),
  1026. end = configSuffix.end();
  1027. it != end; ++it) {
  1028. ofs << "set(AM_CONFIG_SUFFIX_" << it->first << " "
  1029. << cmOutputConverter::EscapeForCMake(it->second) << ")\n";
  1030. }
  1031. for (std::map<std::string, std::string>::iterator
  1032. it = setup.configMocDefines.begin(),
  1033. end = setup.configMocDefines.end();
  1034. it != end; ++it) {
  1035. ofs << "set(AM_MOC_DEFINITIONS_" << it->first << " "
  1036. << cmOutputConverter::EscapeForCMake(it->second) << ")\n";
  1037. }
  1038. for (std::map<std::string, std::string>::iterator
  1039. it = setup.configMocIncludes.begin(),
  1040. end = setup.configMocIncludes.end();
  1041. it != end; ++it) {
  1042. ofs << "set(AM_MOC_INCLUDES_" << it->first << " "
  1043. << cmOutputConverter::EscapeForCMake(it->second) << ")\n";
  1044. }
  1045. for (std::map<std::string, std::string>::iterator
  1046. it = setup.configUicOptions.begin(),
  1047. end = setup.configUicOptions.end();
  1048. it != end; ++it) {
  1049. ofs << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " "
  1050. << cmOutputConverter::EscapeForCMake(it->second) << ")\n";
  1051. }
  1052. } else {
  1053. // File open error
  1054. std::string error = "Internal CMake error when trying to open file: ";
  1055. error += cmQtAutoGeneratorCommon::Quoted(infoFile);
  1056. error += " for writing.";
  1057. cmSystemTools::Error(error.c_str());
  1058. }
  1059. }
  1060. }