cmGeneratorExpressionEvaluator.cxx 59 KB

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