cmGhsMultiTargetGenerator.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  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 "cmGhsMultiTargetGenerator.h"
  4. #include "cmComputeLinkInformation.h"
  5. #include "cmGeneratedFileStream.h"
  6. #include "cmGeneratorTarget.h"
  7. #include "cmGlobalGhsMultiGenerator.h"
  8. #include "cmLinkLineComputer.h"
  9. #include "cmLocalGhsMultiGenerator.h"
  10. #include "cmMakefile.h"
  11. #include "cmSourceFile.h"
  12. #include "cmSourceGroup.h"
  13. #include "cmTarget.h"
  14. cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target)
  15. : GeneratorTarget(target)
  16. , LocalGenerator(
  17. static_cast<cmLocalGhsMultiGenerator*>(target->GetLocalGenerator()))
  18. , Makefile(target->Target->GetMakefile())
  19. , Name(target->GetName())
  20. {
  21. // Store the configuration name that is being used
  22. if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
  23. // Use the build type given by the user.
  24. this->ConfigName = config;
  25. } else {
  26. // No configuration type given.
  27. this->ConfigName.clear();
  28. }
  29. }
  30. cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator()
  31. {
  32. }
  33. void cmGhsMultiTargetGenerator::Generate()
  34. {
  35. // Determine type of target for this project
  36. switch (this->GeneratorTarget->GetType()) {
  37. case cmStateEnums::EXECUTABLE: {
  38. // Get the name of the executable to generate.
  39. std::string targetName;
  40. std::string targetNameImport;
  41. std::string targetNamePDB;
  42. this->GeneratorTarget->GetExecutableNames(
  43. targetName, this->TargetNameReal, targetNameImport, targetNamePDB,
  44. this->ConfigName);
  45. if (cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()) {
  46. this->TagType = GhsMultiGpj::INTERGRITY_APPLICATION;
  47. } else {
  48. this->TagType = GhsMultiGpj::PROGRAM;
  49. }
  50. break;
  51. }
  52. case cmStateEnums::STATIC_LIBRARY: {
  53. std::string targetName;
  54. std::string targetNameSO;
  55. std::string targetNameImport;
  56. std::string targetNamePDB;
  57. this->GeneratorTarget->GetLibraryNames(
  58. targetName, targetNameSO, this->TargetNameReal, targetNameImport,
  59. targetNamePDB, this->ConfigName);
  60. this->TagType = GhsMultiGpj::LIBRARY;
  61. break;
  62. }
  63. case cmStateEnums::SHARED_LIBRARY: {
  64. std::string msg = "add_library(<name> SHARED ...) not supported: ";
  65. msg += this->Name;
  66. cmSystemTools::Message(msg);
  67. return;
  68. }
  69. case cmStateEnums::OBJECT_LIBRARY: {
  70. std::string targetName;
  71. std::string targetNameSO;
  72. std::string targetNameImport;
  73. std::string targetNamePDB;
  74. this->GeneratorTarget->GetLibraryNames(
  75. targetName, targetNameSO, this->TargetNameReal, targetNameImport,
  76. targetNamePDB, this->ConfigName);
  77. this->TagType = GhsMultiGpj::SUBPROJECT;
  78. break;
  79. }
  80. case cmStateEnums::MODULE_LIBRARY: {
  81. std::string msg = "add_library(<name> MODULE ...) not supported: ";
  82. msg += this->Name;
  83. cmSystemTools::Message(msg);
  84. return;
  85. }
  86. case cmStateEnums::UTILITY: {
  87. std::string msg = "add_custom_target(<name> ...) not supported: ";
  88. msg += this->Name;
  89. cmSystemTools::Message(msg);
  90. return;
  91. }
  92. default:
  93. return;
  94. }
  95. // Tell the global generator the name of the project file
  96. this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
  97. this->Name.c_str());
  98. this->GeneratorTarget->Target->SetProperty(
  99. "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType));
  100. this->GenerateTarget();
  101. }
  102. void cmGhsMultiTargetGenerator::GenerateTarget()
  103. {
  104. // Open the filestream in copy-if-different mode.
  105. std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory();
  106. fname += "/";
  107. fname += this->Name;
  108. fname += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
  109. cmGeneratedFileStream fout(fname.c_str());
  110. fout.SetCopyIfDifferent(true);
  111. this->GetGlobalGenerator()->WriteFileHeader(fout);
  112. GhsMultiGpj::WriteGpjTag(this->TagType, fout);
  113. const std::string language(
  114. this->GeneratorTarget->GetLinkerLanguage(this->ConfigName));
  115. this->WriteTargetSpecifics(fout, this->ConfigName);
  116. this->SetCompilerFlags(this->ConfigName, language);
  117. this->WriteCompilerFlags(fout, this->ConfigName, language);
  118. this->WriteCompilerDefinitions(fout, this->ConfigName, language);
  119. this->WriteIncludes(fout, this->ConfigName, language);
  120. this->WriteTargetLinkLine(fout, this->ConfigName);
  121. this->WriteCustomCommands(fout);
  122. this->WriteSources(fout);
  123. this->WriteReferences(fout);
  124. fout.Close();
  125. }
  126. cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator()
  127. const
  128. {
  129. return static_cast<cmGlobalGhsMultiGenerator*>(
  130. this->LocalGenerator->GetGlobalGenerator());
  131. }
  132. void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout,
  133. const std::string& config)
  134. {
  135. std::string outpath;
  136. std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
  137. if (this->TagType != GhsMultiGpj::SUBPROJECT) {
  138. // set target binary file destination
  139. outpath = this->GeneratorTarget->GetDirectory(config);
  140. outpath =
  141. this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath);
  142. fout << " :binDirRelative=\"" << outpath << "\"" << std::endl;
  143. fout << " -o \"" << this->TargetNameReal << "\"" << std::endl;
  144. }
  145. // set target object file destination
  146. outpath = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
  147. fout << " :outputDirRelative=\"" << outpath << "\"" << std::endl;
  148. }
  149. void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config,
  150. const std::string& language)
  151. {
  152. std::map<std::string, std::string>::iterator i =
  153. this->FlagsByLanguage.find(language);
  154. if (i == this->FlagsByLanguage.end()) {
  155. std::string flags;
  156. const char* lang = language.c_str();
  157. this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, lang,
  158. config);
  159. this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang,
  160. config);
  161. this->LocalGenerator->AddVisibilityPresetFlags(
  162. flags, this->GeneratorTarget, lang);
  163. // Append old-style preprocessor definition flags.
  164. if (this->Makefile->GetDefineFlags() != " ") {
  165. this->LocalGenerator->AppendFlags(flags,
  166. this->Makefile->GetDefineFlags());
  167. }
  168. // Add target-specific flags.
  169. this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, lang,
  170. config);
  171. std::map<std::string, std::string>::value_type entry(language, flags);
  172. i = this->FlagsByLanguage.insert(entry).first;
  173. }
  174. }
  175. std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language,
  176. std::string const& config)
  177. {
  178. std::map<std::string, std::string>::iterator i =
  179. this->DefinesByLanguage.find(language);
  180. if (i == this->DefinesByLanguage.end()) {
  181. std::set<std::string> defines;
  182. const char* lang = language.c_str();
  183. // Add preprocessor definitions for this target and configuration.
  184. this->LocalGenerator->GetTargetDefines(this->GeneratorTarget, config,
  185. language, defines);
  186. std::string definesString;
  187. this->LocalGenerator->JoinDefines(defines, definesString, lang);
  188. std::map<std::string, std::string>::value_type entry(language,
  189. definesString);
  190. i = this->DefinesByLanguage.insert(entry).first;
  191. }
  192. return i->second;
  193. }
  194. void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::ostream& fout,
  195. std::string const&,
  196. const std::string& language)
  197. {
  198. std::map<std::string, std::string>::iterator flagsByLangI =
  199. this->FlagsByLanguage.find(language);
  200. if (flagsByLangI != this->FlagsByLanguage.end()) {
  201. if (!flagsByLangI->second.empty()) {
  202. std::vector<std::string> ghsCompFlags =
  203. cmSystemTools::ParseArguments(flagsByLangI->second.c_str());
  204. for (auto& f : ghsCompFlags) {
  205. fout << " " << f << std::endl;
  206. }
  207. }
  208. }
  209. }
  210. void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(
  211. std::ostream& fout, const std::string& config, const std::string& language)
  212. {
  213. std::vector<std::string> compileDefinitions;
  214. this->GeneratorTarget->GetCompileDefinitions(compileDefinitions, config,
  215. language);
  216. for (std::vector<std::string>::const_iterator cdI =
  217. compileDefinitions.begin();
  218. cdI != compileDefinitions.end(); ++cdI) {
  219. fout << " -D" << (*cdI) << std::endl;
  220. }
  221. }
  222. void cmGhsMultiTargetGenerator::WriteIncludes(std::ostream& fout,
  223. const std::string& config,
  224. const std::string& language)
  225. {
  226. std::vector<std::string> includes;
  227. this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
  228. language, config);
  229. for (std::vector<std::string>::const_iterator includes_i = includes.begin();
  230. includes_i != includes.end(); ++includes_i) {
  231. fout << " -I\"" << *includes_i << "\"" << std::endl;
  232. }
  233. }
  234. void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout,
  235. std::string const& config)
  236. {
  237. if (this->TagType == GhsMultiGpj::INTERGRITY_APPLICATION) {
  238. return;
  239. }
  240. std::string linkLibraries;
  241. std::string flags;
  242. std::string linkFlags;
  243. std::string frameworkPath;
  244. std::string linkPath;
  245. std::unique_ptr<cmLinkLineComputer> linkLineComputer(
  246. this->GetGlobalGenerator()->CreateLinkLineComputer(
  247. this->LocalGenerator,
  248. this->LocalGenerator->GetStateSnapshot().GetDirectory()));
  249. this->LocalGenerator->GetTargetFlags(
  250. linkLineComputer.get(), config, linkLibraries, flags, linkFlags,
  251. frameworkPath, linkPath, this->GeneratorTarget);
  252. // write out link options
  253. std::vector<std::string> lopts =
  254. cmSystemTools::ParseArguments(linkFlags.c_str());
  255. for (auto& l : lopts) {
  256. fout << " " << l << std::endl;
  257. }
  258. // write out link search paths
  259. // must be quoted for paths that contain spaces
  260. std::vector<std::string> lpath =
  261. cmSystemTools::ParseArguments(linkPath.c_str());
  262. for (auto& l : lpath) {
  263. fout << " -L\"" << l << "\"" << std::endl;
  264. }
  265. // write out link libs
  266. // must be quoted for filepaths that contains spaces
  267. std::string cbd = this->LocalGenerator->GetCurrentBinaryDirectory();
  268. std::vector<std::string> llibs =
  269. cmSystemTools::ParseArguments(linkLibraries.c_str());
  270. for (auto& l : llibs) {
  271. if (l.compare(0, 2, "-l") == 0) {
  272. fout << " \"" << l << "\"" << std::endl;
  273. } else {
  274. std::string rl = cmSystemTools::CollapseCombinedPath(cbd, l);
  275. fout << " -l\"" << rl << "\"" << std::endl;
  276. }
  277. }
  278. }
  279. void cmGhsMultiTargetGenerator::WriteCustomCommands(std::ostream& fout)
  280. {
  281. WriteCustomCommandsHelper(fout, this->GeneratorTarget->GetPreBuildCommands(),
  282. cmTarget::PRE_BUILD);
  283. WriteCustomCommandsHelper(
  284. fout, this->GeneratorTarget->GetPostBuildCommands(), cmTarget::POST_BUILD);
  285. }
  286. void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
  287. std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet,
  288. cmTarget::CustomCommandType const commandType)
  289. {
  290. for (std::vector<cmCustomCommand>::const_iterator commandsSetI =
  291. commandsSet.begin();
  292. commandsSetI != commandsSet.end(); ++commandsSetI) {
  293. cmCustomCommandLines const& commands = commandsSetI->GetCommandLines();
  294. for (cmCustomCommandLines::const_iterator commandI = commands.begin();
  295. commandI != commands.end(); ++commandI) {
  296. switch (commandType) {
  297. case cmTarget::PRE_BUILD:
  298. fout << " :preexecShellSafe=";
  299. break;
  300. case cmTarget::POST_BUILD:
  301. fout << " :postexecShellSafe=";
  302. break;
  303. default:
  304. assert("Only pre and post are supported");
  305. }
  306. cmCustomCommandLine const& command = *commandI;
  307. for (cmCustomCommandLine::const_iterator commandLineI = command.begin();
  308. commandLineI != command.end(); ++commandLineI) {
  309. std::string subCommandE =
  310. this->LocalGenerator->EscapeForShell(*commandLineI, true);
  311. if (!command.empty()) {
  312. fout << (command.begin() == commandLineI ? "'" : " ");
  313. // Need to double escape backslashes
  314. cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
  315. }
  316. fout << subCommandE;
  317. }
  318. if (!command.empty()) {
  319. fout << "'" << std::endl;
  320. }
  321. }
  322. }
  323. }
  324. void cmGhsMultiTargetGenerator::WriteSourceProperty(std::ostream& fout,
  325. const cmSourceFile* sf,
  326. std::string propName,
  327. std::string propFlag)
  328. {
  329. const char* prop = sf->GetProperty(propName);
  330. if (prop) {
  331. std::vector<std::string> list;
  332. cmSystemTools::ExpandListArgument(prop, list);
  333. for (auto& p : list) {
  334. fout << " " << propFlag << p << std::endl;
  335. }
  336. }
  337. }
  338. void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
  339. {
  340. /* vector of all sources for this target */
  341. std::vector<cmSourceFile*> sources;
  342. this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName);
  343. /* vector of all groups defined for this target
  344. * -- but the vector is not expanded with sub groups or in any useful order
  345. */
  346. std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
  347. /* for each source file assign it to its group */
  348. std::map<std::string, std::vector<cmSourceFile*>> groupFiles;
  349. std::set<std::string> groupNames;
  350. for (auto& sf : sources) {
  351. cmSourceGroup* sourceGroup =
  352. this->Makefile->FindSourceGroup(sf->GetFullPath(), sourceGroups);
  353. std::string gn = sourceGroup->GetFullName();
  354. groupFiles[gn].push_back(sf);
  355. groupNames.insert(gn);
  356. }
  357. /* list of known groups and the order they are displayed in a project file */
  358. const std::vector<std::string> standardGroups = {
  359. "Header Files", "Source Files", "CMake Rules",
  360. "Object Files", "Object Libraries", "Resources"
  361. };
  362. /* list of groups in the order they are displayed in a project file*/
  363. std::vector<std::string> groupFilesList(groupFiles.size());
  364. /* put the groups in the order they should be listed
  365. * - standard groups first, and then everything else
  366. * in the order used by std::map.
  367. */
  368. int i = 0;
  369. for (const std::string& gn : standardGroups) {
  370. auto n = groupNames.find(gn);
  371. if (n != groupNames.end()) {
  372. groupFilesList[i] = *n;
  373. i += 1;
  374. groupNames.erase(gn);
  375. }
  376. }
  377. { /* catch-all group - is last item */
  378. std::string gn = "";
  379. auto n = groupNames.find(gn);
  380. if (n != groupNames.end()) {
  381. groupFilesList.back() = *n;
  382. groupNames.erase(gn);
  383. }
  384. }
  385. for (auto& n : groupNames) {
  386. groupFilesList[i] = n;
  387. i += 1;
  388. }
  389. /* sort the files within each group */
  390. for (auto& n : groupFilesList) {
  391. std::sort(groupFiles[n].begin(), groupFiles[n].end(),
  392. [](cmSourceFile* l, cmSourceFile* r) {
  393. return l->GetFullPath() < r->GetFullPath();
  394. });
  395. }
  396. /* list of open project files */
  397. std::vector<cmGeneratedFileStream*> gfiles;
  398. /* write files into the proper project file
  399. * -- groups go into main project file
  400. * unless FOLDER property or variable is set.
  401. */
  402. for (auto& sg : groupFilesList) {
  403. std::ostream* fout;
  404. bool useProjectFile =
  405. cmSystemTools::IsOn(
  406. this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) ||
  407. cmSystemTools::IsOn(
  408. this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE"));
  409. if (useProjectFile || sg.empty()) {
  410. fout = &fout_proj;
  411. } else {
  412. // Open the filestream in copy-if-different mode.
  413. std::string gname = sg;
  414. cmsys::SystemTools::ReplaceString(gname, "\\", "_");
  415. std::string lpath =
  416. this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
  417. lpath += "/";
  418. lpath += gname;
  419. lpath += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
  420. std::string fpath = this->LocalGenerator->GetCurrentBinaryDirectory();
  421. fpath += "/";
  422. fpath += lpath;
  423. cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath.c_str());
  424. f->SetCopyIfDifferent(true);
  425. gfiles.push_back(f);
  426. fout = f;
  427. this->GetGlobalGenerator()->WriteFileHeader(*f);
  428. GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, *f);
  429. fout_proj << lpath << " ";
  430. GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, fout_proj);
  431. }
  432. if (useProjectFile) {
  433. if (sg.empty()) {
  434. *fout << "{comment} Others" << std::endl;
  435. } else {
  436. *fout << "{comment} " << sg << std::endl;
  437. }
  438. }
  439. /* output rule for each source file */
  440. for (const cmSourceFile* si : groupFiles[sg]) {
  441. // Convert filename to native system
  442. // WORKAROUND: GHS MULTI 6.1.4 and 6.1.6 are known to need backslash on
  443. // windows when opening some files from the search window.
  444. std::string fname(si->GetFullPath());
  445. cmSystemTools::ConvertToOutputSlashes(fname);
  446. *fout << fname << std::endl;
  447. if ("ld" != si->GetExtension() && "int" != si->GetExtension() &&
  448. "bsp" != si->GetExtension()) {
  449. this->WriteObjectLangOverride(*fout, si);
  450. }
  451. this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I");
  452. this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D");
  453. this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", "");
  454. /* to avoid clutter in the gui only print out the objectName if it has
  455. * been renamed */
  456. std::string objectName = this->GeneratorTarget->GetObjectName(si);
  457. if (!objectName.empty() &&
  458. this->GeneratorTarget->HasExplicitObjectName(si)) {
  459. *fout << " -o " << objectName << std::endl;
  460. }
  461. }
  462. }
  463. for (cmGeneratedFileStream* f : gfiles) {
  464. f->Close();
  465. }
  466. }
  467. void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
  468. std::ostream& fout, const cmSourceFile* sourceFile)
  469. {
  470. const char* rawLangProp = sourceFile->GetProperty("LANGUAGE");
  471. if (NULL != rawLangProp) {
  472. std::string sourceLangProp(rawLangProp);
  473. std::string extension(sourceFile->GetExtension());
  474. if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) {
  475. fout << " -dotciscxx" << std::endl;
  476. }
  477. }
  478. }
  479. void cmGhsMultiTargetGenerator::WriteReferences(std::ostream& fout)
  480. {
  481. // This only applies to INTEGRITY Applications
  482. if (this->TagType != GhsMultiGpj::INTERGRITY_APPLICATION) {
  483. return;
  484. }
  485. // Get the targets that this one depends upon
  486. cmTargetDependSet unordered =
  487. this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget);
  488. cmGlobalGhsMultiGenerator::OrderedTargetDependSet ordered(unordered,
  489. this->Name);
  490. for (auto& t : ordered) {
  491. std::string tname = t->GetName();
  492. std::string tpath = t->LocalGenerator->GetCurrentBinaryDirectory();
  493. std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
  494. std::string outpath =
  495. this->LocalGenerator->MaybeConvertToRelativePath(rootpath, tpath) + "/" +
  496. tname + "REF" + cmGlobalGhsMultiGenerator::FILE_EXTENSION;
  497. fout << outpath;
  498. fout << " ";
  499. GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fout);
  500. // Tell the global generator that a refernce project needs to be created
  501. t->Target->SetProperty("GHS_REFERENCE_PROJECT", "ON");
  502. }
  503. }
  504. bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp(void)
  505. {
  506. const char* p = this->GeneratorTarget->GetProperty("ghs_integrity_app");
  507. if (p) {
  508. return cmSystemTools::IsOn(
  509. this->GeneratorTarget->GetProperty("ghs_integrity_app"));
  510. } else {
  511. std::vector<cmSourceFile*> sources;
  512. this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName);
  513. for (auto& sf : sources) {
  514. if ("int" == sf->GetExtension()) {
  515. return true;
  516. }
  517. }
  518. return false;
  519. }
  520. }