cmGeneratorExpressionNode.cxx 86 KB

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