cmGeneratorExpressionNode.cxx 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmGeneratorExpressionNode.h"
  4. #include "cmAlgorithms.h"
  5. #include "cmGeneratorExpression.h"
  6. #include "cmGeneratorExpressionContext.h"
  7. #include "cmGeneratorExpressionDAGChecker.h"
  8. #include "cmGeneratorExpressionEvaluator.h"
  9. #include "cmGeneratorTarget.h"
  10. #include "cmGlobalGenerator.h"
  11. #include "cmLinkItem.h"
  12. #include "cmLocalGenerator.h"
  13. #include "cmMakefile.h"
  14. #include "cmOutputConverter.h"
  15. #include "cmPolicies.h"
  16. #include "cmSourceFile.h"
  17. #include "cmStateTypes.h"
  18. #include "cmSystemTools.h"
  19. #include "cmTarget.h"
  20. #include "cm_auto_ptr.hxx"
  21. #include "cmake.h"
  22. #include <algorithm>
  23. #include <assert.h>
  24. #include <cmConfigure.h>
  25. #include <cmsys/RegularExpression.hxx>
  26. #include <cmsys/String.h>
  27. #include <errno.h>
  28. #include <map>
  29. #include <set>
  30. #include <sstream>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <utility>
  34. std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
  35. std::string const& prop, cmLocalGenerator* lg,
  36. cmGeneratorExpressionContext* context, cmGeneratorTarget const* headTarget,
  37. cmGeneratorTarget const* currentTarget,
  38. cmGeneratorExpressionDAGChecker* dagChecker)
  39. {
  40. cmGeneratorExpression ge(context->Backtrace);
  41. CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
  42. cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem);
  43. std::string result =
  44. cge->Evaluate(lg, context->Config, context->Quiet, headTarget,
  45. currentTarget, dagChecker, context->Language);
  46. if (cge->GetHadContextSensitiveCondition()) {
  47. context->HadContextSensitiveCondition = true;
  48. }
  49. if (cge->GetHadHeadSensitiveCondition()) {
  50. context->HadHeadSensitiveCondition = true;
  51. }
  52. return result;
  53. }
  54. static const struct ZeroNode : public cmGeneratorExpressionNode
  55. {
  56. ZeroNode() {}
  57. bool GeneratesContent() const CM_OVERRIDE { return false; }
  58. bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
  59. std::string Evaluate(const std::vector<std::string>& /*parameters*/,
  60. cmGeneratorExpressionContext* /*context*/,
  61. const GeneratorExpressionContent* /*content*/,
  62. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  63. CM_OVERRIDE
  64. {
  65. return std::string();
  66. }
  67. } zeroNode;
  68. static const struct OneNode : public cmGeneratorExpressionNode
  69. {
  70. OneNode() {}
  71. bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
  72. std::string Evaluate(const std::vector<std::string>& parameters,
  73. cmGeneratorExpressionContext* /*context*/,
  74. const GeneratorExpressionContent* /*content*/,
  75. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  76. CM_OVERRIDE
  77. {
  78. return parameters.front();
  79. }
  80. } oneNode;
  81. static const struct OneNode buildInterfaceNode;
  82. static const struct ZeroNode installInterfaceNode;
  83. #define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
  84. static const struct OP##Node : public cmGeneratorExpressionNode \
  85. { \
  86. OP##Node() {} \
  87. virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \
  88. \
  89. std::string Evaluate(const std::vector<std::string>& parameters, \
  90. cmGeneratorExpressionContext* context, \
  91. const GeneratorExpressionContent* content, \
  92. cmGeneratorExpressionDAGChecker*) const \
  93. { \
  94. std::vector<std::string>::const_iterator it = parameters.begin(); \
  95. const std::vector<std::string>::const_iterator end = parameters.end(); \
  96. for (; it != end; ++it) { \
  97. if (*it == #FAILURE_VALUE) { \
  98. return #FAILURE_VALUE; \
  99. } \
  100. if (*it != #SUCCESS_VALUE) { \
  101. reportError(context, content->GetOriginalExpression(), \
  102. "Parameters to $<" #OP \
  103. "> must resolve to either '0' or '1'."); \
  104. return std::string(); \
  105. } \
  106. } \
  107. return #SUCCESS_VALUE; \
  108. } \
  109. } OPNAME;
  110. BOOLEAN_OP_NODE(andNode, AND, 1, 0)
  111. BOOLEAN_OP_NODE(orNode, OR, 0, 1)
  112. #undef BOOLEAN_OP_NODE
  113. static const struct NotNode : public cmGeneratorExpressionNode
  114. {
  115. NotNode() {}
  116. std::string Evaluate(const std::vector<std::string>& parameters,
  117. cmGeneratorExpressionContext* context,
  118. const GeneratorExpressionContent* content,
  119. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  120. CM_OVERRIDE
  121. {
  122. if (*parameters.begin() != "0" && *parameters.begin() != "1") {
  123. reportError(
  124. context, content->GetOriginalExpression(),
  125. "$<NOT> parameter must resolve to exactly one '0' or '1' value.");
  126. return std::string();
  127. }
  128. return *parameters.begin() == "0" ? "1" : "0";
  129. }
  130. } notNode;
  131. static const struct BoolNode : public cmGeneratorExpressionNode
  132. {
  133. BoolNode() {}
  134. int NumExpectedParameters() const CM_OVERRIDE { return 1; }
  135. std::string Evaluate(const std::vector<std::string>& parameters,
  136. cmGeneratorExpressionContext* /*context*/,
  137. const GeneratorExpressionContent* /*content*/,
  138. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  139. CM_OVERRIDE
  140. {
  141. return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
  142. }
  143. } boolNode;
  144. static const struct StrEqualNode : public cmGeneratorExpressionNode
  145. {
  146. StrEqualNode() {}
  147. int NumExpectedParameters() const CM_OVERRIDE { return 2; }
  148. std::string Evaluate(const std::vector<std::string>& parameters,
  149. cmGeneratorExpressionContext* /*context*/,
  150. const GeneratorExpressionContent* /*content*/,
  151. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  152. CM_OVERRIDE
  153. {
  154. return *parameters.begin() == parameters[1] ? "1" : "0";
  155. }
  156. } strEqualNode;
  157. static const struct EqualNode : public cmGeneratorExpressionNode
  158. {
  159. EqualNode() {}
  160. int NumExpectedParameters() const CM_OVERRIDE { return 2; }
  161. std::string Evaluate(const std::vector<std::string>& parameters,
  162. cmGeneratorExpressionContext* context,
  163. const GeneratorExpressionContent* content,
  164. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  165. CM_OVERRIDE
  166. {
  167. char* pEnd;
  168. int base = 0;
  169. bool flipSign = false;
  170. const char* lhs = parameters[0].c_str();
  171. if (cmHasLiteralPrefix(lhs, "0b") || cmHasLiteralPrefix(lhs, "0B")) {
  172. base = 2;
  173. lhs += 2;
  174. }
  175. if (cmHasLiteralPrefix(lhs, "-0b") || cmHasLiteralPrefix(lhs, "-0B")) {
  176. base = 2;
  177. lhs += 3;
  178. flipSign = true;
  179. }
  180. if (cmHasLiteralPrefix(lhs, "+0b") || cmHasLiteralPrefix(lhs, "+0B")) {
  181. base = 2;
  182. lhs += 3;
  183. }
  184. long lnum = strtol(lhs, &pEnd, base);
  185. if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) {
  186. reportError(context, content->GetOriginalExpression(),
  187. "$<EQUAL> parameter " + parameters[0] +
  188. " is not a valid integer.");
  189. return std::string();
  190. }
  191. if (flipSign) {
  192. lnum = -lnum;
  193. }
  194. base = 0;
  195. flipSign = false;
  196. const char* rhs = parameters[1].c_str();
  197. if (cmHasLiteralPrefix(rhs, "0b") || cmHasLiteralPrefix(rhs, "0B")) {
  198. base = 2;
  199. rhs += 2;
  200. }
  201. if (cmHasLiteralPrefix(rhs, "-0b") || cmHasLiteralPrefix(rhs, "-0B")) {
  202. base = 2;
  203. rhs += 3;
  204. flipSign = true;
  205. }
  206. if (cmHasLiteralPrefix(rhs, "+0b") || cmHasLiteralPrefix(rhs, "+0B")) {
  207. base = 2;
  208. rhs += 3;
  209. }
  210. long rnum = strtol(rhs, &pEnd, base);
  211. if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) {
  212. reportError(context, content->GetOriginalExpression(),
  213. "$<EQUAL> parameter " + parameters[1] +
  214. " is not a valid integer.");
  215. return std::string();
  216. }
  217. if (flipSign) {
  218. rnum = -rnum;
  219. }
  220. return lnum == rnum ? "1" : "0";
  221. }
  222. } equalNode;
  223. static const struct LowerCaseNode : public cmGeneratorExpressionNode
  224. {
  225. LowerCaseNode() {}
  226. bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
  227. std::string Evaluate(const std::vector<std::string>& parameters,
  228. cmGeneratorExpressionContext* /*context*/,
  229. const GeneratorExpressionContent* /*content*/,
  230. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  231. CM_OVERRIDE
  232. {
  233. return cmSystemTools::LowerCase(parameters.front());
  234. }
  235. } lowerCaseNode;
  236. static const struct UpperCaseNode : public cmGeneratorExpressionNode
  237. {
  238. UpperCaseNode() {}
  239. bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
  240. std::string Evaluate(const std::vector<std::string>& parameters,
  241. cmGeneratorExpressionContext* /*context*/,
  242. const GeneratorExpressionContent* /*content*/,
  243. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  244. CM_OVERRIDE
  245. {
  246. return cmSystemTools::UpperCase(parameters.front());
  247. }
  248. } upperCaseNode;
  249. static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
  250. {
  251. MakeCIdentifierNode() {}
  252. bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
  253. std::string Evaluate(const std::vector<std::string>& parameters,
  254. cmGeneratorExpressionContext* /*context*/,
  255. const GeneratorExpressionContent* /*content*/,
  256. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  257. CM_OVERRIDE
  258. {
  259. return cmSystemTools::MakeCidentifier(parameters.front());
  260. }
  261. } makeCIdentifierNode;
  262. static const struct Angle_RNode : public cmGeneratorExpressionNode
  263. {
  264. Angle_RNode() {}
  265. int NumExpectedParameters() const CM_OVERRIDE { return 0; }
  266. std::string Evaluate(const std::vector<std::string>& /*parameters*/,
  267. cmGeneratorExpressionContext* /*context*/,
  268. const GeneratorExpressionContent* /*content*/,
  269. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  270. CM_OVERRIDE
  271. {
  272. return ">";
  273. }
  274. } angle_rNode;
  275. static const struct CommaNode : public cmGeneratorExpressionNode
  276. {
  277. CommaNode() {}
  278. int NumExpectedParameters() const CM_OVERRIDE { return 0; }
  279. std::string Evaluate(const std::vector<std::string>& /*parameters*/,
  280. cmGeneratorExpressionContext* /*context*/,
  281. const GeneratorExpressionContent* /*content*/,
  282. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  283. CM_OVERRIDE
  284. {
  285. return ",";
  286. }
  287. } commaNode;
  288. static const struct SemicolonNode : public cmGeneratorExpressionNode
  289. {
  290. SemicolonNode() {}
  291. int NumExpectedParameters() const CM_OVERRIDE { return 0; }
  292. std::string Evaluate(const std::vector<std::string>& /*parameters*/,
  293. cmGeneratorExpressionContext* /*context*/,
  294. const GeneratorExpressionContent* /*content*/,
  295. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  296. CM_OVERRIDE
  297. {
  298. return ";";
  299. }
  300. } semicolonNode;
  301. struct CompilerIdNode : public cmGeneratorExpressionNode
  302. {
  303. CompilerIdNode() {}
  304. int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
  305. std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
  306. cmGeneratorExpressionContext* context,
  307. const GeneratorExpressionContent* content,
  308. cmGeneratorExpressionDAGChecker* /*unused*/,
  309. const std::string& lang) const
  310. {
  311. const char* compilerId = context->LG->GetMakefile()->GetSafeDefinition(
  312. "CMAKE_" + lang + "_COMPILER_ID");
  313. if (parameters.empty()) {
  314. return compilerId ? compilerId : "";
  315. }
  316. static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
  317. if (!compilerIdValidator.find(*parameters.begin())) {
  318. reportError(context, content->GetOriginalExpression(),
  319. "Expression syntax not recognized.");
  320. return std::string();
  321. }
  322. if (!compilerId) {
  323. return parameters.front().empty() ? "1" : "0";
  324. }
  325. if (strcmp(parameters.begin()->c_str(), compilerId) == 0) {
  326. return "1";
  327. }
  328. if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0) {
  329. switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
  330. case cmPolicies::WARN: {
  331. std::ostringstream e;
  332. e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044);
  333. context->LG->GetCMakeInstance()->IssueMessage(
  334. cmake::AUTHOR_WARNING, e.str(), context->Backtrace);
  335. }
  336. case cmPolicies::OLD:
  337. return "1";
  338. case cmPolicies::NEW:
  339. case cmPolicies::REQUIRED_ALWAYS:
  340. case cmPolicies::REQUIRED_IF_USED:
  341. break;
  342. }
  343. }
  344. return "0";
  345. }
  346. };
  347. static const struct CCompilerIdNode : public CompilerIdNode
  348. {
  349. CCompilerIdNode() {}
  350. std::string Evaluate(const std::vector<std::string>& parameters,
  351. cmGeneratorExpressionContext* context,
  352. const GeneratorExpressionContent* content,
  353. cmGeneratorExpressionDAGChecker* dagChecker) const
  354. CM_OVERRIDE
  355. {
  356. if (!context->HeadTarget) {
  357. reportError(
  358. context, content->GetOriginalExpression(),
  359. "$<C_COMPILER_ID> may only be used with binary targets. It may "
  360. "not be used with add_custom_command or add_custom_target.");
  361. return std::string();
  362. }
  363. return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
  364. "C");
  365. }
  366. } cCompilerIdNode;
  367. static const struct CXXCompilerIdNode : public CompilerIdNode
  368. {
  369. CXXCompilerIdNode() {}
  370. std::string Evaluate(const std::vector<std::string>& parameters,
  371. cmGeneratorExpressionContext* context,
  372. const GeneratorExpressionContent* content,
  373. cmGeneratorExpressionDAGChecker* dagChecker) const
  374. CM_OVERRIDE
  375. {
  376. if (!context->HeadTarget) {
  377. reportError(
  378. context, content->GetOriginalExpression(),
  379. "$<CXX_COMPILER_ID> may only be used with binary targets. It may "
  380. "not be used with add_custom_command or add_custom_target.");
  381. return std::string();
  382. }
  383. return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
  384. "CXX");
  385. }
  386. } cxxCompilerIdNode;
  387. struct CompilerVersionNode : public cmGeneratorExpressionNode
  388. {
  389. CompilerVersionNode() {}
  390. int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
  391. std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
  392. cmGeneratorExpressionContext* context,
  393. const GeneratorExpressionContent* content,
  394. cmGeneratorExpressionDAGChecker* /*unused*/,
  395. const std::string& lang) const
  396. {
  397. const char* compilerVersion =
  398. context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
  399. "_COMPILER_VERSION");
  400. if (parameters.empty()) {
  401. return compilerVersion ? compilerVersion : "";
  402. }
  403. static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
  404. if (!compilerIdValidator.find(*parameters.begin())) {
  405. reportError(context, content->GetOriginalExpression(),
  406. "Expression syntax not recognized.");
  407. return std::string();
  408. }
  409. if (!compilerVersion) {
  410. return parameters.front().empty() ? "1" : "0";
  411. }
  412. return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
  413. parameters.begin()->c_str(),
  414. compilerVersion)
  415. ? "1"
  416. : "0";
  417. }
  418. };
  419. static const struct CCompilerVersionNode : public CompilerVersionNode
  420. {
  421. CCompilerVersionNode() {}
  422. std::string Evaluate(const std::vector<std::string>& parameters,
  423. cmGeneratorExpressionContext* context,
  424. const GeneratorExpressionContent* content,
  425. cmGeneratorExpressionDAGChecker* dagChecker) const
  426. CM_OVERRIDE
  427. {
  428. if (!context->HeadTarget) {
  429. reportError(
  430. context, content->GetOriginalExpression(),
  431. "$<C_COMPILER_VERSION> may only be used with binary targets. It "
  432. "may not be used with add_custom_command or add_custom_target.");
  433. return std::string();
  434. }
  435. return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
  436. "C");
  437. }
  438. } cCompilerVersionNode;
  439. static const struct CxxCompilerVersionNode : public CompilerVersionNode
  440. {
  441. CxxCompilerVersionNode() {}
  442. std::string Evaluate(const std::vector<std::string>& parameters,
  443. cmGeneratorExpressionContext* context,
  444. const GeneratorExpressionContent* content,
  445. cmGeneratorExpressionDAGChecker* dagChecker) const
  446. CM_OVERRIDE
  447. {
  448. if (!context->HeadTarget) {
  449. reportError(
  450. context, content->GetOriginalExpression(),
  451. "$<CXX_COMPILER_VERSION> may only be used with binary targets. It "
  452. "may not be used with add_custom_command or add_custom_target.");
  453. return std::string();
  454. }
  455. return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
  456. "CXX");
  457. }
  458. } cxxCompilerVersionNode;
  459. struct PlatformIdNode : public cmGeneratorExpressionNode
  460. {
  461. PlatformIdNode() {}
  462. int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
  463. std::string Evaluate(const std::vector<std::string>& parameters,
  464. cmGeneratorExpressionContext* context,
  465. const GeneratorExpressionContent* /*content*/,
  466. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  467. CM_OVERRIDE
  468. {
  469. const char* platformId =
  470. context->LG->GetMakefile()->GetSafeDefinition("CMAKE_SYSTEM_NAME");
  471. if (parameters.empty()) {
  472. return platformId ? platformId : "";
  473. }
  474. if (!platformId) {
  475. return parameters.front().empty() ? "1" : "0";
  476. }
  477. if (strcmp(parameters.begin()->c_str(), platformId) == 0) {
  478. return "1";
  479. }
  480. return "0";
  481. }
  482. } platformIdNode;
  483. static const struct VersionGreaterNode : public cmGeneratorExpressionNode
  484. {
  485. VersionGreaterNode() {}
  486. int NumExpectedParameters() const CM_OVERRIDE { return 2; }
  487. std::string Evaluate(const std::vector<std::string>& parameters,
  488. cmGeneratorExpressionContext* /*context*/,
  489. const GeneratorExpressionContent* /*content*/,
  490. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  491. CM_OVERRIDE
  492. {
  493. return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
  494. parameters.front().c_str(),
  495. parameters[1].c_str())
  496. ? "1"
  497. : "0";
  498. }
  499. } versionGreaterNode;
  500. static const struct VersionGreaterEqNode : public cmGeneratorExpressionNode
  501. {
  502. VersionGreaterEqNode() {}
  503. int NumExpectedParameters() const CM_OVERRIDE { return 2; }
  504. std::string Evaluate(const std::vector<std::string>& parameters,
  505. cmGeneratorExpressionContext* /*context*/,
  506. const GeneratorExpressionContent* /*content*/,
  507. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  508. CM_OVERRIDE
  509. {
  510. return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
  511. parameters.front().c_str(),
  512. parameters[1].c_str())
  513. ? "1"
  514. : "0";
  515. }
  516. } versionGreaterEqNode;
  517. static const struct VersionLessNode : public cmGeneratorExpressionNode
  518. {
  519. VersionLessNode() {}
  520. int NumExpectedParameters() const CM_OVERRIDE { return 2; }
  521. std::string Evaluate(const std::vector<std::string>& parameters,
  522. cmGeneratorExpressionContext* /*context*/,
  523. const GeneratorExpressionContent* /*content*/,
  524. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  525. CM_OVERRIDE
  526. {
  527. return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
  528. parameters.front().c_str(),
  529. parameters[1].c_str())
  530. ? "1"
  531. : "0";
  532. }
  533. } versionLessNode;
  534. static const struct VersionLessEqNode : public cmGeneratorExpressionNode
  535. {
  536. VersionLessEqNode() {}
  537. int NumExpectedParameters() const CM_OVERRIDE { return 2; }
  538. std::string Evaluate(const std::vector<std::string>& parameters,
  539. cmGeneratorExpressionContext* /*context*/,
  540. const GeneratorExpressionContent* /*content*/,
  541. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  542. CM_OVERRIDE
  543. {
  544. return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS_EQUAL,
  545. parameters.front().c_str(),
  546. parameters[1].c_str())
  547. ? "1"
  548. : "0";
  549. }
  550. } versionLessEqNode;
  551. static const struct VersionEqualNode : public cmGeneratorExpressionNode
  552. {
  553. VersionEqualNode() {}
  554. int NumExpectedParameters() const CM_OVERRIDE { return 2; }
  555. std::string Evaluate(const std::vector<std::string>& parameters,
  556. cmGeneratorExpressionContext* /*context*/,
  557. const GeneratorExpressionContent* /*content*/,
  558. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  559. CM_OVERRIDE
  560. {
  561. return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
  562. parameters.front().c_str(),
  563. parameters[1].c_str())
  564. ? "1"
  565. : "0";
  566. }
  567. } versionEqualNode;
  568. static const struct LinkOnlyNode : public cmGeneratorExpressionNode
  569. {
  570. LinkOnlyNode() {}
  571. std::string Evaluate(const std::vector<std::string>& parameters,
  572. cmGeneratorExpressionContext* context,
  573. const GeneratorExpressionContent* content,
  574. cmGeneratorExpressionDAGChecker* dagChecker) const
  575. CM_OVERRIDE
  576. {
  577. if (!dagChecker) {
  578. reportError(context, content->GetOriginalExpression(),
  579. "$<LINK_ONLY:...> may only be used for linking");
  580. return std::string();
  581. }
  582. if (!dagChecker->GetTransitivePropertiesOnly()) {
  583. return parameters.front();
  584. }
  585. return std::string();
  586. }
  587. } linkOnlyNode;
  588. static const struct ConfigurationNode : public cmGeneratorExpressionNode
  589. {
  590. ConfigurationNode() {}
  591. int NumExpectedParameters() const CM_OVERRIDE { return 0; }
  592. std::string Evaluate(const std::vector<std::string>& /*parameters*/,
  593. cmGeneratorExpressionContext* context,
  594. const GeneratorExpressionContent* /*content*/,
  595. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  596. CM_OVERRIDE
  597. {
  598. context->HadContextSensitiveCondition = true;
  599. return context->Config;
  600. }
  601. } configurationNode;
  602. static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
  603. {
  604. ConfigurationTestNode() {}
  605. int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
  606. std::string Evaluate(const std::vector<std::string>& parameters,
  607. cmGeneratorExpressionContext* context,
  608. const GeneratorExpressionContent* content,
  609. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  610. CM_OVERRIDE
  611. {
  612. if (parameters.empty()) {
  613. return configurationNode.Evaluate(parameters, context, content,
  614. CM_NULLPTR);
  615. }
  616. static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$");
  617. if (!configValidator.find(*parameters.begin())) {
  618. reportError(context, content->GetOriginalExpression(),
  619. "Expression syntax not recognized.");
  620. return std::string();
  621. }
  622. context->HadContextSensitiveCondition = true;
  623. if (context->Config.empty()) {
  624. return parameters.front().empty() ? "1" : "0";
  625. }
  626. if (cmsysString_strcasecmp(parameters.begin()->c_str(),
  627. context->Config.c_str()) == 0) {
  628. return "1";
  629. }
  630. if (context->CurrentTarget && context->CurrentTarget->IsImported()) {
  631. const char* loc = CM_NULLPTR;
  632. const char* imp = CM_NULLPTR;
  633. std::string suffix;
  634. if (context->CurrentTarget->Target->GetMappedConfig(
  635. context->Config, &loc, &imp, suffix)) {
  636. // This imported target has an appropriate location
  637. // for this (possibly mapped) config.
  638. // Check if there is a proper config mapping for the tested config.
  639. std::vector<std::string> mappedConfigs;
  640. std::string mapProp = "MAP_IMPORTED_CONFIG_";
  641. mapProp += cmSystemTools::UpperCase(context->Config);
  642. if (const char* mapValue =
  643. context->CurrentTarget->GetProperty(mapProp)) {
  644. cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
  645. mappedConfigs);
  646. return std::find(mappedConfigs.begin(), mappedConfigs.end(),
  647. cmSystemTools::UpperCase(parameters.front())) !=
  648. mappedConfigs.end()
  649. ? "1"
  650. : "0";
  651. }
  652. }
  653. }
  654. return "0";
  655. }
  656. } configurationTestNode;
  657. static const struct JoinNode : public cmGeneratorExpressionNode
  658. {
  659. JoinNode() {}
  660. int NumExpectedParameters() const CM_OVERRIDE { return 2; }
  661. bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
  662. std::string Evaluate(const std::vector<std::string>& parameters,
  663. cmGeneratorExpressionContext* /*context*/,
  664. const GeneratorExpressionContent* /*content*/,
  665. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  666. CM_OVERRIDE
  667. {
  668. std::vector<std::string> list;
  669. cmSystemTools::ExpandListArgument(parameters.front(), list);
  670. return cmJoin(list, parameters[1]);
  671. }
  672. } joinNode;
  673. static const struct CompileLanguageNode : public cmGeneratorExpressionNode
  674. {
  675. CompileLanguageNode() {}
  676. int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
  677. std::string Evaluate(const std::vector<std::string>& parameters,
  678. cmGeneratorExpressionContext* context,
  679. const GeneratorExpressionContent* content,
  680. cmGeneratorExpressionDAGChecker* dagChecker) const
  681. CM_OVERRIDE
  682. {
  683. if (context->Language.empty()) {
  684. reportError(
  685. context, content->GetOriginalExpression(),
  686. "$<COMPILE_LANGUAGE:...> may only be used to specify include "
  687. "directories compile definitions, compile options and to evaluate "
  688. "components of the file(GENERATE) command.");
  689. return std::string();
  690. }
  691. std::vector<std::string> enabledLanguages;
  692. cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
  693. gg->GetEnabledLanguages(enabledLanguages);
  694. if (!parameters.empty() &&
  695. std::find(enabledLanguages.begin(), enabledLanguages.end(),
  696. parameters.front()) == enabledLanguages.end()) {
  697. reportError(context, content->GetOriginalExpression(),
  698. "$<COMPILE_LANGUAGE:...> Unknown language.");
  699. return std::string();
  700. }
  701. std::string genName = gg->GetName();
  702. if (genName.find("Visual Studio") != std::string::npos) {
  703. reportError(context, content->GetOriginalExpression(),
  704. "$<COMPILE_LANGUAGE:...> may not be used with Visual Studio "
  705. "generators.");
  706. return std::string();
  707. }
  708. if (genName.find("Xcode") != std::string::npos) {
  709. if (dagChecker && (dagChecker->EvaluatingCompileDefinitions() ||
  710. dagChecker->EvaluatingIncludeDirectories())) {
  711. reportError(
  712. context, content->GetOriginalExpression(),
  713. "$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS "
  714. "with the Xcode generator.");
  715. return std::string();
  716. }
  717. } else {
  718. if (genName.find("Makefiles") == std::string::npos &&
  719. genName.find("Ninja") == std::string::npos &&
  720. genName.find("Watcom WMake") == std::string::npos) {
  721. reportError(
  722. context, content->GetOriginalExpression(),
  723. "$<COMPILE_LANGUAGE:...> not supported for this generator.");
  724. return std::string();
  725. }
  726. }
  727. if (parameters.empty()) {
  728. return context->Language;
  729. }
  730. return context->Language == parameters.front() ? "1" : "0";
  731. }
  732. } languageNode;
  733. #define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY
  734. static const char* targetPropertyTransitiveWhitelist[] = {
  735. CM_NULLPTR CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
  736. };
  737. #undef TRANSITIVE_PROPERTY_NAME
  738. template <typename T>
  739. std::string getLinkedTargetsContent(
  740. std::vector<T> const& libraries, cmGeneratorTarget const* target,
  741. cmGeneratorTarget const* headTarget, cmGeneratorExpressionContext* context,
  742. cmGeneratorExpressionDAGChecker* dagChecker,
  743. const std::string& interfacePropertyName)
  744. {
  745. std::string linkedTargetsContent;
  746. std::string sep;
  747. std::string depString;
  748. for (typename std::vector<T>::const_iterator it = libraries.begin();
  749. it != libraries.end(); ++it) {
  750. // Broken code can have a target in its own link interface.
  751. // Don't follow such link interface entries so as not to create a
  752. // self-referencing loop.
  753. if (it->Target && it->Target != target) {
  754. depString += sep + "$<TARGET_PROPERTY:" + it->Target->GetName() + "," +
  755. interfacePropertyName + ">";
  756. sep = ";";
  757. }
  758. }
  759. if (!depString.empty()) {
  760. linkedTargetsContent =
  761. cmGeneratorExpressionNode::EvaluateDependentExpression(
  762. depString, target->GetLocalGenerator(), context, headTarget, target,
  763. dagChecker);
  764. }
  765. linkedTargetsContent =
  766. cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
  767. return linkedTargetsContent;
  768. }
  769. static const struct TargetPropertyNode : public cmGeneratorExpressionNode
  770. {
  771. TargetPropertyNode() {}
  772. // This node handles errors on parameter count itself.
  773. int NumExpectedParameters() const CM_OVERRIDE { return OneOrMoreParameters; }
  774. std::string Evaluate(const std::vector<std::string>& parameters,
  775. cmGeneratorExpressionContext* context,
  776. const GeneratorExpressionContent* content,
  777. cmGeneratorExpressionDAGChecker* dagCheckerParent) const
  778. CM_OVERRIDE
  779. {
  780. if (parameters.size() != 1 && parameters.size() != 2) {
  781. reportError(
  782. context, content->GetOriginalExpression(),
  783. "$<TARGET_PROPERTY:...> expression requires one or two parameters");
  784. return std::string();
  785. }
  786. static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
  787. cmGeneratorTarget const* target = context->HeadTarget;
  788. std::string propertyName = *parameters.begin();
  789. if (parameters.size() == 1) {
  790. context->HadHeadSensitiveCondition = true;
  791. }
  792. if (!target && parameters.size() == 1) {
  793. reportError(
  794. context, content->GetOriginalExpression(),
  795. "$<TARGET_PROPERTY:prop> may only be used with binary targets. "
  796. "It may not be used with add_custom_command or add_custom_target. "
  797. "Specify the target to read a property from using the "
  798. "$<TARGET_PROPERTY:tgt,prop> signature instead.");
  799. return std::string();
  800. }
  801. if (parameters.size() == 2) {
  802. if (parameters.begin()->empty() && parameters[1].empty()) {
  803. reportError(
  804. context, content->GetOriginalExpression(),
  805. "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
  806. "target name and property name.");
  807. return std::string();
  808. }
  809. if (parameters.begin()->empty()) {
  810. reportError(
  811. context, content->GetOriginalExpression(),
  812. "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
  813. "target name.");
  814. return std::string();
  815. }
  816. std::string targetName = parameters.front();
  817. propertyName = parameters[1];
  818. if (!cmGeneratorExpression::IsValidTargetName(targetName)) {
  819. if (!propertyNameValidator.find(propertyName.c_str())) {
  820. ::reportError(context, content->GetOriginalExpression(),
  821. "Target name and property name not supported.");
  822. return std::string();
  823. }
  824. ::reportError(context, content->GetOriginalExpression(),
  825. "Target name not supported.");
  826. return std::string();
  827. }
  828. if (propertyName == "ALIASED_TARGET") {
  829. if (context->LG->GetMakefile()->IsAlias(targetName)) {
  830. if (cmGeneratorTarget* tgt =
  831. context->LG->FindGeneratorTargetToUse(targetName)) {
  832. return tgt->GetName();
  833. }
  834. }
  835. return "";
  836. }
  837. target = context->LG->FindGeneratorTargetToUse(targetName);
  838. if (!target) {
  839. std::ostringstream e;
  840. e << "Target \"" << targetName << "\" not found.";
  841. reportError(context, content->GetOriginalExpression(), e.str());
  842. return std::string();
  843. }
  844. context->AllTargets.insert(target);
  845. }
  846. if (target == context->HeadTarget) {
  847. // Keep track of the properties seen while processing.
  848. // The evaluation of the LINK_LIBRARIES generator expressions
  849. // will check this to ensure that properties have one consistent
  850. // value for all evaluations.
  851. context->SeenTargetProperties.insert(propertyName);
  852. }
  853. if (propertyName == "SOURCES") {
  854. context->SourceSensitiveTargets.insert(target);
  855. }
  856. if (propertyName.empty()) {
  857. reportError(
  858. context, content->GetOriginalExpression(),
  859. "$<TARGET_PROPERTY:...> expression requires a non-empty property "
  860. "name.");
  861. return std::string();
  862. }
  863. if (!propertyNameValidator.find(propertyName)) {
  864. ::reportError(context, content->GetOriginalExpression(),
  865. "Property name not supported.");
  866. return std::string();
  867. }
  868. assert(target);
  869. if (propertyName == "LINKER_LANGUAGE") {
  870. if (target->LinkLanguagePropagatesToDependents() && dagCheckerParent &&
  871. (dagCheckerParent->EvaluatingLinkLibraries() ||
  872. dagCheckerParent->EvaluatingSources())) {
  873. reportError(
  874. context, content->GetOriginalExpression(),
  875. "LINKER_LANGUAGE target property can not be used while evaluating "
  876. "link libraries for a static library");
  877. return std::string();
  878. }
  879. return target->GetLinkerLanguage(context->Config);
  880. }
  881. cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
  882. target->GetName(), propertyName,
  883. content, dagCheckerParent);
  884. switch (dagChecker.Check()) {
  885. case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
  886. dagChecker.ReportError(context, content->GetOriginalExpression());
  887. return std::string();
  888. case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
  889. // No error. We just skip cyclic references.
  890. return std::string();
  891. case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
  892. for (size_t i = 1; i < cmArraySize(targetPropertyTransitiveWhitelist);
  893. ++i) {
  894. if (targetPropertyTransitiveWhitelist[i] == propertyName) {
  895. // No error. We're not going to find anything new here.
  896. return std::string();
  897. }
  898. }
  899. case cmGeneratorExpressionDAGChecker::DAG:
  900. break;
  901. }
  902. const char* prop = target->GetProperty(propertyName);
  903. if (dagCheckerParent) {
  904. if (dagCheckerParent->EvaluatingLinkLibraries()) {
  905. #define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
  906. (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
  907. if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(
  908. TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(clang-tidy)
  909. reportError(
  910. context, content->GetOriginalExpression(),
  911. "$<TARGET_PROPERTY:...> expression in link libraries "
  912. "evaluation depends on target property which is transitive "
  913. "over the link libraries, creating a recursion.");
  914. return std::string();
  915. }
  916. #undef TRANSITIVE_PROPERTY_COMPARE
  917. if (!prop) {
  918. return std::string();
  919. }
  920. } else {
  921. #define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
  922. assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
  923. ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
  924. #undef ASSERT_TRANSITIVE_PROPERTY_METHOD
  925. }
  926. }
  927. std::string linkedTargetsContent;
  928. std::string interfacePropertyName;
  929. bool isInterfaceProperty = false;
  930. #define POPULATE_INTERFACE_PROPERTY_NAME(prop) \
  931. if (propertyName == #prop) { \
  932. interfacePropertyName = "INTERFACE_" #prop; \
  933. } else if (propertyName == "INTERFACE_" #prop) { \
  934. interfacePropertyName = "INTERFACE_" #prop; \
  935. isInterfaceProperty = true; \
  936. } else
  937. CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
  938. // Note that the above macro terminates with an else
  939. /* else */ if (cmHasLiteralPrefix(propertyName.c_str(),
  940. "COMPILE_DEFINITIONS_")) {
  941. cmPolicies::PolicyStatus polSt =
  942. context->LG->GetPolicyStatus(cmPolicies::CMP0043);
  943. if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
  944. interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
  945. }
  946. }
  947. #undef POPULATE_INTERFACE_PROPERTY_NAME
  948. cmGeneratorTarget const* headTarget =
  949. context->HeadTarget && isInterfaceProperty ? context->HeadTarget
  950. : target;
  951. if (isInterfaceProperty) {
  952. if (cmLinkInterfaceLibraries const* iface =
  953. target->GetLinkInterfaceLibraries(context->Config, headTarget,
  954. true)) {
  955. linkedTargetsContent =
  956. getLinkedTargetsContent(iface->Libraries, target, headTarget,
  957. context, &dagChecker, interfacePropertyName);
  958. }
  959. } else if (!interfacePropertyName.empty()) {
  960. if (cmLinkImplementationLibraries const* impl =
  961. target->GetLinkImplementationLibraries(context->Config)) {
  962. linkedTargetsContent =
  963. getLinkedTargetsContent(impl->Libraries, target, target, context,
  964. &dagChecker, interfacePropertyName);
  965. }
  966. }
  967. if (!prop) {
  968. if (target->IsImported() ||
  969. target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
  970. return linkedTargetsContent;
  971. }
  972. if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
  973. context->Config)) {
  974. context->HadContextSensitiveCondition = true;
  975. return target->GetLinkInterfaceDependentBoolProperty(propertyName,
  976. context->Config)
  977. ? "1"
  978. : "0";
  979. }
  980. if (target->IsLinkInterfaceDependentStringProperty(propertyName,
  981. context->Config)) {
  982. context->HadContextSensitiveCondition = true;
  983. const char* propContent =
  984. target->GetLinkInterfaceDependentStringProperty(propertyName,
  985. context->Config);
  986. return propContent ? propContent : "";
  987. }
  988. if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
  989. context->Config)) {
  990. context->HadContextSensitiveCondition = true;
  991. const char* propContent =
  992. target->GetLinkInterfaceDependentNumberMinProperty(propertyName,
  993. context->Config);
  994. return propContent ? propContent : "";
  995. }
  996. if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
  997. context->Config)) {
  998. context->HadContextSensitiveCondition = true;
  999. const char* propContent =
  1000. target->GetLinkInterfaceDependentNumberMaxProperty(propertyName,
  1001. context->Config);
  1002. return propContent ? propContent : "";
  1003. }
  1004. return linkedTargetsContent;
  1005. }
  1006. if (!target->IsImported() && dagCheckerParent &&
  1007. !dagCheckerParent->EvaluatingLinkLibraries()) {
  1008. if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
  1009. context->Config)) {
  1010. context->HadContextSensitiveCondition = true;
  1011. const char* propContent =
  1012. target->GetLinkInterfaceDependentNumberMinProperty(propertyName,
  1013. context->Config);
  1014. return propContent ? propContent : "";
  1015. }
  1016. if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
  1017. context->Config)) {
  1018. context->HadContextSensitiveCondition = true;
  1019. const char* propContent =
  1020. target->GetLinkInterfaceDependentNumberMaxProperty(propertyName,
  1021. context->Config);
  1022. return propContent ? propContent : "";
  1023. }
  1024. }
  1025. if (!interfacePropertyName.empty()) {
  1026. std::string result = this->EvaluateDependentExpression(
  1027. prop, context->LG, context, headTarget, target, &dagChecker);
  1028. if (!linkedTargetsContent.empty()) {
  1029. result += (result.empty() ? "" : ";") + linkedTargetsContent;
  1030. }
  1031. return result;
  1032. }
  1033. return prop;
  1034. }
  1035. } targetPropertyNode;
  1036. static const struct TargetNameNode : public cmGeneratorExpressionNode
  1037. {
  1038. TargetNameNode() {}
  1039. bool GeneratesContent() const CM_OVERRIDE { return true; }
  1040. bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
  1041. bool RequiresLiteralInput() const CM_OVERRIDE { return true; }
  1042. std::string Evaluate(const std::vector<std::string>& parameters,
  1043. cmGeneratorExpressionContext* /*context*/,
  1044. const GeneratorExpressionContent* /*content*/,
  1045. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  1046. CM_OVERRIDE
  1047. {
  1048. return parameters.front();
  1049. }
  1050. int NumExpectedParameters() const CM_OVERRIDE { return 1; }
  1051. } targetNameNode;
  1052. static const struct TargetObjectsNode : public cmGeneratorExpressionNode
  1053. {
  1054. TargetObjectsNode() {}
  1055. std::string Evaluate(const std::vector<std::string>& parameters,
  1056. cmGeneratorExpressionContext* context,
  1057. const GeneratorExpressionContent* content,
  1058. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  1059. CM_OVERRIDE
  1060. {
  1061. if (!context->EvaluateForBuildsystem) {
  1062. std::ostringstream e;
  1063. e << "The evaluation of the TARGET_OBJECTS generator expression "
  1064. "is only suitable for consumption by CMake. It is not suitable "
  1065. "for writing out elsewhere.";
  1066. reportError(context, content->GetOriginalExpression(), e.str());
  1067. return std::string();
  1068. }
  1069. std::string tgtName = parameters.front();
  1070. cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
  1071. if (!gt) {
  1072. std::ostringstream e;
  1073. e << "Objects of target \"" << tgtName
  1074. << "\" referenced but no such target exists.";
  1075. reportError(context, content->GetOriginalExpression(), e.str());
  1076. return std::string();
  1077. }
  1078. if (gt->GetType() != cmStateEnums::OBJECT_LIBRARY) {
  1079. std::ostringstream e;
  1080. e << "Objects of target \"" << tgtName
  1081. << "\" referenced but is not an OBJECT library.";
  1082. reportError(context, content->GetOriginalExpression(), e.str());
  1083. return std::string();
  1084. }
  1085. std::vector<cmSourceFile const*> objectSources;
  1086. gt->GetObjectSources(objectSources, context->Config);
  1087. std::map<cmSourceFile const*, std::string> mapping;
  1088. for (std::vector<cmSourceFile const*>::const_iterator it =
  1089. objectSources.begin();
  1090. it != objectSources.end(); ++it) {
  1091. mapping[*it];
  1092. }
  1093. gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
  1094. std::string obj_dir = gt->ObjectDirectory;
  1095. std::string result;
  1096. const char* sep = "";
  1097. for (std::vector<cmSourceFile const*>::const_iterator it =
  1098. objectSources.begin();
  1099. it != objectSources.end(); ++it) {
  1100. // Find the object file name corresponding to this source file.
  1101. std::map<cmSourceFile const*, std::string>::const_iterator map_it =
  1102. mapping.find(*it);
  1103. // It must exist because we populated the mapping just above.
  1104. assert(!map_it->second.empty());
  1105. result += sep;
  1106. std::string objFile = obj_dir + map_it->second;
  1107. cmSourceFile* sf =
  1108. context->LG->GetMakefile()->GetOrCreateSource(objFile, true);
  1109. sf->SetObjectLibrary(tgtName);
  1110. sf->SetProperty("EXTERNAL_OBJECT", "1");
  1111. result += objFile;
  1112. sep = ";";
  1113. }
  1114. return result;
  1115. }
  1116. } targetObjectsNode;
  1117. static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
  1118. {
  1119. CompileFeaturesNode() {}
  1120. int NumExpectedParameters() const CM_OVERRIDE { return OneOrMoreParameters; }
  1121. std::string Evaluate(const std::vector<std::string>& parameters,
  1122. cmGeneratorExpressionContext* context,
  1123. const GeneratorExpressionContent* content,
  1124. cmGeneratorExpressionDAGChecker* dagChecker) const
  1125. CM_OVERRIDE
  1126. {
  1127. cmGeneratorTarget const* target = context->HeadTarget;
  1128. if (!target) {
  1129. reportError(
  1130. context, content->GetOriginalExpression(),
  1131. "$<COMPILE_FEATURE> may only be used with binary targets. It may "
  1132. "not be used with add_custom_command or add_custom_target.");
  1133. return std::string();
  1134. }
  1135. context->HadHeadSensitiveCondition = true;
  1136. typedef std::map<std::string, std::vector<std::string> > LangMap;
  1137. static LangMap availableFeatures;
  1138. LangMap testedFeatures;
  1139. for (std::vector<std::string>::const_iterator it = parameters.begin();
  1140. it != parameters.end(); ++it) {
  1141. std::string error;
  1142. std::string lang;
  1143. if (!context->LG->GetMakefile()->CompileFeatureKnown(
  1144. context->HeadTarget->Target, *it, lang, &error)) {
  1145. reportError(context, content->GetOriginalExpression(), error);
  1146. return std::string();
  1147. }
  1148. testedFeatures[lang].push_back(*it);
  1149. if (availableFeatures.find(lang) == availableFeatures.end()) {
  1150. const char* featuresKnown =
  1151. context->LG->GetMakefile()->CompileFeaturesAvailable(lang, &error);
  1152. if (!featuresKnown) {
  1153. reportError(context, content->GetOriginalExpression(), error);
  1154. return std::string();
  1155. }
  1156. cmSystemTools::ExpandListArgument(featuresKnown,
  1157. availableFeatures[lang]);
  1158. }
  1159. }
  1160. bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries();
  1161. for (LangMap::const_iterator lit = testedFeatures.begin();
  1162. lit != testedFeatures.end(); ++lit) {
  1163. std::vector<std::string> const& langAvailable =
  1164. availableFeatures[lit->first];
  1165. const char* standardDefault = context->LG->GetMakefile()->GetDefinition(
  1166. "CMAKE_" + lit->first + "_STANDARD_DEFAULT");
  1167. for (std::vector<std::string>::const_iterator it = lit->second.begin();
  1168. it != lit->second.end(); ++it) {
  1169. if (std::find(langAvailable.begin(), langAvailable.end(), *it) ==
  1170. langAvailable.end()) {
  1171. return "0";
  1172. }
  1173. if (standardDefault && !*standardDefault) {
  1174. // This compiler has no notion of language standard levels.
  1175. // All features known for the language are always available.
  1176. continue;
  1177. }
  1178. if (!context->LG->GetMakefile()->HaveStandardAvailable(
  1179. target->Target, lit->first, *it)) {
  1180. if (evalLL) {
  1181. const char* l = target->GetProperty(lit->first + "_STANDARD");
  1182. if (!l) {
  1183. l = standardDefault;
  1184. }
  1185. assert(l);
  1186. context->MaxLanguageStandard[target][lit->first] = l;
  1187. } else {
  1188. return "0";
  1189. }
  1190. }
  1191. }
  1192. }
  1193. return "1";
  1194. }
  1195. } compileFeaturesNode;
  1196. static const char* targetPolicyWhitelist[] = {
  1197. CM_NULLPTR
  1198. #define TARGET_POLICY_STRING(POLICY) , #POLICY
  1199. CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
  1200. #undef TARGET_POLICY_STRING
  1201. };
  1202. cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt,
  1203. const char* policy)
  1204. {
  1205. #define RETURN_POLICY(POLICY) \
  1206. if (strcmp(policy, #POLICY) == 0) { \
  1207. return tgt->GetPolicyStatus##POLICY(); \
  1208. }
  1209. CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
  1210. #undef RETURN_POLICY
  1211. assert(false && "Unreachable code. Not a valid policy");
  1212. return cmPolicies::WARN;
  1213. }
  1214. cmPolicies::PolicyID policyForString(const char* policy_id)
  1215. {
  1216. #define RETURN_POLICY_ID(POLICY_ID) \
  1217. if (strcmp(policy_id, #POLICY_ID) == 0) { \
  1218. return cmPolicies::POLICY_ID; \
  1219. }
  1220. CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
  1221. #undef RETURN_POLICY_ID
  1222. assert(false && "Unreachable code. Not a valid policy");
  1223. return cmPolicies::CMP0002;
  1224. }
  1225. static const struct TargetPolicyNode : public cmGeneratorExpressionNode
  1226. {
  1227. TargetPolicyNode() {}
  1228. int NumExpectedParameters() const CM_OVERRIDE { return 1; }
  1229. std::string Evaluate(const std::vector<std::string>& parameters,
  1230. cmGeneratorExpressionContext* context,
  1231. const GeneratorExpressionContent* content,
  1232. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  1233. CM_OVERRIDE
  1234. {
  1235. if (!context->HeadTarget) {
  1236. reportError(
  1237. context, content->GetOriginalExpression(),
  1238. "$<TARGET_POLICY:prop> may only be used with binary targets. It "
  1239. "may not be used with add_custom_command or add_custom_target.");
  1240. return std::string();
  1241. }
  1242. context->HadContextSensitiveCondition = true;
  1243. context->HadHeadSensitiveCondition = true;
  1244. for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i) {
  1245. const char* policy = targetPolicyWhitelist[i];
  1246. if (parameters.front() == policy) {
  1247. cmLocalGenerator* lg = context->HeadTarget->GetLocalGenerator();
  1248. switch (statusForTarget(context->HeadTarget, policy)) {
  1249. case cmPolicies::WARN:
  1250. lg->IssueMessage(
  1251. cmake::AUTHOR_WARNING,
  1252. cmPolicies::GetPolicyWarning(policyForString(policy)));
  1253. case cmPolicies::REQUIRED_IF_USED:
  1254. case cmPolicies::REQUIRED_ALWAYS:
  1255. case cmPolicies::OLD:
  1256. return "0";
  1257. case cmPolicies::NEW:
  1258. return "1";
  1259. }
  1260. }
  1261. }
  1262. reportError(
  1263. context, content->GetOriginalExpression(),
  1264. "$<TARGET_POLICY:prop> may only be used with a limited number of "
  1265. "policies. Currently it may be used with the following policies:\n"
  1266. #define STRINGIFY_HELPER(X) #X
  1267. #define STRINGIFY(X) STRINGIFY_HELPER(X)
  1268. #define TARGET_POLICY_LIST_ITEM(POLICY) " * " STRINGIFY(POLICY) "\n"
  1269. CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
  1270. #undef TARGET_POLICY_LIST_ITEM
  1271. );
  1272. return std::string();
  1273. }
  1274. } targetPolicyNode;
  1275. static const struct InstallPrefixNode : public cmGeneratorExpressionNode
  1276. {
  1277. InstallPrefixNode() {}
  1278. bool GeneratesContent() const CM_OVERRIDE { return true; }
  1279. int NumExpectedParameters() const CM_OVERRIDE { return 0; }
  1280. std::string Evaluate(const std::vector<std::string>& /*parameters*/,
  1281. cmGeneratorExpressionContext* context,
  1282. const GeneratorExpressionContent* content,
  1283. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  1284. CM_OVERRIDE
  1285. {
  1286. reportError(context, content->GetOriginalExpression(),
  1287. "INSTALL_PREFIX is a marker for install(EXPORT) only. It "
  1288. "should never be evaluated.");
  1289. return std::string();
  1290. }
  1291. } installPrefixNode;
  1292. class ArtifactDirTag;
  1293. class ArtifactLinkerTag;
  1294. class ArtifactNameTag;
  1295. class ArtifactPathTag;
  1296. class ArtifactPdbTag;
  1297. class ArtifactSonameTag;
  1298. template <typename ArtifactT>
  1299. struct TargetFilesystemArtifactResultCreator
  1300. {
  1301. static std::string Create(cmGeneratorTarget* target,
  1302. cmGeneratorExpressionContext* context,
  1303. const GeneratorExpressionContent* content);
  1304. };
  1305. template <>
  1306. struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
  1307. {
  1308. static std::string Create(cmGeneratorTarget* target,
  1309. cmGeneratorExpressionContext* context,
  1310. const GeneratorExpressionContent* content)
  1311. {
  1312. // The target soname file (.so.1).
  1313. if (target->IsDLLPlatform()) {
  1314. ::reportError(context, content->GetOriginalExpression(),
  1315. "TARGET_SONAME_FILE is not allowed "
  1316. "for DLL target platforms.");
  1317. return std::string();
  1318. }
  1319. if (target->GetType() != cmStateEnums::SHARED_LIBRARY) {
  1320. ::reportError(context, content->GetOriginalExpression(),
  1321. "TARGET_SONAME_FILE is allowed only for "
  1322. "SHARED libraries.");
  1323. return std::string();
  1324. }
  1325. std::string result = target->GetDirectory(context->Config);
  1326. result += "/";
  1327. result += target->GetSOName(context->Config);
  1328. return result;
  1329. }
  1330. };
  1331. template <>
  1332. struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
  1333. {
  1334. static std::string Create(cmGeneratorTarget* target,
  1335. cmGeneratorExpressionContext* context,
  1336. const GeneratorExpressionContent* content)
  1337. {
  1338. if (target->IsImported()) {
  1339. ::reportError(context, content->GetOriginalExpression(),
  1340. "TARGET_PDB_FILE not allowed for IMPORTED targets.");
  1341. return std::string();
  1342. }
  1343. std::string language = target->GetLinkerLanguage(context->Config);
  1344. std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";
  1345. if (!context->LG->GetMakefile()->IsOn(pdbSupportVar)) {
  1346. ::reportError(context, content->GetOriginalExpression(),
  1347. "TARGET_PDB_FILE is not supported by the target linker.");
  1348. return std::string();
  1349. }
  1350. cmStateEnums::TargetType targetType = target->GetType();
  1351. if (targetType != cmStateEnums::SHARED_LIBRARY &&
  1352. targetType != cmStateEnums::MODULE_LIBRARY &&
  1353. targetType != cmStateEnums::EXECUTABLE) {
  1354. ::reportError(context, content->GetOriginalExpression(),
  1355. "TARGET_PDB_FILE is allowed only for "
  1356. "targets with linker created artifacts.");
  1357. return std::string();
  1358. }
  1359. std::string result = target->GetPDBDirectory(context->Config);
  1360. result += "/";
  1361. result += target->GetPDBName(context->Config);
  1362. return result;
  1363. }
  1364. };
  1365. template <>
  1366. struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
  1367. {
  1368. static std::string Create(cmGeneratorTarget* target,
  1369. cmGeneratorExpressionContext* context,
  1370. const GeneratorExpressionContent* content)
  1371. {
  1372. // The file used to link to the target (.so, .lib, .a).
  1373. if (!target->IsLinkable()) {
  1374. ::reportError(context, content->GetOriginalExpression(),
  1375. "TARGET_LINKER_FILE is allowed only for libraries and "
  1376. "executables with ENABLE_EXPORTS.");
  1377. return std::string();
  1378. }
  1379. return target->GetFullPath(context->Config, target->HasImportLibrary());
  1380. }
  1381. };
  1382. template <>
  1383. struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
  1384. {
  1385. static std::string Create(cmGeneratorTarget* target,
  1386. cmGeneratorExpressionContext* context,
  1387. const GeneratorExpressionContent* /*unused*/)
  1388. {
  1389. return target->GetFullPath(context->Config, false, true);
  1390. }
  1391. };
  1392. template <typename ArtifactT>
  1393. struct TargetFilesystemArtifactResultGetter
  1394. {
  1395. static std::string Get(const std::string& result);
  1396. };
  1397. template <>
  1398. struct TargetFilesystemArtifactResultGetter<ArtifactNameTag>
  1399. {
  1400. static std::string Get(const std::string& result)
  1401. {
  1402. return cmSystemTools::GetFilenameName(result);
  1403. }
  1404. };
  1405. template <>
  1406. struct TargetFilesystemArtifactResultGetter<ArtifactDirTag>
  1407. {
  1408. static std::string Get(const std::string& result)
  1409. {
  1410. return cmSystemTools::GetFilenamePath(result);
  1411. }
  1412. };
  1413. template <>
  1414. struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
  1415. {
  1416. static std::string Get(const std::string& result) { return result; }
  1417. };
  1418. template <typename ArtifactT, typename ComponentT>
  1419. struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
  1420. {
  1421. TargetFilesystemArtifact() {}
  1422. int NumExpectedParameters() const CM_OVERRIDE { return 1; }
  1423. std::string Evaluate(const std::vector<std::string>& parameters,
  1424. cmGeneratorExpressionContext* context,
  1425. const GeneratorExpressionContent* content,
  1426. cmGeneratorExpressionDAGChecker* dagChecker) const
  1427. CM_OVERRIDE
  1428. {
  1429. // Lookup the referenced target.
  1430. std::string name = *parameters.begin();
  1431. if (!cmGeneratorExpression::IsValidTargetName(name)) {
  1432. ::reportError(context, content->GetOriginalExpression(),
  1433. "Expression syntax not recognized.");
  1434. return std::string();
  1435. }
  1436. cmGeneratorTarget* target = context->LG->FindGeneratorTargetToUse(name);
  1437. if (!target) {
  1438. ::reportError(context, content->GetOriginalExpression(),
  1439. "No target \"" + name + "\"");
  1440. return std::string();
  1441. }
  1442. if (target->GetType() >= cmStateEnums::OBJECT_LIBRARY &&
  1443. target->GetType() != cmStateEnums::UNKNOWN_LIBRARY) {
  1444. ::reportError(context, content->GetOriginalExpression(), "Target \"" +
  1445. name + "\" is not an executable or library.");
  1446. return std::string();
  1447. }
  1448. if (dagChecker && (dagChecker->EvaluatingLinkLibraries(name.c_str()) ||
  1449. (dagChecker->EvaluatingSources() &&
  1450. name == dagChecker->TopTarget()))) {
  1451. ::reportError(context, content->GetOriginalExpression(),
  1452. "Expressions which require the linker language may not "
  1453. "be used while evaluating link libraries");
  1454. return std::string();
  1455. }
  1456. context->DependTargets.insert(target);
  1457. context->AllTargets.insert(target);
  1458. std::string result =
  1459. TargetFilesystemArtifactResultCreator<ArtifactT>::Create(target, context,
  1460. content);
  1461. if (context->HadError) {
  1462. return std::string();
  1463. }
  1464. return TargetFilesystemArtifactResultGetter<ComponentT>::Get(result);
  1465. }
  1466. };
  1467. template <typename ArtifactT>
  1468. struct TargetFilesystemArtifactNodeGroup
  1469. {
  1470. TargetFilesystemArtifactNodeGroup() {}
  1471. TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File;
  1472. TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName;
  1473. TargetFilesystemArtifact<ArtifactT, ArtifactDirTag> FileDir;
  1474. };
  1475. static const TargetFilesystemArtifactNodeGroup<ArtifactNameTag>
  1476. targetNodeGroup;
  1477. static const TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag>
  1478. targetLinkerNodeGroup;
  1479. static const TargetFilesystemArtifactNodeGroup<ArtifactSonameTag>
  1480. targetSoNameNodeGroup;
  1481. static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag>
  1482. targetPdbNodeGroup;
  1483. static const struct ShellPathNode : public cmGeneratorExpressionNode
  1484. {
  1485. ShellPathNode() {}
  1486. std::string Evaluate(const std::vector<std::string>& parameters,
  1487. cmGeneratorExpressionContext* context,
  1488. const GeneratorExpressionContent* content,
  1489. cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
  1490. CM_OVERRIDE
  1491. {
  1492. if (!cmSystemTools::FileIsFullPath(parameters.front())) {
  1493. reportError(context, content->GetOriginalExpression(),
  1494. "\"" + parameters.front() + "\" is not an absolute path.");
  1495. return std::string();
  1496. }
  1497. cmOutputConverter converter(context->LG->GetStateSnapshot());
  1498. return converter.ConvertDirectorySeparatorsForShell(parameters.front());
  1499. }
  1500. } shellPathNode;
  1501. const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
  1502. const std::string& identifier)
  1503. {
  1504. typedef std::map<std::string, const cmGeneratorExpressionNode*> NodeMap;
  1505. static NodeMap nodeMap;
  1506. if (nodeMap.empty()) {
  1507. nodeMap["0"] = &zeroNode;
  1508. nodeMap["1"] = &oneNode;
  1509. nodeMap["AND"] = &andNode;
  1510. nodeMap["OR"] = &orNode;
  1511. nodeMap["NOT"] = &notNode;
  1512. nodeMap["C_COMPILER_ID"] = &cCompilerIdNode;
  1513. nodeMap["CXX_COMPILER_ID"] = &cxxCompilerIdNode;
  1514. nodeMap["VERSION_GREATER"] = &versionGreaterNode;
  1515. nodeMap["VERSION_GREATER_EQUAL"] = &versionGreaterEqNode;
  1516. nodeMap["VERSION_LESS"] = &versionLessNode;
  1517. nodeMap["VERSION_LESS_EQUAL"] = &versionLessEqNode;
  1518. nodeMap["VERSION_EQUAL"] = &versionEqualNode;
  1519. nodeMap["C_COMPILER_VERSION"] = &cCompilerVersionNode;
  1520. nodeMap["CXX_COMPILER_VERSION"] = &cxxCompilerVersionNode;
  1521. nodeMap["PLATFORM_ID"] = &platformIdNode;
  1522. nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode;
  1523. nodeMap["CONFIGURATION"] = &configurationNode;
  1524. nodeMap["CONFIG"] = &configurationTestNode;
  1525. nodeMap["TARGET_FILE"] = &targetNodeGroup.File;
  1526. nodeMap["TARGET_LINKER_FILE"] = &targetLinkerNodeGroup.File;
  1527. nodeMap["TARGET_SONAME_FILE"] = &targetSoNameNodeGroup.File;
  1528. nodeMap["TARGET_PDB_FILE"] = &targetPdbNodeGroup.File;
  1529. nodeMap["TARGET_FILE_NAME"] = &targetNodeGroup.FileName;
  1530. nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerNodeGroup.FileName;
  1531. nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameNodeGroup.FileName;
  1532. nodeMap["TARGET_PDB_FILE_NAME"] = &targetPdbNodeGroup.FileName;
  1533. nodeMap["TARGET_FILE_DIR"] = &targetNodeGroup.FileDir;
  1534. nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir;
  1535. nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir;
  1536. nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir;
  1537. nodeMap["STREQUAL"] = &strEqualNode;
  1538. nodeMap["EQUAL"] = &equalNode;
  1539. nodeMap["LOWER_CASE"] = &lowerCaseNode;
  1540. nodeMap["UPPER_CASE"] = &upperCaseNode;
  1541. nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode;
  1542. nodeMap["BOOL"] = &boolNode;
  1543. nodeMap["ANGLE-R"] = &angle_rNode;
  1544. nodeMap["COMMA"] = &commaNode;
  1545. nodeMap["SEMICOLON"] = &semicolonNode;
  1546. nodeMap["TARGET_PROPERTY"] = &targetPropertyNode;
  1547. nodeMap["TARGET_NAME"] = &targetNameNode;
  1548. nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
  1549. nodeMap["TARGET_POLICY"] = &targetPolicyNode;
  1550. nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
  1551. nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
  1552. nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
  1553. nodeMap["JOIN"] = &joinNode;
  1554. nodeMap["LINK_ONLY"] = &linkOnlyNode;
  1555. nodeMap["COMPILE_LANGUAGE"] = &languageNode;
  1556. nodeMap["SHELL_PATH"] = &shellPathNode;
  1557. }
  1558. NodeMap::const_iterator i = nodeMap.find(identifier);
  1559. if (i == nodeMap.end()) {
  1560. return CM_NULLPTR;
  1561. }
  1562. return i->second;
  1563. }
  1564. void reportError(cmGeneratorExpressionContext* context,
  1565. const std::string& expr, const std::string& result)
  1566. {
  1567. context->HadError = true;
  1568. if (context->Quiet) {
  1569. return;
  1570. }
  1571. std::ostringstream e;
  1572. /* clang-format off */
  1573. e << "Error evaluating generator expression:\n"
  1574. << " " << expr << "\n"
  1575. << result;
  1576. /* clang-format on */
  1577. context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
  1578. context->Backtrace);
  1579. }