cmFileAPICodemodel.cxx 76 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file LICENSE.rst or https://cmake.org/licensing for details. */
  3. #include "cmFileAPICodemodel.h"
  4. #include <algorithm>
  5. #include <cassert>
  6. #include <cstddef>
  7. #include <functional>
  8. #include <limits>
  9. #include <map>
  10. #include <memory>
  11. #include <set>
  12. #include <string>
  13. #include <unordered_map>
  14. #include <utility>
  15. #include <vector>
  16. #include <cm/string_view>
  17. #include <cmext/algorithm>
  18. #include <cmext/string_view>
  19. #include <cm3p/json/value.h>
  20. #include "cmCryptoHash.h"
  21. #include "cmExportSet.h"
  22. #include "cmFileAPI.h"
  23. #include "cmFileSet.h"
  24. #include "cmGenExContext.h"
  25. #include "cmGeneratorExpression.h"
  26. #include "cmGeneratorTarget.h"
  27. #include "cmGlobalGenerator.h"
  28. #include "cmInstallCxxModuleBmiGenerator.h"
  29. #include "cmInstallDirectoryGenerator.h"
  30. #include "cmInstallExportGenerator.h"
  31. #include "cmInstallFileSetGenerator.h"
  32. #include "cmInstallFilesGenerator.h"
  33. #include "cmInstallGenerator.h"
  34. #include "cmInstallGetRuntimeDependenciesGenerator.h"
  35. #include "cmInstallImportedRuntimeArtifactsGenerator.h"
  36. #include "cmInstallRuntimeDependencySet.h"
  37. #include "cmInstallRuntimeDependencySetGenerator.h"
  38. #include "cmInstallScriptGenerator.h"
  39. #include "cmInstallSubdirectoryGenerator.h"
  40. #include "cmInstallTargetGenerator.h"
  41. #include "cmLinkItem.h"
  42. #include "cmLinkLineComputer.h" // IWYU pragma: keep
  43. #include "cmList.h"
  44. #include "cmListFileCache.h"
  45. #include "cmLocalGenerator.h"
  46. #include "cmMakefile.h"
  47. #include "cmMessageType.h"
  48. #include "cmRange.h"
  49. #include "cmSourceFile.h"
  50. #include "cmSourceGroup.h"
  51. #include "cmState.h"
  52. #include "cmStateDirectory.h"
  53. #include "cmStateSnapshot.h"
  54. #include "cmStateTypes.h"
  55. #include "cmStringAlgorithms.h"
  56. #include "cmSystemTools.h"
  57. #include "cmTarget.h"
  58. #include "cmTargetDepend.h"
  59. #include "cmTargetExport.h"
  60. #include "cmValue.h"
  61. #include "cmake.h"
  62. namespace {
  63. using TargetIndexMapType =
  64. std::unordered_map<cmGeneratorTarget const*, Json::ArrayIndex>;
  65. std::string RelativeIfUnder(std::string const& top, std::string const& in)
  66. {
  67. return cmSystemTools::RelativeIfUnder(top, in);
  68. }
  69. class JBTIndex
  70. {
  71. public:
  72. JBTIndex() = default;
  73. explicit operator bool() const { return this->Index != None; }
  74. Json::ArrayIndex Index = None;
  75. static Json::ArrayIndex const None = static_cast<Json::ArrayIndex>(-1);
  76. };
  77. template <typename T>
  78. class JBT
  79. {
  80. public:
  81. JBT(T v = T(), JBTIndex bt = JBTIndex())
  82. : Value(std::move(v))
  83. , Backtrace(bt)
  84. {
  85. }
  86. T Value;
  87. JBTIndex Backtrace;
  88. friend bool operator==(JBT<T> const& l, JBT<T> const& r)
  89. {
  90. return l.Value == r.Value && l.Backtrace.Index == r.Backtrace.Index;
  91. }
  92. static bool ValueEq(JBT<T> const& l, JBT<T> const& r)
  93. {
  94. return l.Value == r.Value;
  95. }
  96. static bool ValueLess(JBT<T> const& l, JBT<T> const& r)
  97. {
  98. return l.Value < r.Value;
  99. }
  100. };
  101. template <typename T>
  102. class JBTs
  103. {
  104. public:
  105. JBTs(T v = T(), std::vector<JBTIndex> ids = std::vector<JBTIndex>())
  106. : Value(std::move(v))
  107. , Backtraces(std::move(ids))
  108. {
  109. }
  110. T Value;
  111. std::vector<JBTIndex> Backtraces;
  112. friend bool operator==(JBTs<T> const& l, JBTs<T> const& r)
  113. {
  114. if ((l.Value == r.Value) && (l.Backtraces.size() == r.Backtraces.size())) {
  115. for (size_t i = 0; i < l.Backtraces.size(); i++) {
  116. if (l.Backtraces[i].Index != r.Backtraces[i].Index) {
  117. return false;
  118. }
  119. }
  120. }
  121. return true;
  122. }
  123. static bool ValueEq(JBTs<T> const& l, JBTs<T> const& r)
  124. {
  125. return l.Value == r.Value;
  126. }
  127. static bool ValueLess(JBTs<T> const& l, JBTs<T> const& r)
  128. {
  129. return l.Value < r.Value;
  130. }
  131. };
  132. class BacktraceData
  133. {
  134. std::string TopSource;
  135. std::unordered_map<std::string, Json::ArrayIndex> CommandMap;
  136. std::unordered_map<std::string, Json::ArrayIndex> FileMap;
  137. std::unordered_map<cmListFileContext const*, Json::ArrayIndex> NodeMap;
  138. Json::Value Commands = Json::arrayValue;
  139. Json::Value Files = Json::arrayValue;
  140. Json::Value Nodes = Json::arrayValue;
  141. Json::ArrayIndex AddCommand(std::string const& command)
  142. {
  143. auto i = this->CommandMap.find(command);
  144. if (i == this->CommandMap.end()) {
  145. auto cmdIndex = static_cast<Json::ArrayIndex>(this->Commands.size());
  146. i = this->CommandMap.emplace(command, cmdIndex).first;
  147. this->Commands.append(command);
  148. }
  149. return i->second;
  150. }
  151. Json::ArrayIndex AddFile(std::string const& file)
  152. {
  153. auto i = this->FileMap.find(file);
  154. if (i == this->FileMap.end()) {
  155. auto fileIndex = static_cast<Json::ArrayIndex>(this->Files.size());
  156. i = this->FileMap.emplace(file, fileIndex).first;
  157. this->Files.append(RelativeIfUnder(this->TopSource, file));
  158. }
  159. return i->second;
  160. }
  161. public:
  162. BacktraceData(std::string topSource);
  163. JBTIndex Add(cmListFileBacktrace const& bt);
  164. Json::Value Dump();
  165. };
  166. BacktraceData::BacktraceData(std::string topSource)
  167. : TopSource(std::move(topSource))
  168. {
  169. }
  170. JBTIndex BacktraceData::Add(cmListFileBacktrace const& bt)
  171. {
  172. JBTIndex index;
  173. if (bt.Empty()) {
  174. return index;
  175. }
  176. cmListFileContext const* top = &bt.Top();
  177. auto found = this->NodeMap.find(top);
  178. if (found != this->NodeMap.end()) {
  179. index.Index = found->second;
  180. return index;
  181. }
  182. Json::Value entry = Json::objectValue;
  183. entry["file"] = this->AddFile(top->FilePath);
  184. if (top->Line) {
  185. entry["line"] = static_cast<int>(top->Line);
  186. }
  187. if (!top->Name.empty()) {
  188. entry["command"] = this->AddCommand(top->Name);
  189. }
  190. if (JBTIndex parent = this->Add(bt.Pop())) {
  191. entry["parent"] = parent.Index;
  192. }
  193. index.Index = this->NodeMap[top] = this->Nodes.size();
  194. this->Nodes.append(std::move(entry)); // NOLINT(*)
  195. return index;
  196. }
  197. Json::Value BacktraceData::Dump()
  198. {
  199. Json::Value backtraceGraph;
  200. this->CommandMap.clear();
  201. this->FileMap.clear();
  202. this->NodeMap.clear();
  203. backtraceGraph["commands"] = std::move(this->Commands);
  204. backtraceGraph["files"] = std::move(this->Files);
  205. backtraceGraph["nodes"] = std::move(this->Nodes);
  206. return backtraceGraph;
  207. }
  208. class Codemodel
  209. {
  210. cmFileAPI& FileAPI;
  211. unsigned int VersionMajor;
  212. unsigned int VersionMinor;
  213. Json::Value DumpPaths();
  214. Json::Value DumpConfigurations();
  215. Json::Value DumpConfiguration(std::string const& config);
  216. public:
  217. Codemodel(cmFileAPI& fileAPI, unsigned int versionMajor,
  218. unsigned int versionMinor);
  219. Json::Value Dump();
  220. };
  221. class CodemodelConfig
  222. {
  223. cmFileAPI& FileAPI;
  224. unsigned int VersionMajor;
  225. unsigned int VersionMinor;
  226. std::string const& Config;
  227. std::string TopSource;
  228. std::string TopBuild;
  229. struct Directory
  230. {
  231. cmStateSnapshot Snapshot;
  232. cmLocalGenerator const* LocalGenerator = nullptr;
  233. Json::Value BuildSystemTargetIndexes = Json::arrayValue;
  234. Json::Value AbstractTargetIndexes = Json::arrayValue;
  235. Json::ArrayIndex ProjectIndex;
  236. bool HasInstallRule = false;
  237. };
  238. std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
  239. DirectoryMap;
  240. std::vector<Directory> Directories;
  241. struct Project
  242. {
  243. cmStateSnapshot Snapshot;
  244. static Json::ArrayIndex const NoParentIndex =
  245. static_cast<Json::ArrayIndex>(-1);
  246. Json::ArrayIndex ParentIndex = NoParentIndex;
  247. Json::Value ChildIndexes = Json::arrayValue;
  248. Json::Value DirectoryIndexes = Json::arrayValue;
  249. Json::Value BuildSystemTargetIndexes = Json::arrayValue;
  250. Json::Value AbstractTargetIndexes = Json::arrayValue;
  251. };
  252. std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
  253. ProjectMap;
  254. std::vector<Project> Projects;
  255. TargetIndexMapType TargetIndexMap;
  256. struct DumpedTargets
  257. {
  258. Json::Value BuildSystemTargets = Json::arrayValue;
  259. Json::Value AbstractTargets = Json::arrayValue;
  260. };
  261. void ProcessDirectories();
  262. Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg);
  263. Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s);
  264. Json::ArrayIndex AddProject(cmStateSnapshot s);
  265. DumpedTargets DumpTargets();
  266. Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti);
  267. Json::Value DumpDirectories();
  268. Json::Value DumpDirectory(Directory& d);
  269. Json::Value DumpDirectoryObject(Directory& d);
  270. Json::Value DumpProjects();
  271. Json::Value DumpProject(Project& p);
  272. Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s);
  273. public:
  274. CodemodelConfig(cmFileAPI& fileAPI, unsigned int versionMajor,
  275. unsigned int versionMinor, std::string const& config);
  276. Json::Value Dump();
  277. };
  278. std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild)
  279. {
  280. cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
  281. std::string path = RelativeIfUnder(
  282. topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
  283. std::string hash = hasher.HashString(path);
  284. hash.resize(20, '0');
  285. return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
  286. }
  287. struct CompileData
  288. {
  289. struct IncludeEntry
  290. {
  291. JBT<std::string> Path;
  292. bool IsSystem = false;
  293. IncludeEntry(JBT<std::string> path, bool isSystem)
  294. : Path(std::move(path))
  295. , IsSystem(isSystem)
  296. {
  297. }
  298. friend bool operator==(IncludeEntry const& l, IncludeEntry const& r)
  299. {
  300. return l.Path == r.Path && l.IsSystem == r.IsSystem;
  301. }
  302. };
  303. std::string Language;
  304. std::string Sysroot;
  305. JBTs<std::string> LanguageStandard;
  306. std::vector<JBT<std::string>> Flags;
  307. std::vector<JBT<std::string>> Defines;
  308. std::vector<JBT<std::string>> PrecompileHeaders;
  309. std::vector<IncludeEntry> Includes;
  310. std::vector<IncludeEntry> Frameworks;
  311. friend bool operator==(CompileData const& l, CompileData const& r)
  312. {
  313. return (l.Language == r.Language && l.Sysroot == r.Sysroot &&
  314. l.Flags == r.Flags && l.Defines == r.Defines &&
  315. l.PrecompileHeaders == r.PrecompileHeaders &&
  316. l.LanguageStandard == r.LanguageStandard &&
  317. l.Includes == r.Includes && l.Frameworks == r.Frameworks);
  318. }
  319. };
  320. }
  321. namespace std {
  322. template <>
  323. struct hash<CompileData>
  324. {
  325. std::size_t operator()(CompileData const& in) const
  326. {
  327. using std::hash;
  328. size_t result =
  329. hash<std::string>()(in.Language) ^ hash<std::string>()(in.Sysroot);
  330. for (auto const& i : in.Includes) {
  331. result = result ^
  332. (hash<std::string>()(i.Path.Value) ^
  333. hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^
  334. (i.IsSystem ? std::numeric_limits<size_t>::max() : 0));
  335. }
  336. for (auto const& i : in.Frameworks) {
  337. result = result ^
  338. (hash<std::string>()(i.Path.Value) ^
  339. hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^
  340. (i.IsSystem ? std::numeric_limits<size_t>::max() : 0));
  341. }
  342. for (auto const& i : in.Flags) {
  343. result = result ^ hash<std::string>()(i.Value) ^
  344. hash<Json::ArrayIndex>()(i.Backtrace.Index);
  345. }
  346. for (auto const& i : in.Defines) {
  347. result = result ^ hash<std::string>()(i.Value) ^
  348. hash<Json::ArrayIndex>()(i.Backtrace.Index);
  349. }
  350. for (auto const& i : in.PrecompileHeaders) {
  351. result = result ^ hash<std::string>()(i.Value) ^
  352. hash<Json::ArrayIndex>()(i.Backtrace.Index);
  353. }
  354. if (!in.LanguageStandard.Value.empty()) {
  355. result = result ^ hash<std::string>()(in.LanguageStandard.Value);
  356. for (JBTIndex backtrace : in.LanguageStandard.Backtraces) {
  357. result = result ^ hash<Json::ArrayIndex>()(backtrace.Index);
  358. }
  359. }
  360. return result;
  361. }
  362. };
  363. } // namespace std
  364. namespace {
  365. class DirectoryObject
  366. {
  367. cmLocalGenerator const* LG = nullptr;
  368. unsigned int VersionMajor;
  369. unsigned int VersionMinor;
  370. std::string const& Config;
  371. TargetIndexMapType& TargetIndexMap;
  372. std::string TopSource;
  373. std::string TopBuild;
  374. BacktraceData Backtraces;
  375. void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);
  376. Json::Value DumpPaths();
  377. Json::Value DumpInstallers();
  378. Json::Value DumpInstaller(cmInstallGenerator* gen);
  379. Json::Value DumpInstallerExportTargets(cmExportSet* exp);
  380. Json::Value DumpInstallerPath(std::string const& top,
  381. std::string const& fromPathIn,
  382. std::string const& toPath);
  383. public:
  384. DirectoryObject(cmLocalGenerator const* lg, unsigned int versionMajor,
  385. unsigned int versionMinor, std::string const& config,
  386. TargetIndexMapType& targetIndexMap);
  387. Json::Value Dump();
  388. };
  389. class Target
  390. {
  391. cmGeneratorTarget* GT;
  392. unsigned int VersionMajor;
  393. unsigned int VersionMinor;
  394. std::string const& Config;
  395. std::string TopSource;
  396. std::string TopBuild;
  397. std::vector<cmSourceGroup> SourceGroupsLocal;
  398. BacktraceData Backtraces;
  399. std::map<std::string, CompileData> CompileDataMap;
  400. std::unordered_map<cmSourceFile const*, Json::ArrayIndex> SourceMap;
  401. Json::Value Sources = Json::arrayValue;
  402. struct SourceGroup
  403. {
  404. std::string Name;
  405. Json::Value SourceIndexes = Json::arrayValue;
  406. };
  407. std::unordered_map<cmSourceGroup const*, Json::ArrayIndex> SourceGroupsMap;
  408. std::vector<SourceGroup> SourceGroups;
  409. struct CompileGroup
  410. {
  411. std::unordered_map<CompileData, Json::ArrayIndex>::iterator Entry;
  412. Json::Value SourceIndexes = Json::arrayValue;
  413. };
  414. std::unordered_map<CompileData, Json::ArrayIndex> CompileGroupMap;
  415. std::vector<CompileGroup> CompileGroups;
  416. using FileSetDatabase = std::map<std::string, Json::ArrayIndex>;
  417. template <typename T>
  418. JBT<T> ToJBT(BT<T> const& bt)
  419. {
  420. return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace));
  421. }
  422. template <typename T>
  423. JBTs<T> ToJBTs(BTs<T> const& bts)
  424. {
  425. std::vector<JBTIndex> ids;
  426. ids.reserve(bts.Backtraces.size());
  427. for (cmListFileBacktrace const& backtrace : bts.Backtraces) {
  428. ids.emplace_back(this->Backtraces.Add(backtrace));
  429. }
  430. return JBTs<T>(bts.Value, ids);
  431. }
  432. void ProcessLanguages();
  433. void ProcessLanguage(std::string const& lang);
  434. Json::ArrayIndex AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si);
  435. CompileData BuildCompileData(cmSourceFile* sf);
  436. CompileData MergeCompileData(CompileData const& fd);
  437. Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf,
  438. Json::ArrayIndex si);
  439. void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);
  440. void AddBacktrace(Json::Value& object, JBTIndex bt);
  441. Json::Value DumpPaths();
  442. Json::Value DumpCompileData(CompileData const& cd);
  443. Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
  444. Json::Value DumpFramework(CompileData::IncludeEntry const& fw);
  445. Json::Value DumpPrecompileHeader(JBT<std::string> const& header);
  446. Json::Value DumpLanguageStandard(JBTs<std::string> const& standard);
  447. Json::Value DumpDefine(JBT<std::string> const& def);
  448. std::pair<Json::Value, FileSetDatabase> DumpFileSets();
  449. Json::Value DumpFileSet(cmFileSet const* fs,
  450. std::vector<std::string> const& directories);
  451. Json::Value DumpSources(FileSetDatabase const& fsdb);
  452. Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
  453. Json::ArrayIndex si, FileSetDatabase const& fsdb);
  454. Json::Value DumpSourceGroups();
  455. Json::Value DumpSourceGroup(SourceGroup& sg);
  456. Json::Value DumpCompileGroups();
  457. Json::Value DumpCompileGroup(CompileGroup& cg);
  458. Json::Value DumpSysroot(std::string const& path);
  459. Json::Value DumpInstall();
  460. Json::Value DumpInstallPrefix();
  461. Json::Value DumpInstallDestinations();
  462. Json::Value DumpInstallDestination(cmInstallTargetGenerator* itGen);
  463. Json::Value DumpArtifacts();
  464. Json::Value DumpLink();
  465. Json::Value DumpArchive();
  466. Json::Value DumpLinkCommandFragments();
  467. Json::Value DumpCommandFragments(std::vector<JBT<std::string>> const& frags);
  468. Json::Value DumpCommandFragment(JBT<std::string> const& frag,
  469. std::string const& role = std::string());
  470. Json::Value DumpDependencies();
  471. Json::Value DumpDependency(cmTargetDepend const& td);
  472. Json::Value DumpLinkItem(cmLinkItem const& linkItem);
  473. Json::Value DumpLinkImplementationLibraries(cmGeneratorTarget::UseTo usage);
  474. Json::Value DumpLinkInterfaceLibraries(cmGeneratorTarget::UseTo usage);
  475. Json::Value DumpObjectDependencies();
  476. Json::Value DumpOrderDependencies();
  477. Json::Value DumpFolder();
  478. Json::Value DumpLauncher(char const* name, char const* type);
  479. Json::Value DumpLaunchers();
  480. Json::Value DumpDebugger();
  481. public:
  482. Target(cmGeneratorTarget* gt, unsigned int versionMajor,
  483. unsigned int versionMinor, std::string const& config);
  484. Json::Value Dump();
  485. };
  486. Codemodel::Codemodel(cmFileAPI& fileAPI, unsigned int versionMajor,
  487. unsigned int versionMinor)
  488. : FileAPI(fileAPI)
  489. , VersionMajor(versionMajor)
  490. , VersionMinor(versionMinor)
  491. {
  492. }
  493. Json::Value Codemodel::Dump()
  494. {
  495. Json::Value codemodel = Json::objectValue;
  496. codemodel["paths"] = this->DumpPaths();
  497. codemodel["configurations"] = this->DumpConfigurations();
  498. return codemodel;
  499. }
  500. Json::Value Codemodel::DumpPaths()
  501. {
  502. Json::Value paths = Json::objectValue;
  503. paths["source"] = this->FileAPI.GetCMakeInstance()->GetHomeDirectory();
  504. paths["build"] = this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory();
  505. return paths;
  506. }
  507. Json::Value Codemodel::DumpConfigurations()
  508. {
  509. Json::Value configurations = Json::arrayValue;
  510. cmGlobalGenerator* gg =
  511. this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
  512. auto const& makefiles = gg->GetMakefiles();
  513. if (!makefiles.empty()) {
  514. std::vector<std::string> const& configs =
  515. makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
  516. for (std::string const& config : configs) {
  517. configurations.append(this->DumpConfiguration(config));
  518. }
  519. }
  520. return configurations;
  521. }
  522. Json::Value Codemodel::DumpConfiguration(std::string const& config)
  523. {
  524. CodemodelConfig configuration(this->FileAPI, this->VersionMajor,
  525. this->VersionMinor, config);
  526. return configuration.Dump();
  527. }
  528. CodemodelConfig::CodemodelConfig(cmFileAPI& fileAPI, unsigned int versionMajor,
  529. unsigned int versionMinor,
  530. std::string const& config)
  531. : FileAPI(fileAPI)
  532. , VersionMajor(versionMajor)
  533. , VersionMinor(versionMinor)
  534. , Config(config)
  535. , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory())
  536. , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory())
  537. {
  538. }
  539. Json::Value CodemodelConfig::Dump()
  540. {
  541. Json::Value configuration = Json::objectValue;
  542. configuration["name"] = this->Config;
  543. this->ProcessDirectories();
  544. DumpedTargets dumpedTargets = this->DumpTargets();
  545. configuration["targets"] = dumpedTargets.BuildSystemTargets;
  546. configuration["abstractTargets"] = dumpedTargets.AbstractTargets;
  547. configuration["directories"] = this->DumpDirectories();
  548. configuration["projects"] = this->DumpProjects();
  549. return configuration;
  550. }
  551. void CodemodelConfig::ProcessDirectories()
  552. {
  553. cmGlobalGenerator* gg =
  554. this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
  555. auto const& localGens = gg->GetLocalGenerators();
  556. // Add directories in forward order to process parents before children.
  557. this->Directories.reserve(localGens.size());
  558. for (auto const& lg : localGens) {
  559. auto directoryIndex =
  560. static_cast<Json::ArrayIndex>(this->Directories.size());
  561. this->Directories.emplace_back();
  562. Directory& d = this->Directories[directoryIndex];
  563. d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory();
  564. d.LocalGenerator = lg.get();
  565. this->DirectoryMap[d.Snapshot] = directoryIndex;
  566. d.ProjectIndex = this->AddProject(d.Snapshot);
  567. this->Projects[d.ProjectIndex].DirectoryIndexes.append(directoryIndex);
  568. }
  569. // Update directories in reverse order to process children before parents.
  570. for (auto di = this->Directories.rbegin(); di != this->Directories.rend();
  571. ++di) {
  572. Directory& d = *di;
  573. // Accumulate the presence of install rules on the way up.
  574. for (auto const& gen :
  575. d.LocalGenerator->GetMakefile()->GetInstallGenerators()) {
  576. if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen.get())) {
  577. d.HasInstallRule = true;
  578. break;
  579. }
  580. }
  581. if (!d.HasInstallRule) {
  582. for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) {
  583. cmStateSnapshot childDir = child.GetBuildsystemDirectory();
  584. Json::ArrayIndex const childIndex = this->GetDirectoryIndex(childDir);
  585. if (this->Directories[childIndex].HasInstallRule) {
  586. d.HasInstallRule = true;
  587. break;
  588. }
  589. }
  590. }
  591. }
  592. }
  593. Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmLocalGenerator const* lg)
  594. {
  595. return this->GetDirectoryIndex(
  596. lg->GetStateSnapshot().GetBuildsystemDirectory());
  597. }
  598. Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmStateSnapshot s)
  599. {
  600. auto i = this->DirectoryMap.find(s);
  601. assert(i != this->DirectoryMap.end());
  602. return i->second;
  603. }
  604. Json::ArrayIndex CodemodelConfig::AddProject(cmStateSnapshot s)
  605. {
  606. cmStateSnapshot ps = s.GetBuildsystemDirectoryParent();
  607. if (ps.IsValid() && ps.GetProjectName() == s.GetProjectName()) {
  608. // This directory is part of its parent directory project.
  609. Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps);
  610. return this->Directories[parentDirIndex].ProjectIndex;
  611. }
  612. // This directory starts a new project.
  613. auto projectIndex = static_cast<Json::ArrayIndex>(this->Projects.size());
  614. this->Projects.emplace_back();
  615. Project& p = this->Projects[projectIndex];
  616. p.Snapshot = s;
  617. this->ProjectMap[s] = projectIndex;
  618. if (ps.IsValid()) {
  619. Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps);
  620. p.ParentIndex = this->Directories[parentDirIndex].ProjectIndex;
  621. this->Projects[p.ParentIndex].ChildIndexes.append(projectIndex);
  622. }
  623. return projectIndex;
  624. }
  625. CodemodelConfig::DumpedTargets CodemodelConfig::DumpTargets()
  626. {
  627. DumpedTargets dumpedTargets;
  628. std::vector<cmGeneratorTarget*> targetList;
  629. cmGlobalGenerator* gg =
  630. this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
  631. for (auto const& lg : gg->GetLocalGenerators()) {
  632. cm::append(targetList, lg->GetGeneratorTargets());
  633. cm::append(targetList, lg->GetOwnedImportedGeneratorTargets());
  634. }
  635. std::sort(targetList.begin(), targetList.end(),
  636. [](cmGeneratorTarget* l, cmGeneratorTarget* r) {
  637. return l->GetName() < r->GetName();
  638. });
  639. for (cmGeneratorTarget* gt : targetList) {
  640. if (gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
  641. continue;
  642. }
  643. // Ignore targets starting with `__cmake_` as they are internal.
  644. if (cmHasLiteralPrefix(gt->GetName(), "__cmake_")) {
  645. continue;
  646. }
  647. Json::Value& targets = gt->IsInBuildSystem()
  648. ? dumpedTargets.BuildSystemTargets
  649. : dumpedTargets.AbstractTargets;
  650. targets.append(this->DumpTarget(gt, targets.size()));
  651. }
  652. return dumpedTargets;
  653. }
  654. Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt,
  655. Json::ArrayIndex ti)
  656. {
  657. Target t(gt, this->VersionMajor, this->VersionMinor, this->Config);
  658. std::string safeTargetName = gt->GetName();
  659. std::replace(safeTargetName.begin(), safeTargetName.end(), ':', '_');
  660. std::string prefix = "target-" + safeTargetName;
  661. if (!this->Config.empty()) {
  662. prefix += "-" + this->Config;
  663. }
  664. Json::Value target = this->FileAPI.MaybeJsonFile(t.Dump(), prefix);
  665. target["name"] = gt->GetName();
  666. target["id"] = TargetId(gt, this->TopBuild);
  667. // Cross-reference directory containing target.
  668. Json::ArrayIndex di = this->GetDirectoryIndex(gt->GetLocalGenerator());
  669. target["directoryIndex"] = di;
  670. if (gt->IsInBuildSystem()) {
  671. this->Directories[di].BuildSystemTargetIndexes.append(ti);
  672. } else {
  673. this->Directories[di].AbstractTargetIndexes.append(ti);
  674. }
  675. // Cross-reference project containing target.
  676. Json::ArrayIndex pi = this->Directories[di].ProjectIndex;
  677. target["projectIndex"] = pi;
  678. if (gt->IsInBuildSystem()) {
  679. this->Projects[pi].BuildSystemTargetIndexes.append(ti);
  680. } else {
  681. this->Projects[pi].AbstractTargetIndexes.append(ti);
  682. }
  683. this->TargetIndexMap[gt] = ti;
  684. return target;
  685. }
  686. Json::Value CodemodelConfig::DumpDirectories()
  687. {
  688. Json::Value directories = Json::arrayValue;
  689. for (Directory& d : this->Directories) {
  690. directories.append(this->DumpDirectory(d));
  691. }
  692. return directories;
  693. }
  694. Json::Value CodemodelConfig::DumpDirectory(Directory& d)
  695. {
  696. Json::Value directory = this->DumpDirectoryObject(d);
  697. std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource();
  698. directory["source"] = RelativeIfUnder(this->TopSource, sourceDir);
  699. std::string buildDir = d.Snapshot.GetDirectory().GetCurrentBinary();
  700. directory["build"] = RelativeIfUnder(this->TopBuild, buildDir);
  701. cmStateSnapshot parentDir = d.Snapshot.GetBuildsystemDirectoryParent();
  702. if (parentDir.IsValid()) {
  703. directory["parentIndex"] = this->GetDirectoryIndex(parentDir);
  704. }
  705. Json::Value childIndexes = Json::arrayValue;
  706. for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) {
  707. childIndexes.append(
  708. this->GetDirectoryIndex(child.GetBuildsystemDirectory()));
  709. }
  710. if (!childIndexes.empty()) {
  711. directory["childIndexes"] = std::move(childIndexes);
  712. }
  713. directory["projectIndex"] = d.ProjectIndex;
  714. if (!d.BuildSystemTargetIndexes.empty()) {
  715. directory["targetIndexes"] = std::move(d.BuildSystemTargetIndexes);
  716. }
  717. if (!d.AbstractTargetIndexes.empty()) {
  718. directory["abstractTargetIndexes"] = std::move(d.AbstractTargetIndexes);
  719. }
  720. Json::Value minimumCMakeVersion = this->DumpMinimumCMakeVersion(d.Snapshot);
  721. if (!minimumCMakeVersion.isNull()) {
  722. directory["minimumCMakeVersion"] = std::move(minimumCMakeVersion);
  723. }
  724. if (d.HasInstallRule) {
  725. directory["hasInstallRule"] = true;
  726. }
  727. return directory;
  728. }
  729. Json::Value CodemodelConfig::DumpDirectoryObject(Directory& d)
  730. {
  731. std::string prefix = "directory";
  732. std::string sourceDirRel = RelativeIfUnder(
  733. this->TopSource, d.Snapshot.GetDirectory().GetCurrentSource());
  734. std::string buildDirRel = RelativeIfUnder(
  735. this->TopBuild, d.Snapshot.GetDirectory().GetCurrentBinary());
  736. if (!cmSystemTools::FileIsFullPath(buildDirRel)) {
  737. prefix = cmStrCat(prefix, '-', buildDirRel);
  738. } else if (!cmSystemTools::FileIsFullPath(sourceDirRel)) {
  739. prefix = cmStrCat(prefix, '-', sourceDirRel);
  740. }
  741. for (char& c : prefix) {
  742. if (c == '/' || c == '\\') {
  743. c = '.';
  744. }
  745. }
  746. if (!this->Config.empty()) {
  747. prefix += "-" + this->Config;
  748. }
  749. DirectoryObject dir(d.LocalGenerator, this->VersionMajor, this->VersionMinor,
  750. this->Config, this->TargetIndexMap);
  751. return this->FileAPI.MaybeJsonFile(dir.Dump(), prefix);
  752. }
  753. Json::Value CodemodelConfig::DumpProjects()
  754. {
  755. Json::Value projects = Json::arrayValue;
  756. for (Project& p : this->Projects) {
  757. projects.append(this->DumpProject(p));
  758. }
  759. return projects;
  760. }
  761. Json::Value CodemodelConfig::DumpProject(Project& p)
  762. {
  763. Json::Value project = Json::objectValue;
  764. project["name"] = p.Snapshot.GetProjectName();
  765. if (p.ParentIndex != Project::NoParentIndex) {
  766. project["parentIndex"] = p.ParentIndex;
  767. }
  768. if (!p.ChildIndexes.empty()) {
  769. project["childIndexes"] = std::move(p.ChildIndexes);
  770. }
  771. project["directoryIndexes"] = std::move(p.DirectoryIndexes);
  772. if (!p.BuildSystemTargetIndexes.empty()) {
  773. project["targetIndexes"] = std::move(p.BuildSystemTargetIndexes);
  774. }
  775. if (!p.AbstractTargetIndexes.empty()) {
  776. project["abstractTargetIndexes"] = std::move(p.AbstractTargetIndexes);
  777. }
  778. return project;
  779. }
  780. Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
  781. {
  782. Json::Value minimumCMakeVersion;
  783. if (cmValue def = s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
  784. minimumCMakeVersion = Json::objectValue;
  785. minimumCMakeVersion["string"] = *def;
  786. }
  787. return minimumCMakeVersion;
  788. }
  789. DirectoryObject::DirectoryObject(cmLocalGenerator const* lg,
  790. unsigned int versionMajor,
  791. unsigned int versionMinor,
  792. std::string const& config,
  793. TargetIndexMapType& targetIndexMap)
  794. : LG(lg)
  795. , VersionMajor(versionMajor)
  796. , VersionMinor(versionMinor)
  797. , Config(config)
  798. , TargetIndexMap(targetIndexMap)
  799. , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
  800. , TopBuild(
  801. lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
  802. , Backtraces(this->TopSource)
  803. {
  804. }
  805. Json::Value DirectoryObject::Dump()
  806. {
  807. Json::Value directoryObject = Json::objectValue;
  808. directoryObject["codemodelVersion"] =
  809. cmFileAPI::BuildVersion(this->VersionMajor, this->VersionMinor);
  810. directoryObject["paths"] = this->DumpPaths();
  811. directoryObject["installers"] = this->DumpInstallers();
  812. directoryObject["backtraceGraph"] = this->Backtraces.Dump();
  813. return directoryObject;
  814. }
  815. void DirectoryObject::AddBacktrace(Json::Value& object,
  816. cmListFileBacktrace const& bt)
  817. {
  818. if (JBTIndex backtrace = this->Backtraces.Add(bt)) {
  819. object["backtrace"] = backtrace.Index;
  820. }
  821. }
  822. Json::Value DirectoryObject::DumpPaths()
  823. {
  824. Json::Value paths = Json::objectValue;
  825. std::string const& sourceDir = this->LG->GetCurrentSourceDirectory();
  826. paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);
  827. std::string const& buildDir = this->LG->GetCurrentBinaryDirectory();
  828. paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);
  829. return paths;
  830. }
  831. Json::Value DirectoryObject::DumpInstallers()
  832. {
  833. Json::Value installers = Json::arrayValue;
  834. for (auto const& gen : this->LG->GetMakefile()->GetInstallGenerators()) {
  835. Json::Value installer = this->DumpInstaller(gen.get());
  836. if (!installer.empty()) {
  837. installers.append(std::move(installer)); // NOLINT(*)
  838. }
  839. }
  840. return installers;
  841. }
  842. Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
  843. {
  844. assert(gen);
  845. Json::Value installer = Json::objectValue;
  846. // Exclude subdirectory installers and file(GET_RUNTIME_DEPENDENCIES)
  847. // installers. They are implementation details.
  848. if (dynamic_cast<cmInstallSubdirectoryGenerator*>(gen) ||
  849. dynamic_cast<cmInstallGetRuntimeDependenciesGenerator*>(gen)) {
  850. return installer;
  851. }
  852. // Exclude installers not used in this configuration.
  853. if (!gen->InstallsForConfig(this->Config)) {
  854. return installer;
  855. }
  856. // Add fields specific to each kind of install generator.
  857. if (auto* installTarget = dynamic_cast<cmInstallTargetGenerator*>(gen)) {
  858. cmInstallTargetGenerator::Files const& files =
  859. installTarget->GetFiles(this->Config);
  860. if (files.From.empty()) {
  861. return installer;
  862. }
  863. installer["type"] = "target";
  864. installer["destination"] = installTarget->GetDestination(this->Config);
  865. installer["targetId"] =
  866. TargetId(installTarget->GetTarget(), this->TopBuild);
  867. installer["targetIndex"] =
  868. this->TargetIndexMap[installTarget->GetTarget()];
  869. std::string fromDir = files.FromDir;
  870. if (!fromDir.empty()) {
  871. fromDir.push_back('/');
  872. }
  873. std::string toDir = files.ToDir;
  874. if (!toDir.empty()) {
  875. toDir.push_back('/');
  876. }
  877. Json::Value paths = Json::arrayValue;
  878. for (size_t i = 0; i < files.From.size(); ++i) {
  879. std::string const& fromPath = cmStrCat(fromDir, files.From[i]);
  880. std::string const& toPath = cmStrCat(toDir, files.To[i]);
  881. paths.append(this->DumpInstallerPath(this->TopBuild, fromPath, toPath));
  882. }
  883. installer["paths"] = std::move(paths);
  884. if (installTarget->GetOptional()) {
  885. installer["isOptional"] = true;
  886. }
  887. if (installTarget->IsImportLibrary()) {
  888. installer["targetIsImportLibrary"] = true;
  889. }
  890. switch (files.NamelinkMode) {
  891. case cmInstallTargetGenerator::NamelinkModeNone:
  892. break;
  893. case cmInstallTargetGenerator::NamelinkModeOnly:
  894. installer["targetInstallNamelink"] = "only";
  895. break;
  896. case cmInstallTargetGenerator::NamelinkModeSkip:
  897. installer["targetInstallNamelink"] = "skip";
  898. break;
  899. }
  900. // FIXME: Parse FilePermissions to provide structured information.
  901. // FIXME: Thread EXPORT name through from install() call.
  902. } else if (auto* installFiles =
  903. dynamic_cast<cmInstallFilesGenerator*>(gen)) {
  904. std::vector<std::string> const& files =
  905. installFiles->GetFiles(this->Config);
  906. if (files.empty()) {
  907. return installer;
  908. }
  909. installer["type"] = "file";
  910. installer["destination"] = installFiles->GetDestination(this->Config);
  911. Json::Value paths = Json::arrayValue;
  912. std::string const& rename = installFiles->GetRename(this->Config);
  913. if (!rename.empty() && files.size() == 1) {
  914. paths.append(this->DumpInstallerPath(this->TopSource, files[0], rename));
  915. } else {
  916. for (std::string const& file : installFiles->GetFiles(this->Config)) {
  917. paths.append(RelativeIfUnder(this->TopSource, file));
  918. }
  919. }
  920. installer["paths"] = std::move(paths);
  921. if (installFiles->GetOptional()) {
  922. installer["isOptional"] = true;
  923. }
  924. // FIXME: Parse FilePermissions to provide structured information.
  925. } else if (auto* installDir =
  926. dynamic_cast<cmInstallDirectoryGenerator*>(gen)) {
  927. std::vector<std::string> const& dirs =
  928. installDir->GetDirectories(this->Config);
  929. if (dirs.empty()) {
  930. return installer;
  931. }
  932. installer["type"] = "directory";
  933. installer["destination"] = installDir->GetDestination(this->Config);
  934. Json::Value paths = Json::arrayValue;
  935. for (std::string const& dir : dirs) {
  936. if (cmHasLiteralSuffix(dir, "/")) {
  937. paths.append(this->DumpInstallerPath(
  938. this->TopSource, dir.substr(0, dir.size() - 1), "."));
  939. } else {
  940. paths.append(this->DumpInstallerPath(
  941. this->TopSource, dir, cmSystemTools::GetFilenameName(dir)));
  942. }
  943. }
  944. installer["paths"] = std::move(paths);
  945. if (installDir->GetOptional()) {
  946. installer["isOptional"] = true;
  947. }
  948. // FIXME: Parse FilePermissions, DirPermissions, and LiteralArguments.
  949. // to provide structured information.
  950. } else if (auto* installExport =
  951. dynamic_cast<cmInstallExportGenerator*>(gen)) {
  952. installer["type"] = "export";
  953. installer["destination"] = installExport->GetDestination();
  954. cmExportSet* exportSet = installExport->GetExportSet();
  955. installer["exportName"] = exportSet->GetName();
  956. installer["exportTargets"] = this->DumpInstallerExportTargets(exportSet);
  957. Json::Value paths = Json::arrayValue;
  958. paths.append(
  959. RelativeIfUnder(this->TopBuild, installExport->GetMainImportFile()));
  960. installer["paths"] = std::move(paths);
  961. } else if (auto* installScript =
  962. dynamic_cast<cmInstallScriptGenerator*>(gen)) {
  963. if (installScript->IsCode()) {
  964. installer["type"] = "code";
  965. } else {
  966. installer["type"] = "script";
  967. installer["scriptFile"] = RelativeIfUnder(
  968. this->TopSource, installScript->GetScript(this->Config));
  969. }
  970. } else if (auto* installImportedRuntimeArtifacts =
  971. dynamic_cast<cmInstallImportedRuntimeArtifactsGenerator*>(
  972. gen)) {
  973. installer["type"] = "importedRuntimeArtifacts";
  974. installer["destination"] =
  975. installImportedRuntimeArtifacts->GetDestination(this->Config);
  976. if (installImportedRuntimeArtifacts->GetOptional()) {
  977. installer["isOptional"] = true;
  978. }
  979. } else if (auto* installRuntimeDependencySet =
  980. dynamic_cast<cmInstallRuntimeDependencySetGenerator*>(gen)) {
  981. installer["type"] = "runtimeDependencySet";
  982. installer["destination"] =
  983. installRuntimeDependencySet->GetDestination(this->Config);
  984. std::string name(
  985. installRuntimeDependencySet->GetRuntimeDependencySet()->GetName());
  986. if (!name.empty()) {
  987. installer["runtimeDependencySetName"] = name;
  988. }
  989. switch (installRuntimeDependencySet->GetDependencyType()) {
  990. case cmInstallRuntimeDependencySetGenerator::DependencyType::Framework:
  991. installer["runtimeDependencySetType"] = "framework";
  992. break;
  993. case cmInstallRuntimeDependencySetGenerator::DependencyType::Library:
  994. installer["runtimeDependencySetType"] = "library";
  995. break;
  996. }
  997. } else if (auto* installFileSet =
  998. dynamic_cast<cmInstallFileSetGenerator*>(gen)) {
  999. auto const* fileSet = installFileSet->GetFileSet();
  1000. // No fileSet by that name exists for the associated target
  1001. if (!fileSet) {
  1002. return installer;
  1003. }
  1004. installer["type"] = "fileSet";
  1005. installer["destination"] = installFileSet->GetDestination(this->Config);
  1006. auto* target = installFileSet->GetTarget();
  1007. cm::GenEx::Context context(target->LocalGenerator, this->Config);
  1008. auto dirCges = fileSet->CompileDirectoryEntries();
  1009. auto dirs = fileSet->EvaluateDirectoryEntries(dirCges, context, target);
  1010. auto entryCges = fileSet->CompileFileEntries();
  1011. std::map<std::string, std::vector<std::string>> entries;
  1012. for (auto const& entryCge : entryCges) {
  1013. fileSet->EvaluateFileEntry(dirs, entries, entryCge, context, target);
  1014. }
  1015. Json::Value files = Json::arrayValue;
  1016. for (auto const& it : entries) {
  1017. auto dir = it.first;
  1018. if (!dir.empty()) {
  1019. dir += '/';
  1020. }
  1021. for (auto const& file : it.second) {
  1022. files.append(this->DumpInstallerPath(
  1023. this->TopSource, file,
  1024. cmStrCat(dir, cmSystemTools::GetFilenameName(file))));
  1025. }
  1026. }
  1027. installer["paths"] = std::move(files);
  1028. installer["fileSetName"] = fileSet->GetName();
  1029. installer["fileSetType"] = fileSet->GetType();
  1030. installer["fileSetDirectories"] = Json::arrayValue;
  1031. for (auto const& dir : dirs) {
  1032. installer["fileSetDirectories"].append(
  1033. RelativeIfUnder(this->TopSource, dir));
  1034. }
  1035. installer["fileSetTarget"] = Json::objectValue;
  1036. installer["fileSetTarget"]["id"] = TargetId(target, this->TopBuild);
  1037. installer["fileSetTarget"]["index"] = this->TargetIndexMap[target];
  1038. if (installFileSet->GetOptional()) {
  1039. installer["isOptional"] = true;
  1040. }
  1041. } else if (auto* cxxModuleBmi =
  1042. dynamic_cast<cmInstallCxxModuleBmiGenerator*>(gen)) {
  1043. installer["type"] = "cxxModuleBmi";
  1044. installer["destination"] = cxxModuleBmi->GetDestination(this->Config);
  1045. auto const* target = cxxModuleBmi->GetTarget();
  1046. installer["cxxModuleBmiTarget"] = Json::objectValue;
  1047. installer["cxxModuleBmiTarget"]["id"] = TargetId(target, this->TopBuild);
  1048. installer["cxxModuleBmiTarget"]["index"] = this->TargetIndexMap[target];
  1049. // FIXME: Parse FilePermissions.
  1050. // FIXME: Parse MessageLevel.
  1051. if (cxxModuleBmi->GetOptional()) {
  1052. installer["isOptional"] = true;
  1053. }
  1054. }
  1055. // Add fields common to all install generators.
  1056. installer["component"] = gen->GetComponent();
  1057. if (gen->GetExcludeFromAll()) {
  1058. installer["isExcludeFromAll"] = true;
  1059. }
  1060. if (gen->GetAllComponentsFlag()) {
  1061. installer["isForAllComponents"] = true;
  1062. }
  1063. this->AddBacktrace(installer, gen->GetBacktrace());
  1064. return installer;
  1065. }
  1066. Json::Value DirectoryObject::DumpInstallerExportTargets(cmExportSet* exp)
  1067. {
  1068. Json::Value targets = Json::arrayValue;
  1069. for (auto const& targetExport : exp->GetTargetExports()) {
  1070. Json::Value target = Json::objectValue;
  1071. target["id"] = TargetId(targetExport->Target, this->TopBuild);
  1072. target["index"] = this->TargetIndexMap[targetExport->Target];
  1073. targets.append(std::move(target)); // NOLINT(*)
  1074. }
  1075. return targets;
  1076. }
  1077. Json::Value DirectoryObject::DumpInstallerPath(std::string const& top,
  1078. std::string const& fromPathIn,
  1079. std::string const& toPath)
  1080. {
  1081. Json::Value installPath;
  1082. std::string fromPath = RelativeIfUnder(top, fromPathIn);
  1083. // If toPath is the last component of fromPath, use just fromPath.
  1084. if (toPath.find_first_of('/') == std::string::npos &&
  1085. cmHasSuffix(fromPath, toPath) &&
  1086. (fromPath.size() == toPath.size() ||
  1087. fromPath[fromPath.size() - toPath.size() - 1] == '/')) {
  1088. installPath = fromPath;
  1089. } else {
  1090. installPath = Json::objectValue;
  1091. installPath["from"] = fromPath;
  1092. installPath["to"] = toPath;
  1093. }
  1094. return installPath;
  1095. }
  1096. Target::Target(cmGeneratorTarget* gt, unsigned int versionMajor,
  1097. unsigned int versionMinor, std::string const& config)
  1098. : GT(gt)
  1099. , VersionMajor(versionMajor)
  1100. , VersionMinor(versionMinor)
  1101. , Config(config)
  1102. , TopSource(gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
  1103. , TopBuild(
  1104. gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
  1105. , SourceGroupsLocal(this->GT->Makefile->GetSourceGroups())
  1106. , Backtraces(this->TopSource)
  1107. {
  1108. }
  1109. Json::Value Target::Dump()
  1110. {
  1111. Json::Value target = Json::objectValue;
  1112. cmStateEnums::TargetType const type = this->GT->GetType();
  1113. target["codemodelVersion"] =
  1114. cmFileAPI::BuildVersion(this->VersionMajor, this->VersionMinor);
  1115. target["name"] = this->GT->GetName();
  1116. target["type"] = cmState::GetTargetTypeName(type);
  1117. target["id"] = TargetId(this->GT, this->TopBuild);
  1118. if (this->GT->IsImported()) {
  1119. target["imported"] = true;
  1120. if (!this->GT->IsImportedGloballyVisible()) {
  1121. target["local"] = true;
  1122. }
  1123. }
  1124. if (this->GT->IsSymbolic()) {
  1125. target["symbolic"] = true;
  1126. }
  1127. if (!this->GT->IsInBuildSystem()) {
  1128. target["abstract"] = true;
  1129. }
  1130. target["paths"] = this->DumpPaths();
  1131. if (this->GT->Target->GetIsGeneratorProvided()) {
  1132. target["isGeneratorProvided"] = true;
  1133. }
  1134. this->AddBacktrace(target, this->GT->GetBacktrace());
  1135. if (this->GT->Target->GetHaveInstallRule()) {
  1136. target["install"] = this->DumpInstall();
  1137. }
  1138. if (this->GT->HaveWellDefinedOutputFiles()) {
  1139. Json::Value artifacts = this->DumpArtifacts();
  1140. if (!artifacts.empty()) {
  1141. target["artifacts"] = std::move(artifacts);
  1142. }
  1143. }
  1144. if (type == cmStateEnums::EXECUTABLE ||
  1145. type == cmStateEnums::SHARED_LIBRARY ||
  1146. type == cmStateEnums::MODULE_LIBRARY) {
  1147. target["nameOnDisk"] = this->GT->GetFullName(this->Config);
  1148. if (!this->GT->IsImported()) {
  1149. target["link"] = this->DumpLink();
  1150. }
  1151. } else if (type == cmStateEnums::STATIC_LIBRARY) {
  1152. target["nameOnDisk"] = this->GT->GetFullName(this->Config);
  1153. if (!this->GT->IsImported()) {
  1154. target["archive"] = this->DumpArchive();
  1155. }
  1156. }
  1157. if (type == cmStateEnums::EXECUTABLE) {
  1158. Json::Value launchers = this->DumpLaunchers();
  1159. if (!launchers.empty()) {
  1160. target["launchers"] = std::move(launchers);
  1161. }
  1162. }
  1163. if (!this->GT->IsImported()) {
  1164. Json::Value dependencies = this->DumpDependencies();
  1165. if (!dependencies.empty()) {
  1166. target["dependencies"] = dependencies;
  1167. }
  1168. }
  1169. {
  1170. Json::Value linkLibraries =
  1171. this->DumpLinkImplementationLibraries(cmGeneratorTarget::UseTo::Link);
  1172. if (!linkLibraries.empty()) {
  1173. target["linkLibraries"] = std::move(linkLibraries);
  1174. }
  1175. Json::Value ifaceLinkLibraries =
  1176. this->DumpLinkInterfaceLibraries(cmGeneratorTarget::UseTo::Link);
  1177. if (!ifaceLinkLibraries.empty()) {
  1178. target["interfaceLinkLibraries"] = std::move(ifaceLinkLibraries);
  1179. }
  1180. Json::Value compileDependencies =
  1181. this->DumpLinkImplementationLibraries(cmGeneratorTarget::UseTo::Compile);
  1182. if (!compileDependencies.empty()) {
  1183. target["compileDependencies"] = std::move(compileDependencies);
  1184. }
  1185. Json::Value ifaceCompileDependencies =
  1186. this->DumpLinkInterfaceLibraries(cmGeneratorTarget::UseTo::Compile);
  1187. if (!ifaceCompileDependencies.empty()) {
  1188. target["interfaceCompileDependencies"] =
  1189. std::move(ifaceCompileDependencies);
  1190. }
  1191. Json::Value objectDependencies = this->DumpObjectDependencies();
  1192. if (!objectDependencies.empty()) {
  1193. target["objectDependencies"] = std::move(objectDependencies);
  1194. }
  1195. Json::Value orderDependencies = this->DumpOrderDependencies();
  1196. if (!orderDependencies.empty()) {
  1197. target["orderDependencies"] = std::move(orderDependencies);
  1198. }
  1199. if (!this->GT->IsImported()) {
  1200. this->ProcessLanguages();
  1201. }
  1202. auto fileSetInfo = this->DumpFileSets();
  1203. if (!fileSetInfo.first.isNull()) {
  1204. target["fileSets"] = fileSetInfo.first;
  1205. }
  1206. // Even though some types of targets can't have sources, we have to always
  1207. // output a sources array to preserve backward compatibility
  1208. target["sources"] = this->DumpSources(fileSetInfo.second);
  1209. Json::Value folder = this->DumpFolder();
  1210. if (!folder.isNull()) {
  1211. target["folder"] = std::move(folder);
  1212. }
  1213. if (!this->GT->IsImported()) {
  1214. Json::Value sourceGroups = this->DumpSourceGroups();
  1215. if (!sourceGroups.empty()) {
  1216. target["sourceGroups"] = std::move(sourceGroups);
  1217. }
  1218. Json::Value compileGroups = this->DumpCompileGroups();
  1219. if (!compileGroups.empty()) {
  1220. target["compileGroups"] = std::move(compileGroups);
  1221. }
  1222. }
  1223. }
  1224. target["backtraceGraph"] = this->Backtraces.Dump();
  1225. if (!this->GT->IsImported()) {
  1226. Json::Value debugger = this->DumpDebugger();
  1227. if (!debugger.isNull()) {
  1228. target["debugger"] = std::move(debugger);
  1229. }
  1230. }
  1231. return target;
  1232. }
  1233. void Target::ProcessLanguages()
  1234. {
  1235. std::set<std::string> languages;
  1236. this->GT->GetLanguages(languages, this->Config);
  1237. for (std::string const& lang : languages) {
  1238. this->ProcessLanguage(lang);
  1239. }
  1240. }
  1241. void Target::ProcessLanguage(std::string const& lang)
  1242. {
  1243. CompileData& cd = this->CompileDataMap[lang];
  1244. cd.Language = lang;
  1245. if (cmValue sysrootCompile =
  1246. this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
  1247. cd.Sysroot = *sysrootCompile;
  1248. } else if (cmValue sysroot =
  1249. this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
  1250. cd.Sysroot = *sysroot;
  1251. }
  1252. cmLocalGenerator* lg = this->GT->GetLocalGenerator();
  1253. {
  1254. // FIXME: Add flags from end section of ExpandRuleVariable,
  1255. // which may need to be factored out.
  1256. std::vector<BT<std::string>> flags =
  1257. lg->GetTargetCompileFlags(this->GT, this->Config, lang);
  1258. cd.Flags.reserve(flags.size());
  1259. for (const BT<std::string>& f : flags) {
  1260. cd.Flags.emplace_back(this->ToJBT(f));
  1261. }
  1262. }
  1263. std::set<BT<std::string>> defines =
  1264. lg->GetTargetDefines(this->GT, this->Config, lang);
  1265. cd.Defines.reserve(defines.size());
  1266. for (BT<std::string> const& d : defines) {
  1267. cd.Defines.emplace_back(this->ToJBT(d));
  1268. }
  1269. std::vector<BT<std::string>> includePathList =
  1270. lg->GetIncludeDirectories(this->GT, lang, this->Config);
  1271. for (BT<std::string> const& i : includePathList) {
  1272. if (this->GT->IsApple() && cmSystemTools::IsPathToFramework(i.Value)) {
  1273. cd.Frameworks.emplace_back(
  1274. this->ToJBT(i),
  1275. this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
  1276. } else {
  1277. cd.Includes.emplace_back(
  1278. this->ToJBT(i),
  1279. this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
  1280. }
  1281. }
  1282. std::vector<BT<std::string>> precompileHeaders =
  1283. this->GT->GetPrecompileHeaders(this->Config, lang);
  1284. for (BT<std::string> const& pch : precompileHeaders) {
  1285. cd.PrecompileHeaders.emplace_back(this->ToJBT(pch));
  1286. }
  1287. BTs<std::string> const* languageStandard =
  1288. this->GT->GetLanguageStandardProperty(lang, this->Config);
  1289. if (languageStandard) {
  1290. cd.LanguageStandard = this->ToJBTs(*languageStandard);
  1291. }
  1292. }
  1293. Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si)
  1294. {
  1295. auto i = this->SourceGroupsMap.find(sg);
  1296. if (i == this->SourceGroupsMap.end()) {
  1297. auto sgIndex = static_cast<Json::ArrayIndex>(this->SourceGroups.size());
  1298. i = this->SourceGroupsMap.emplace(sg, sgIndex).first;
  1299. SourceGroup g;
  1300. g.Name = sg->GetFullName();
  1301. this->SourceGroups.push_back(std::move(g));
  1302. }
  1303. this->SourceGroups[i->second].SourceIndexes.append(si);
  1304. return i->second;
  1305. }
  1306. CompileData Target::BuildCompileData(cmSourceFile* sf)
  1307. {
  1308. CompileData fd;
  1309. fd.Language = sf->GetOrDetermineLanguage();
  1310. if (fd.Language.empty()) {
  1311. return fd;
  1312. }
  1313. cmLocalGenerator* lg = this->GT->GetLocalGenerator();
  1314. cmGeneratorExpressionInterpreter genexInterpreter(lg, this->Config, this->GT,
  1315. fd.Language);
  1316. std::string const COMPILE_FLAGS("COMPILE_FLAGS");
  1317. if (cmValue cflags = sf->GetProperty(COMPILE_FLAGS)) {
  1318. std::string flags = genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS);
  1319. fd.Flags.emplace_back(std::move(flags), JBTIndex());
  1320. }
  1321. std::string const COMPILE_OPTIONS("COMPILE_OPTIONS");
  1322. for (BT<std::string> tmpOpt : sf->GetCompileOptions()) {
  1323. tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS);
  1324. // After generator evaluation we need to use the AppendCompileOptions
  1325. // method so we handle situations where backtrace entries have lists
  1326. // and properly escape flags.
  1327. std::string tmp;
  1328. lg->AppendCompileOptions(tmp, tmpOpt.Value);
  1329. BT<std::string> opt(tmp, tmpOpt.Backtrace);
  1330. fd.Flags.emplace_back(this->ToJBT(opt));
  1331. }
  1332. // Add precompile headers compile options.
  1333. std::vector<std::string> pchArchs =
  1334. this->GT->GetPchArchs(this->Config, fd.Language);
  1335. std::unordered_map<std::string, std::string> pchSources;
  1336. for (std::string const& arch : pchArchs) {
  1337. std::string const pchSource =
  1338. this->GT->GetPchSource(this->Config, fd.Language, arch);
  1339. if (!pchSource.empty()) {
  1340. pchSources.insert(std::make_pair(pchSource, arch));
  1341. }
  1342. }
  1343. if (!pchSources.empty() && !sf->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
  1344. std::string pchOptions;
  1345. auto pchIt = pchSources.find(sf->ResolveFullPath());
  1346. if (pchIt != pchSources.end()) {
  1347. pchOptions = this->GT->GetPchCreateCompileOptions(
  1348. this->Config, fd.Language, pchIt->second);
  1349. } else {
  1350. pchOptions =
  1351. this->GT->GetPchUseCompileOptions(this->Config, fd.Language);
  1352. }
  1353. BT<std::string> tmpOpt(pchOptions);
  1354. tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS);
  1355. // After generator evaluation we need to use the AppendCompileOptions
  1356. // method so we handle situations where backtrace entries have lists
  1357. // and properly escape flags.
  1358. std::string tmp;
  1359. lg->AppendCompileOptions(tmp, tmpOpt.Value);
  1360. BT<std::string> opt(tmp, tmpOpt.Backtrace);
  1361. fd.Flags.emplace_back(this->ToJBT(opt));
  1362. }
  1363. // Add include directories from source file properties.
  1364. {
  1365. std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
  1366. for (BT<std::string> tmpInclude : sf->GetIncludeDirectories()) {
  1367. tmpInclude.Value =
  1368. genexInterpreter.Evaluate(tmpInclude.Value, INCLUDE_DIRECTORIES);
  1369. // After generator evaluation we need to use the AppendIncludeDirectories
  1370. // method so we handle situations where backtrace entries have lists.
  1371. std::vector<std::string> tmp;
  1372. lg->AppendIncludeDirectories(tmp, tmpInclude.Value, *sf);
  1373. for (std::string& i : tmp) {
  1374. bool const isSystemInclude =
  1375. this->GT->IsSystemIncludeDirectory(i, this->Config, fd.Language);
  1376. BT<std::string> include(i, tmpInclude.Backtrace);
  1377. if (this->GT->IsApple() && cmSystemTools::IsPathToFramework(i)) {
  1378. fd.Frameworks.emplace_back(this->ToJBT(include), isSystemInclude);
  1379. } else {
  1380. fd.Includes.emplace_back(this->ToJBT(include), isSystemInclude);
  1381. }
  1382. }
  1383. }
  1384. }
  1385. std::string const COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
  1386. std::set<BT<std::string>> fileDefines;
  1387. for (BT<std::string> tmpDef : sf->GetCompileDefinitions()) {
  1388. tmpDef.Value =
  1389. genexInterpreter.Evaluate(tmpDef.Value, COMPILE_DEFINITIONS);
  1390. // After generator evaluation we need to use the AppendDefines method
  1391. // so we handle situations where backtrace entries have lists.
  1392. std::set<std::string> tmp;
  1393. lg->AppendDefines(tmp, tmpDef.Value);
  1394. for (std::string const& i : tmp) {
  1395. BT<std::string> def(i, tmpDef.Backtrace);
  1396. fileDefines.insert(def);
  1397. }
  1398. }
  1399. std::set<std::string> configFileDefines;
  1400. std::string const defPropName =
  1401. "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(this->Config);
  1402. if (cmValue config_defs = sf->GetProperty(defPropName)) {
  1403. lg->AppendDefines(
  1404. configFileDefines,
  1405. genexInterpreter.Evaluate(*config_defs, COMPILE_DEFINITIONS));
  1406. }
  1407. fd.Defines.reserve(fileDefines.size() + configFileDefines.size());
  1408. for (BT<std::string> const& def : fileDefines) {
  1409. fd.Defines.emplace_back(this->ToJBT(def));
  1410. }
  1411. for (std::string const& d : configFileDefines) {
  1412. fd.Defines.emplace_back(d, JBTIndex());
  1413. }
  1414. return fd;
  1415. }
  1416. CompileData Target::MergeCompileData(CompileData const& fd)
  1417. {
  1418. CompileData cd;
  1419. cd.Language = fd.Language;
  1420. if (cd.Language.empty()) {
  1421. return cd;
  1422. }
  1423. CompileData const& td = this->CompileDataMap.at(cd.Language);
  1424. // All compile groups share the sysroot of the target.
  1425. cd.Sysroot = td.Sysroot;
  1426. // All compile groups share the precompile headers of the target.
  1427. cd.PrecompileHeaders = td.PrecompileHeaders;
  1428. // All compile groups share the language standard of the target.
  1429. cd.LanguageStandard = td.LanguageStandard;
  1430. // Use target-wide flags followed by source-specific flags.
  1431. cd.Flags.reserve(td.Flags.size() + fd.Flags.size());
  1432. cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end());
  1433. cd.Flags.insert(cd.Flags.end(), fd.Flags.begin(), fd.Flags.end());
  1434. // Use source-specific includes followed by target-wide includes.
  1435. cd.Includes.reserve(fd.Includes.size() + td.Includes.size());
  1436. cd.Includes.insert(cd.Includes.end(), fd.Includes.begin(),
  1437. fd.Includes.end());
  1438. cd.Includes.insert(cd.Includes.end(), td.Includes.begin(),
  1439. td.Includes.end());
  1440. // Use source-specific frameworks followed by target-wide frameworks.
  1441. cd.Frameworks.reserve(fd.Frameworks.size() + td.Frameworks.size());
  1442. cd.Frameworks.insert(cd.Frameworks.end(), fd.Frameworks.begin(),
  1443. fd.Frameworks.end());
  1444. cd.Frameworks.insert(cd.Frameworks.end(), td.Frameworks.begin(),
  1445. td.Frameworks.end());
  1446. // Use target-wide defines followed by source-specific defines.
  1447. cd.Defines.reserve(td.Defines.size() + fd.Defines.size());
  1448. cd.Defines.insert(cd.Defines.end(), td.Defines.begin(), td.Defines.end());
  1449. cd.Defines.insert(cd.Defines.end(), fd.Defines.begin(), fd.Defines.end());
  1450. // De-duplicate defines.
  1451. std::stable_sort(cd.Defines.begin(), cd.Defines.end(),
  1452. JBT<std::string>::ValueLess);
  1453. auto end = std::unique(cd.Defines.begin(), cd.Defines.end(),
  1454. JBT<std::string>::ValueEq);
  1455. cd.Defines.erase(end, cd.Defines.end());
  1456. return cd;
  1457. }
  1458. Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf,
  1459. Json::ArrayIndex si)
  1460. {
  1461. CompileData compileData = this->BuildCompileData(sf);
  1462. auto i = this->CompileGroupMap.find(compileData);
  1463. if (i == this->CompileGroupMap.end()) {
  1464. Json::ArrayIndex cgIndex =
  1465. static_cast<Json::ArrayIndex>(this->CompileGroups.size());
  1466. i = this->CompileGroupMap.emplace(std::move(compileData), cgIndex).first;
  1467. CompileGroup g;
  1468. g.Entry = i;
  1469. this->CompileGroups.push_back(std::move(g));
  1470. }
  1471. this->CompileGroups[i->second].SourceIndexes.append(si);
  1472. return i->second;
  1473. }
  1474. void Target::AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt)
  1475. {
  1476. if (JBTIndex backtrace = this->Backtraces.Add(bt)) {
  1477. object["backtrace"] = backtrace.Index;
  1478. }
  1479. }
  1480. void Target::AddBacktrace(Json::Value& object, JBTIndex bt)
  1481. {
  1482. if (bt) {
  1483. object["backtrace"] = bt.Index;
  1484. }
  1485. }
  1486. Json::Value Target::DumpPaths()
  1487. {
  1488. Json::Value paths = Json::objectValue;
  1489. cmLocalGenerator* lg = this->GT->GetLocalGenerator();
  1490. std::string const& sourceDir = lg->GetCurrentSourceDirectory();
  1491. paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);
  1492. std::string const& buildDir = lg->GetCurrentBinaryDirectory();
  1493. paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);
  1494. return paths;
  1495. }
  1496. std::pair<Json::Value, Target::FileSetDatabase> Target::DumpFileSets()
  1497. {
  1498. Json::Value fsJson = Json::nullValue;
  1499. FileSetDatabase fsdb;
  1500. // Build the fileset database.
  1501. auto const* tgt = this->GT->Target;
  1502. auto const& fs_names = tgt->GetAllFileSetNames();
  1503. if (!fs_names.empty()) {
  1504. fsJson = Json::arrayValue;
  1505. size_t fsIndex = 0;
  1506. for (auto const& fs_name : fs_names) {
  1507. auto const* fs = tgt->GetFileSet(fs_name);
  1508. if (!fs) {
  1509. this->GT->Makefile->IssueMessage(
  1510. MessageType::INTERNAL_ERROR,
  1511. cmStrCat("Target \"", tgt->GetName(),
  1512. "\" is tracked to have file set \"", fs_name,
  1513. "\", but it was not found."));
  1514. continue;
  1515. }
  1516. cm::GenEx::Context context(this->GT->LocalGenerator, this->Config);
  1517. auto fileEntries = fs->CompileFileEntries();
  1518. auto directoryEntries = fs->CompileDirectoryEntries();
  1519. auto directories =
  1520. fs->EvaluateDirectoryEntries(directoryEntries, context, this->GT);
  1521. fsJson.append(this->DumpFileSet(fs, directories));
  1522. std::map<std::string, std::vector<std::string>> files_per_dirs;
  1523. for (auto const& entry : fileEntries) {
  1524. fs->EvaluateFileEntry(directories, files_per_dirs, entry, context,
  1525. this->GT);
  1526. }
  1527. for (auto const& files_per_dir : files_per_dirs) {
  1528. auto const& dir = files_per_dir.first;
  1529. for (auto const& file : files_per_dir.second) {
  1530. std::string sf_path;
  1531. if (dir.empty()) {
  1532. sf_path = file;
  1533. } else {
  1534. sf_path = cmStrCat(dir, '/', file);
  1535. }
  1536. fsdb[sf_path] = static_cast<Json::ArrayIndex>(fsIndex);
  1537. }
  1538. }
  1539. ++fsIndex;
  1540. }
  1541. }
  1542. return std::make_pair(fsJson, fsdb);
  1543. }
  1544. Json::Value Target::DumpFileSet(cmFileSet const* fs,
  1545. std::vector<std::string> const& directories)
  1546. {
  1547. Json::Value fileSet = Json::objectValue;
  1548. fileSet["name"] = fs->GetName();
  1549. fileSet["type"] = fs->GetType();
  1550. fileSet["visibility"] =
  1551. std::string(cmFileSetVisibilityToName(fs->GetVisibility()));
  1552. Json::Value baseDirs = Json::arrayValue;
  1553. for (auto const& directory : directories) {
  1554. baseDirs.append(RelativeIfUnder(this->TopSource, directory));
  1555. }
  1556. fileSet["baseDirectories"] = baseDirs;
  1557. return fileSet;
  1558. }
  1559. Json::Value Target::DumpSources(FileSetDatabase const& fsdb)
  1560. {
  1561. Json::Value sources = Json::arrayValue;
  1562. cmGeneratorTarget::KindedSources const& kinded =
  1563. this->GT->GetKindedSources(this->Config);
  1564. for (cmGeneratorTarget::SourceAndKind const& sk : kinded.Sources) {
  1565. sources.append(this->DumpSource(sk, sources.size(), fsdb));
  1566. }
  1567. return sources;
  1568. }
  1569. Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
  1570. Json::ArrayIndex si,
  1571. FileSetDatabase const& fsdb)
  1572. {
  1573. Json::Value source = Json::objectValue;
  1574. cmSourceFile* sf = sk.Source.Value;
  1575. std::string const path = sf->ResolveFullPath();
  1576. source["path"] = RelativeIfUnder(this->TopSource, path);
  1577. if (sk.Source.Value->GetIsGenerated()) {
  1578. source["isGenerated"] = true;
  1579. }
  1580. this->AddBacktrace(source, sk.Source.Backtrace);
  1581. auto fsit = fsdb.find(path);
  1582. if (fsit != fsdb.end()) {
  1583. source["fileSetIndex"] = fsit->second;
  1584. }
  1585. if (cmSourceGroup* sg =
  1586. this->GT->Makefile->FindSourceGroup(path, this->SourceGroupsLocal)) {
  1587. source["sourceGroupIndex"] = this->AddSourceGroup(sg, si);
  1588. }
  1589. switch (sk.Kind) {
  1590. case cmGeneratorTarget::SourceKindCxxModuleSource:
  1591. case cmGeneratorTarget::SourceKindObjectSource: {
  1592. source["compileGroupIndex"] =
  1593. this->AddSourceCompileGroup(sk.Source.Value, si);
  1594. } break;
  1595. case cmGeneratorTarget::SourceKindAppManifest:
  1596. case cmGeneratorTarget::SourceKindCertificate:
  1597. case cmGeneratorTarget::SourceKindCustomCommand:
  1598. case cmGeneratorTarget::SourceKindExternalObject:
  1599. case cmGeneratorTarget::SourceKindExtra:
  1600. case cmGeneratorTarget::SourceKindHeader:
  1601. case cmGeneratorTarget::SourceKindIDL:
  1602. case cmGeneratorTarget::SourceKindManifest:
  1603. case cmGeneratorTarget::SourceKindModuleDefinition:
  1604. case cmGeneratorTarget::SourceKindResx:
  1605. case cmGeneratorTarget::SourceKindXaml:
  1606. case cmGeneratorTarget::SourceKindUnityBatched:
  1607. break;
  1608. }
  1609. return source;
  1610. }
  1611. Json::Value Target::DumpCompileData(CompileData const& cd)
  1612. {
  1613. Json::Value result = Json::objectValue;
  1614. if (!cd.Language.empty()) {
  1615. result["language"] = cd.Language;
  1616. }
  1617. if (!cd.Sysroot.empty()) {
  1618. result["sysroot"] = this->DumpSysroot(cd.Sysroot);
  1619. }
  1620. if (!cd.Flags.empty()) {
  1621. result["compileCommandFragments"] = this->DumpCommandFragments(cd.Flags);
  1622. }
  1623. if (!cd.Includes.empty()) {
  1624. Json::Value includes = Json::arrayValue;
  1625. for (auto const& i : cd.Includes) {
  1626. includes.append(this->DumpInclude(i));
  1627. }
  1628. result["includes"] = includes;
  1629. }
  1630. if (!cd.Frameworks.empty()) {
  1631. Json::Value frameworks = Json::arrayValue;
  1632. for (auto const& i : cd.Frameworks) {
  1633. frameworks.append(this->DumpFramework(i));
  1634. }
  1635. result["frameworks"] = frameworks;
  1636. }
  1637. if (!cd.Defines.empty()) {
  1638. Json::Value defines = Json::arrayValue;
  1639. for (JBT<std::string> const& d : cd.Defines) {
  1640. defines.append(this->DumpDefine(d));
  1641. }
  1642. result["defines"] = std::move(defines);
  1643. }
  1644. if (!cd.PrecompileHeaders.empty()) {
  1645. Json::Value precompileHeaders = Json::arrayValue;
  1646. for (JBT<std::string> const& pch : cd.PrecompileHeaders) {
  1647. precompileHeaders.append(this->DumpPrecompileHeader(pch));
  1648. }
  1649. result["precompileHeaders"] = std::move(precompileHeaders);
  1650. }
  1651. if (!cd.LanguageStandard.Value.empty()) {
  1652. result["languageStandard"] =
  1653. this->DumpLanguageStandard(cd.LanguageStandard);
  1654. }
  1655. return result;
  1656. }
  1657. Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc)
  1658. {
  1659. Json::Value include = Json::objectValue;
  1660. include["path"] = inc.Path.Value;
  1661. if (inc.IsSystem) {
  1662. include["isSystem"] = true;
  1663. }
  1664. this->AddBacktrace(include, inc.Path.Backtrace);
  1665. return include;
  1666. }
  1667. Json::Value Target::DumpFramework(CompileData::IncludeEntry const& fw)
  1668. {
  1669. // for now, idem as include
  1670. return this->DumpInclude(fw);
  1671. }
  1672. Json::Value Target::DumpPrecompileHeader(JBT<std::string> const& header)
  1673. {
  1674. Json::Value precompileHeader = Json::objectValue;
  1675. precompileHeader["header"] = header.Value;
  1676. this->AddBacktrace(precompileHeader, header.Backtrace);
  1677. return precompileHeader;
  1678. }
  1679. Json::Value Target::DumpLanguageStandard(JBTs<std::string> const& standard)
  1680. {
  1681. Json::Value languageStandard = Json::objectValue;
  1682. languageStandard["standard"] = standard.Value;
  1683. if (!standard.Backtraces.empty()) {
  1684. Json::Value backtraces = Json::arrayValue;
  1685. for (JBTIndex backtrace : standard.Backtraces) {
  1686. backtraces.append(backtrace.Index);
  1687. }
  1688. languageStandard["backtraces"] = backtraces;
  1689. }
  1690. return languageStandard;
  1691. }
  1692. Json::Value Target::DumpDefine(JBT<std::string> const& def)
  1693. {
  1694. Json::Value define = Json::objectValue;
  1695. define["define"] = def.Value;
  1696. this->AddBacktrace(define, def.Backtrace);
  1697. return define;
  1698. }
  1699. Json::Value Target::DumpSourceGroups()
  1700. {
  1701. Json::Value sourceGroups = Json::arrayValue;
  1702. for (auto& sg : this->SourceGroups) {
  1703. sourceGroups.append(this->DumpSourceGroup(sg));
  1704. }
  1705. return sourceGroups;
  1706. }
  1707. Json::Value Target::DumpSourceGroup(SourceGroup& sg)
  1708. {
  1709. Json::Value group = Json::objectValue;
  1710. group["name"] = sg.Name;
  1711. group["sourceIndexes"] = std::move(sg.SourceIndexes);
  1712. return group;
  1713. }
  1714. Json::Value Target::DumpCompileGroups()
  1715. {
  1716. Json::Value compileGroups = Json::arrayValue;
  1717. for (auto& cg : this->CompileGroups) {
  1718. compileGroups.append(this->DumpCompileGroup(cg));
  1719. }
  1720. return compileGroups;
  1721. }
  1722. Json::Value Target::DumpCompileGroup(CompileGroup& cg)
  1723. {
  1724. Json::Value group =
  1725. this->DumpCompileData(this->MergeCompileData(cg.Entry->first));
  1726. group["sourceIndexes"] = std::move(cg.SourceIndexes);
  1727. return group;
  1728. }
  1729. Json::Value Target::DumpSysroot(std::string const& path)
  1730. {
  1731. Json::Value sysroot = Json::objectValue;
  1732. sysroot["path"] = path;
  1733. return sysroot;
  1734. }
  1735. Json::Value Target::DumpInstall()
  1736. {
  1737. Json::Value install = Json::objectValue;
  1738. install["prefix"] = this->DumpInstallPrefix();
  1739. install["destinations"] = this->DumpInstallDestinations();
  1740. return install;
  1741. }
  1742. Json::Value Target::DumpInstallPrefix()
  1743. {
  1744. Json::Value prefix = Json::objectValue;
  1745. std::string p =
  1746. this->GT->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
  1747. cmSystemTools::ConvertToUnixSlashes(p);
  1748. prefix["path"] = p;
  1749. return prefix;
  1750. }
  1751. Json::Value Target::DumpInstallDestinations()
  1752. {
  1753. Json::Value destinations = Json::arrayValue;
  1754. auto installGens = this->GT->Target->GetInstallGenerators();
  1755. for (auto* itGen : installGens) {
  1756. destinations.append(this->DumpInstallDestination(itGen));
  1757. }
  1758. return destinations;
  1759. }
  1760. Json::Value Target::DumpInstallDestination(cmInstallTargetGenerator* itGen)
  1761. {
  1762. Json::Value destination = Json::objectValue;
  1763. destination["path"] = itGen->GetDestination(this->Config);
  1764. this->AddBacktrace(destination, itGen->GetBacktrace());
  1765. return destination;
  1766. }
  1767. Json::Value Target::DumpArtifacts()
  1768. {
  1769. Json::Value artifacts = Json::arrayValue;
  1770. // Object libraries have only object files as artifacts.
  1771. if (this->GT->GetType() == cmStateEnums::OBJECT_LIBRARY) {
  1772. if (!this->GT->Target->HasKnownObjectFileLocation(nullptr)) {
  1773. return artifacts;
  1774. }
  1775. std::vector<cmSourceFile const*> objectSources;
  1776. this->GT->GetObjectSources(objectSources, this->Config);
  1777. std::string const obj_dir = this->GT->GetObjectDirectory(this->Config);
  1778. for (cmSourceFile const* sf : objectSources) {
  1779. std::string const& obj = this->GT->GetObjectName(sf);
  1780. Json::Value artifact = Json::objectValue;
  1781. artifact["path"] = RelativeIfUnder(this->TopBuild, obj_dir + obj);
  1782. artifacts.append(std::move(artifact)); // NOLINT(*)
  1783. }
  1784. return artifacts;
  1785. }
  1786. // Other target types always have a "main" artifact.
  1787. {
  1788. Json::Value artifact = Json::objectValue;
  1789. artifact["path"] =
  1790. RelativeIfUnder(this->TopBuild,
  1791. this->GT->GetFullPath(
  1792. this->Config, cmStateEnums::RuntimeBinaryArtifact));
  1793. artifacts.append(std::move(artifact)); // NOLINT(*)
  1794. }
  1795. // Add Windows-specific artifacts produced by the linker.
  1796. if (this->GT->HasImportLibrary(this->Config)) {
  1797. Json::Value artifact = Json::objectValue;
  1798. artifact["path"] =
  1799. RelativeIfUnder(this->TopBuild,
  1800. this->GT->GetFullPath(
  1801. this->Config, cmStateEnums::ImportLibraryArtifact));
  1802. artifacts.append(std::move(artifact)); // NOLINT(*)
  1803. }
  1804. if (this->GT->IsDLLPlatform() &&
  1805. this->GT->GetType() != cmStateEnums::STATIC_LIBRARY) {
  1806. cmGeneratorTarget::OutputInfo const* output =
  1807. this->GT->GetOutputInfo(this->Config);
  1808. if (output && !output->PdbDir.empty()) {
  1809. Json::Value artifact = Json::objectValue;
  1810. artifact["path"] = RelativeIfUnder(this->TopBuild,
  1811. output->PdbDir + '/' +
  1812. this->GT->GetPDBName(this->Config));
  1813. artifacts.append(std::move(artifact)); // NOLINT(*)
  1814. }
  1815. }
  1816. return artifacts;
  1817. }
  1818. Json::Value Target::DumpLink()
  1819. {
  1820. Json::Value link = Json::objectValue;
  1821. std::string lang = this->GT->GetLinkerLanguage(this->Config);
  1822. link["language"] = lang;
  1823. {
  1824. Json::Value commandFragments = this->DumpLinkCommandFragments();
  1825. if (!commandFragments.empty()) {
  1826. link["commandFragments"] = std::move(commandFragments);
  1827. }
  1828. }
  1829. if (cmValue sysrootLink =
  1830. this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
  1831. link["sysroot"] = this->DumpSysroot(*sysrootLink);
  1832. } else if (cmValue sysroot =
  1833. this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
  1834. link["sysroot"] = this->DumpSysroot(*sysroot);
  1835. }
  1836. if (this->GT->IsIPOEnabled(lang, this->Config)) {
  1837. link["lto"] = true;
  1838. }
  1839. return link;
  1840. }
  1841. Json::Value Target::DumpArchive()
  1842. {
  1843. Json::Value archive = Json::objectValue;
  1844. {
  1845. // The "link" fragments not relevant to static libraries are empty.
  1846. Json::Value commandFragments = this->DumpLinkCommandFragments();
  1847. if (!commandFragments.empty()) {
  1848. archive["commandFragments"] = std::move(commandFragments);
  1849. }
  1850. }
  1851. std::string lang = this->GT->GetLinkerLanguage(this->Config);
  1852. if (this->GT->IsIPOEnabled(lang, this->Config)) {
  1853. archive["lto"] = true;
  1854. }
  1855. return archive;
  1856. }
  1857. Json::Value Target::DumpLinkCommandFragments()
  1858. {
  1859. Json::Value linkFragments = Json::arrayValue;
  1860. std::string linkLanguageFlags;
  1861. std::vector<BT<std::string>> linkFlags;
  1862. std::string frameworkPath;
  1863. std::vector<BT<std::string>> linkPath;
  1864. std::vector<BT<std::string>> linkLibs;
  1865. cmLocalGenerator* lg = this->GT->GetLocalGenerator();
  1866. cmGlobalGenerator* gg = this->GT->GetGlobalGenerator();
  1867. std::unique_ptr<cmLinkLineComputer> linkLineComputer =
  1868. gg->CreateLinkLineComputer(lg, lg->GetStateSnapshot().GetDirectory());
  1869. lg->GetTargetFlags(linkLineComputer.get(), this->Config, linkLibs,
  1870. linkLanguageFlags, linkFlags, frameworkPath, linkPath,
  1871. this->GT);
  1872. linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
  1873. frameworkPath = cmTrimWhitespace(frameworkPath);
  1874. if (!linkLanguageFlags.empty()) {
  1875. linkFragments.append(
  1876. this->DumpCommandFragment(std::move(linkLanguageFlags), "flags"));
  1877. }
  1878. if (!linkFlags.empty()) {
  1879. for (BT<std::string> frag : linkFlags) {
  1880. frag.Value = cmTrimWhitespace(frag.Value);
  1881. linkFragments.append(
  1882. this->DumpCommandFragment(this->ToJBT(frag), "flags"));
  1883. }
  1884. }
  1885. if (!frameworkPath.empty()) {
  1886. linkFragments.append(
  1887. this->DumpCommandFragment(std::move(frameworkPath), "frameworkPath"));
  1888. }
  1889. if (!linkPath.empty()) {
  1890. for (BT<std::string> frag : linkPath) {
  1891. frag.Value = cmTrimWhitespace(frag.Value);
  1892. linkFragments.append(
  1893. this->DumpCommandFragment(this->ToJBT(frag), "libraryPath"));
  1894. }
  1895. }
  1896. if (!linkLibs.empty()) {
  1897. for (BT<std::string> frag : linkLibs) {
  1898. frag.Value = cmTrimWhitespace(frag.Value);
  1899. linkFragments.append(
  1900. this->DumpCommandFragment(this->ToJBT(frag), "libraries"));
  1901. }
  1902. }
  1903. return linkFragments;
  1904. }
  1905. Json::Value Target::DumpCommandFragments(
  1906. std::vector<JBT<std::string>> const& frags)
  1907. {
  1908. Json::Value commandFragments = Json::arrayValue;
  1909. for (JBT<std::string> const& f : frags) {
  1910. commandFragments.append(this->DumpCommandFragment(f));
  1911. }
  1912. return commandFragments;
  1913. }
  1914. Json::Value Target::DumpCommandFragment(JBT<std::string> const& frag,
  1915. std::string const& role)
  1916. {
  1917. Json::Value fragment = Json::objectValue;
  1918. fragment["fragment"] = frag.Value;
  1919. if (!role.empty()) {
  1920. fragment["role"] = role;
  1921. }
  1922. this->AddBacktrace(fragment, frag.Backtrace);
  1923. return fragment;
  1924. }
  1925. Json::Value Target::DumpDependencies()
  1926. {
  1927. Json::Value dependencies = Json::arrayValue;
  1928. cmGlobalGenerator* gg = this->GT->GetGlobalGenerator();
  1929. for (cmTargetDepend const& td : gg->GetTargetDirectDepends(this->GT)) {
  1930. dependencies.append(this->DumpDependency(td));
  1931. }
  1932. return dependencies;
  1933. }
  1934. Json::Value Target::DumpDependency(cmTargetDepend const& td)
  1935. {
  1936. Json::Value dependency = Json::objectValue;
  1937. dependency["id"] = TargetId(td, this->TopBuild);
  1938. this->AddBacktrace(dependency, td.GetBacktrace());
  1939. return dependency;
  1940. }
  1941. Json::Value Target::DumpLinkItem(cmLinkItem const& linkItem)
  1942. {
  1943. Json::Value itemJson = Json::objectValue;
  1944. if (linkItem.Target) {
  1945. itemJson["id"] = TargetId(linkItem.Target, this->TopBuild);
  1946. } else {
  1947. itemJson["fragment"] = linkItem.AsStr();
  1948. }
  1949. if (linkItem.InterfaceDirectFrom) {
  1950. Json::Value jsonDirectFrom = Json::objectValue;
  1951. jsonDirectFrom["id"] =
  1952. TargetId(linkItem.InterfaceDirectFrom, this->TopBuild);
  1953. itemJson["fromDependency"] = jsonDirectFrom;
  1954. }
  1955. this->AddBacktrace(itemJson, linkItem.Backtrace);
  1956. return itemJson;
  1957. }
  1958. Json::Value Target::DumpLinkImplementationLibraries(
  1959. cmGeneratorTarget::UseTo usage)
  1960. {
  1961. Json::Value jsonLibs = Json::arrayValue;
  1962. cmLinkImplementationLibraries const* implLibs =
  1963. this->GT->GetLinkImplementationLibraries(this->Config, usage);
  1964. if (implLibs) {
  1965. for (cmLinkItem const& linkItem : implLibs->Libraries) {
  1966. // Non-target compile items are never used, so we drop them here too
  1967. if (usage == cmGeneratorTarget::UseTo::Link || linkItem.Target) {
  1968. jsonLibs.append(this->DumpLinkItem(linkItem));
  1969. }
  1970. }
  1971. }
  1972. return jsonLibs;
  1973. }
  1974. Json::Value Target::DumpLinkInterfaceLibraries(cmGeneratorTarget::UseTo usage)
  1975. {
  1976. Json::Value jsonLibs = Json::arrayValue;
  1977. cmLinkInterfaceLibraries const* ifaceLibs =
  1978. this->GT->GetLinkInterfaceLibraries(this->Config, this->GT, usage);
  1979. if (ifaceLibs) {
  1980. for (cmLinkItem const& linkItem : ifaceLibs->Libraries) {
  1981. // Non-target compile items are never used, so we drop them here too
  1982. if (usage == cmGeneratorTarget::UseTo::Link || linkItem.Target) {
  1983. jsonLibs.append(this->DumpLinkItem(linkItem));
  1984. }
  1985. }
  1986. }
  1987. return jsonLibs;
  1988. }
  1989. Json::Value Target::DumpObjectDependencies()
  1990. {
  1991. // Object dependencies are a special case. They cannot be config-specific
  1992. // because they are obtained by matching the pattern $<TARGET_OBJECTS:xxx>
  1993. // against the SOURCES property, and the matcher rejects any cases where
  1994. // "xxx" contains a generator expression. We can't use
  1995. // GetSourceObjectLibraries() either because that also returns object
  1996. // libraries added via LINK_LIBRARIES rather than $<TARGET_OBJECTS:xxx>,
  1997. // and the whole point of orderDependencies is to capture those that are
  1998. // not listed in LINK_LIBRARIES.
  1999. std::vector<BT<cmGeneratorTarget*>> objectLibraries;
  2000. this->GT->GetObjectLibrariesInSources(objectLibraries);
  2001. // We don't want to repeat the same target in the list. We will only
  2002. // retain one backtrace for cases where the same target is added multiple
  2003. // times from different commands. We also need a deterministic ordering,
  2004. // so we can't use cmGeneratorTarget* pointers in a std::set here.
  2005. using TargetIdMap = std::map<std::string, BT<cmGeneratorTarget*>>;
  2006. TargetIdMap uniqueObjectLibraries;
  2007. for (BT<cmGeneratorTarget*> const& target : objectLibraries) {
  2008. uniqueObjectLibraries[TargetId(target.Value, this->TopBuild)] = target;
  2009. }
  2010. Json::Value jsonDependencies = Json::arrayValue;
  2011. for (TargetIdMap::value_type const& idTargetPair : uniqueObjectLibraries) {
  2012. Json::Value jsonDependency = Json::objectValue;
  2013. jsonDependency["id"] = idTargetPair.first;
  2014. this->AddBacktrace(jsonDependency, idTargetPair.second.Backtrace);
  2015. jsonDependencies.append(jsonDependency);
  2016. }
  2017. return jsonDependencies;
  2018. }
  2019. Json::Value Target::DumpOrderDependencies()
  2020. {
  2021. // The generated build systems don't account for per-config dependencies.
  2022. // This is due to limitations of Xcode and/or Visual Studio, which have
  2023. // (or at least once had) no way to express a per-config inter-target
  2024. // dependency.
  2025. Json::Value jsonDependencies = Json::arrayValue;
  2026. for (cmLinkItem const& linkItem : this->GT->GetUtilityItems()) {
  2027. // We don't want to dump dependencies on reserved targets like ZERO_CHECK
  2028. if (linkItem.Target &&
  2029. cmGlobalGenerator::IsReservedTarget(linkItem.Target->GetName())) {
  2030. continue;
  2031. }
  2032. Json::Value jsonDependency = Json::objectValue;
  2033. jsonDependency["id"] = TargetId(linkItem.Target, this->TopBuild);
  2034. this->AddBacktrace(jsonDependency, linkItem.Backtrace);
  2035. jsonDependencies.append(jsonDependency);
  2036. }
  2037. return jsonDependencies;
  2038. }
  2039. Json::Value Target::DumpFolder()
  2040. {
  2041. Json::Value folder;
  2042. if (cmValue f = this->GT->GetProperty("FOLDER")) {
  2043. folder = Json::objectValue;
  2044. folder["name"] = *f;
  2045. }
  2046. return folder;
  2047. }
  2048. Json::Value Target::DumpLauncher(char const* name, char const* type)
  2049. {
  2050. cmValue property = this->GT->GetProperty(name);
  2051. Json::Value launcher;
  2052. if (property) {
  2053. cmLocalGenerator* lg = this->GT->GetLocalGenerator();
  2054. cmGeneratorExpression ge(*lg->GetCMakeInstance());
  2055. cmList commandWithArgs{ ge.Parse(*property)->Evaluate(lg, this->Config) };
  2056. if (!commandWithArgs.empty() && !commandWithArgs[0].empty()) {
  2057. std::string command(commandWithArgs[0]);
  2058. cmSystemTools::ConvertToUnixSlashes(command);
  2059. launcher = Json::objectValue;
  2060. launcher["command"] = RelativeIfUnder(this->TopSource, command);
  2061. launcher["type"] = type;
  2062. Json::Value args;
  2063. for (std::string const& arg : cmMakeRange(commandWithArgs).advance(1)) {
  2064. args.append(arg);
  2065. }
  2066. if (!args.empty()) {
  2067. launcher["arguments"] = std::move(args);
  2068. }
  2069. }
  2070. }
  2071. return launcher;
  2072. }
  2073. Json::Value Target::DumpLaunchers()
  2074. {
  2075. Json::Value launchers;
  2076. {
  2077. Json::Value launcher = DumpLauncher("TEST_LAUNCHER", "test");
  2078. if (!launcher.empty()) {
  2079. launchers.append(std::move(launcher));
  2080. }
  2081. }
  2082. if (this->GT->Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
  2083. Json::Value emulator = DumpLauncher("CROSSCOMPILING_EMULATOR", "emulator");
  2084. if (!emulator.empty()) {
  2085. launchers.append(std::move(emulator));
  2086. }
  2087. }
  2088. return launchers;
  2089. }
  2090. }
  2091. Json::Value Target::DumpDebugger()
  2092. {
  2093. Json::Value debuggerInformation;
  2094. if (cmValue debuggerWorkingDirectory =
  2095. this->GT->GetGlobalGenerator()->GetDebuggerWorkingDirectory(
  2096. this->GT)) {
  2097. debuggerInformation = Json::objectValue;
  2098. debuggerInformation["workingDirectory"] = *debuggerWorkingDirectory;
  2099. }
  2100. return debuggerInformation;
  2101. }
  2102. Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI,
  2103. unsigned int versionMajor,
  2104. unsigned int versionMinor)
  2105. {
  2106. Codemodel codemodel(fileAPI, versionMajor, versionMinor);
  2107. return codemodel.Dump();
  2108. }