cmGeneratorExpressionEvaluator.cxx 61 KB

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