1
0

cmGeneratorExpressionNode.cxx 72 KB

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