cmGeneratorExpressionEvaluator.cxx 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653
  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. static const struct VersionGreaterNode : public cmGeneratorExpressionNode
  381. {
  382. VersionGreaterNode() {}
  383. virtual int NumExpectedParameters() const { return 2; }
  384. std::string Evaluate(const std::vector<std::string> &parameters,
  385. cmGeneratorExpressionContext *,
  386. const GeneratorExpressionContent *,
  387. cmGeneratorExpressionDAGChecker *) const
  388. {
  389. return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
  390. parameters.front().c_str(),
  391. parameters[1].c_str()) ? "1" : "0";
  392. }
  393. } versionGreaterNode;
  394. //----------------------------------------------------------------------------
  395. static const struct VersionLessNode : public cmGeneratorExpressionNode
  396. {
  397. VersionLessNode() {}
  398. virtual int NumExpectedParameters() const { return 2; }
  399. std::string Evaluate(const std::vector<std::string> &parameters,
  400. cmGeneratorExpressionContext *,
  401. const GeneratorExpressionContent *,
  402. cmGeneratorExpressionDAGChecker *) const
  403. {
  404. return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
  405. parameters.front().c_str(),
  406. parameters[1].c_str()) ? "1" : "0";
  407. }
  408. } versionLessNode;
  409. //----------------------------------------------------------------------------
  410. static const struct VersionEqualNode : public cmGeneratorExpressionNode
  411. {
  412. VersionEqualNode() {}
  413. virtual int NumExpectedParameters() const { return 2; }
  414. std::string Evaluate(const std::vector<std::string> &parameters,
  415. cmGeneratorExpressionContext *,
  416. const GeneratorExpressionContent *,
  417. cmGeneratorExpressionDAGChecker *) const
  418. {
  419. return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
  420. parameters.front().c_str(),
  421. parameters[1].c_str()) ? "1" : "0";
  422. }
  423. } versionEqualNode;
  424. //----------------------------------------------------------------------------
  425. static const struct LinkOnlyNode : public cmGeneratorExpressionNode
  426. {
  427. LinkOnlyNode() {}
  428. std::string Evaluate(const std::vector<std::string> &parameters,
  429. cmGeneratorExpressionContext *,
  430. const GeneratorExpressionContent *,
  431. cmGeneratorExpressionDAGChecker *dagChecker) const
  432. {
  433. if(!dagChecker->GetTransitivePropertiesOnly())
  434. {
  435. return parameters.front();
  436. }
  437. return "";
  438. }
  439. } linkOnlyNode;
  440. //----------------------------------------------------------------------------
  441. static const struct ConfigurationNode : public cmGeneratorExpressionNode
  442. {
  443. ConfigurationNode() {}
  444. virtual int NumExpectedParameters() const { return 0; }
  445. std::string Evaluate(const std::vector<std::string> &,
  446. cmGeneratorExpressionContext *context,
  447. const GeneratorExpressionContent *,
  448. cmGeneratorExpressionDAGChecker *) const
  449. {
  450. context->HadContextSensitiveCondition = true;
  451. return context->Config ? context->Config : "";
  452. }
  453. } configurationNode;
  454. //----------------------------------------------------------------------------
  455. static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
  456. {
  457. ConfigurationTestNode() {}
  458. virtual int NumExpectedParameters() const { return 1; }
  459. std::string Evaluate(const std::vector<std::string> &parameters,
  460. cmGeneratorExpressionContext *context,
  461. const GeneratorExpressionContent *content,
  462. cmGeneratorExpressionDAGChecker *) const
  463. {
  464. cmsys::RegularExpression configValidator;
  465. configValidator.compile("^[A-Za-z0-9_]*$");
  466. if (!configValidator.find(parameters.begin()->c_str()))
  467. {
  468. reportError(context, content->GetOriginalExpression(),
  469. "Expression syntax not recognized.");
  470. return std::string();
  471. }
  472. context->HadContextSensitiveCondition = true;
  473. if (!context->Config)
  474. {
  475. return parameters.front().empty() ? "1" : "0";
  476. }
  477. if (cmsysString_strcasecmp(parameters.begin()->c_str(),
  478. context->Config) == 0)
  479. {
  480. return "1";
  481. }
  482. if (context->CurrentTarget
  483. && context->CurrentTarget->IsImported())
  484. {
  485. const char* loc = 0;
  486. const char* imp = 0;
  487. std::string suffix;
  488. if (context->CurrentTarget->GetMappedConfig(context->Config,
  489. &loc,
  490. &imp,
  491. suffix))
  492. {
  493. // This imported target has an appropriate location
  494. // for this (possibly mapped) config.
  495. // Check if there is a proper config mapping for the tested config.
  496. std::vector<std::string> mappedConfigs;
  497. std::string mapProp = "MAP_IMPORTED_CONFIG_";
  498. mapProp += context->Config;
  499. if(const char* mapValue =
  500. context->CurrentTarget->GetProperty(mapProp.c_str()))
  501. {
  502. cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
  503. mappedConfigs);
  504. return std::find(mappedConfigs.begin(), mappedConfigs.end(),
  505. context->Config) != mappedConfigs.end() ? "1" : "0";
  506. }
  507. }
  508. }
  509. return "0";
  510. }
  511. } configurationTestNode;
  512. static const struct JoinNode : public cmGeneratorExpressionNode
  513. {
  514. JoinNode() {}
  515. virtual int NumExpectedParameters() const { return 2; }
  516. virtual bool AcceptsArbitraryContentParameter() const { return true; }
  517. std::string Evaluate(const std::vector<std::string> &parameters,
  518. cmGeneratorExpressionContext *,
  519. const GeneratorExpressionContent *,
  520. cmGeneratorExpressionDAGChecker *) const
  521. {
  522. std::string result;
  523. std::vector<std::string> list;
  524. cmSystemTools::ExpandListArgument(parameters.front(), list);
  525. std::string sep;
  526. for(std::vector<std::string>::const_iterator li = list.begin();
  527. li != list.end(); ++li)
  528. {
  529. result += sep + *li;
  530. sep = parameters[1];
  531. }
  532. return result;
  533. }
  534. } joinNode;
  535. #define TRANSITIVE_PROPERTY_NAME(PROPERTY) \
  536. , #PROPERTY
  537. //----------------------------------------------------------------------------
  538. static const char* targetPropertyTransitiveWhitelist[] = {
  539. 0
  540. CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
  541. };
  542. std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
  543. cmTarget *target,
  544. cmTarget *headTarget,
  545. cmGeneratorExpressionContext *context,
  546. cmGeneratorExpressionDAGChecker *dagChecker,
  547. const std::string &interfacePropertyName)
  548. {
  549. cmGeneratorExpression ge(context->Backtrace);
  550. std::string sep;
  551. std::string depString;
  552. for (std::vector<std::string>::const_iterator
  553. it = libraries.begin();
  554. it != libraries.end(); ++it)
  555. {
  556. if (*it == target->GetName())
  557. {
  558. // Broken code can have a target in its own link interface.
  559. // Don't follow such link interface entries so as not to create a
  560. // self-referencing loop.
  561. continue;
  562. }
  563. if (context->Makefile->FindTargetToUse(it->c_str()))
  564. {
  565. depString +=
  566. sep + "$<TARGET_PROPERTY:" + *it + "," + interfacePropertyName + ">";
  567. sep = ";";
  568. }
  569. }
  570. cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString);
  571. std::string linkedTargetsContent = cge->Evaluate(context->Makefile,
  572. context->Config,
  573. context->Quiet,
  574. headTarget,
  575. target,
  576. dagChecker);
  577. if (cge->GetHadContextSensitiveCondition())
  578. {
  579. context->HadContextSensitiveCondition = true;
  580. }
  581. return linkedTargetsContent;
  582. }
  583. //----------------------------------------------------------------------------
  584. struct TransitiveWhitelistCompare
  585. {
  586. explicit TransitiveWhitelistCompare(const std::string &needle)
  587. : Needle(needle) {}
  588. bool operator() (const char *item)
  589. { return strcmp(item, this->Needle.c_str()) == 0; }
  590. private:
  591. std::string Needle;
  592. };
  593. //----------------------------------------------------------------------------
  594. static const struct TargetPropertyNode : public cmGeneratorExpressionNode
  595. {
  596. TargetPropertyNode() {}
  597. // This node handles errors on parameter count itself.
  598. virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
  599. std::string Evaluate(const std::vector<std::string> &parameters,
  600. cmGeneratorExpressionContext *context,
  601. const GeneratorExpressionContent *content,
  602. cmGeneratorExpressionDAGChecker *dagCheckerParent
  603. ) const
  604. {
  605. if (parameters.size() != 1 && parameters.size() != 2)
  606. {
  607. reportError(context, content->GetOriginalExpression(),
  608. "$<TARGET_PROPERTY:...> expression requires one or two parameters");
  609. return std::string();
  610. }
  611. cmsys::RegularExpression propertyNameValidator;
  612. propertyNameValidator.compile("^[A-Za-z0-9_]+$");
  613. cmTarget* target = context->HeadTarget;
  614. std::string propertyName = *parameters.begin();
  615. if (!target && parameters.size() == 1)
  616. {
  617. reportError(context, content->GetOriginalExpression(),
  618. "$<TARGET_PROPERTY:prop> may only be used with targets. It may not "
  619. "be used with add_custom_command. Specify the target to read a "
  620. "property from using the $<TARGET_PROPERTY:tgt,prop> signature "
  621. "instead.");
  622. return std::string();
  623. }
  624. if (parameters.size() == 2)
  625. {
  626. if (parameters.begin()->empty() && parameters[1].empty())
  627. {
  628. reportError(context, content->GetOriginalExpression(),
  629. "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
  630. "target name and property name.");
  631. return std::string();
  632. }
  633. if (parameters.begin()->empty())
  634. {
  635. reportError(context, content->GetOriginalExpression(),
  636. "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
  637. "target name.");
  638. return std::string();
  639. }
  640. std::string targetName = parameters.front();
  641. propertyName = parameters[1];
  642. if (!cmGeneratorExpression::IsValidTargetName(targetName))
  643. {
  644. if (!propertyNameValidator.find(propertyName.c_str()))
  645. {
  646. ::reportError(context, content->GetOriginalExpression(),
  647. "Target name and property name not supported.");
  648. return std::string();
  649. }
  650. ::reportError(context, content->GetOriginalExpression(),
  651. "Target name not supported.");
  652. return std::string();
  653. }
  654. if(propertyName == "ALIASED_TARGET")
  655. {
  656. if(context->Makefile->IsAlias(targetName.c_str()))
  657. {
  658. if(cmTarget* tgt =
  659. context->Makefile->FindTargetToUse(targetName.c_str()))
  660. {
  661. return tgt->GetName();
  662. }
  663. }
  664. return "";
  665. }
  666. target = context->Makefile->FindTargetToUse(
  667. targetName.c_str());
  668. if (!target)
  669. {
  670. cmOStringStream e;
  671. e << "Target \""
  672. << targetName
  673. << "\" not found.";
  674. reportError(context, content->GetOriginalExpression(), e.str());
  675. return std::string();
  676. }
  677. context->AllTargets.insert(target);
  678. }
  679. if (target == context->HeadTarget)
  680. {
  681. // Keep track of the properties seen while processing.
  682. // The evaluation of the LINK_LIBRARIES generator expressions
  683. // will check this to ensure that properties have one consistent
  684. // value for all evaluations.
  685. context->SeenTargetProperties.insert(propertyName);
  686. }
  687. if (propertyName.empty())
  688. {
  689. reportError(context, content->GetOriginalExpression(),
  690. "$<TARGET_PROPERTY:...> expression requires a non-empty property "
  691. "name.");
  692. return std::string();
  693. }
  694. if (!propertyNameValidator.find(propertyName.c_str()))
  695. {
  696. ::reportError(context, content->GetOriginalExpression(),
  697. "Property name not supported.");
  698. return std::string();
  699. }
  700. assert(target);
  701. if (propertyName == "LINKER_LANGUAGE")
  702. {
  703. if (target->LinkLanguagePropagatesToDependents() &&
  704. dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
  705. {
  706. reportError(context, content->GetOriginalExpression(),
  707. "LINKER_LANGUAGE target property can not be used while evaluating "
  708. "link libraries for a static library");
  709. return std::string();
  710. }
  711. const char *lang = target->GetLinkerLanguage(context->Config);
  712. return lang ? lang : "";
  713. }
  714. cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
  715. target->GetName(),
  716. propertyName,
  717. content,
  718. dagCheckerParent);
  719. switch (dagChecker.check())
  720. {
  721. case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
  722. dagChecker.reportError(context, content->GetOriginalExpression());
  723. return std::string();
  724. case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
  725. // No error. We just skip cyclic references.
  726. return std::string();
  727. case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
  728. for (size_t i = 1;
  729. i < (sizeof(targetPropertyTransitiveWhitelist) /
  730. sizeof(*targetPropertyTransitiveWhitelist));
  731. ++i)
  732. {
  733. if (targetPropertyTransitiveWhitelist[i] == propertyName)
  734. {
  735. // No error. We're not going to find anything new here.
  736. return std::string();
  737. }
  738. }
  739. case cmGeneratorExpressionDAGChecker::DAG:
  740. break;
  741. }
  742. const char *prop = target->GetProperty(propertyName.c_str());
  743. if (dagCheckerParent)
  744. {
  745. if (dagCheckerParent->EvaluatingLinkLibraries())
  746. {
  747. if(!prop)
  748. {
  749. return std::string();
  750. }
  751. }
  752. else
  753. {
  754. #define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) \
  755. dagCheckerParent->METHOD () ||
  756. assert(
  757. CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
  758. ASSERT_TRANSITIVE_PROPERTY_METHOD)
  759. false);
  760. }
  761. }
  762. std::string linkedTargetsContent;
  763. std::string interfacePropertyName;
  764. if (propertyName == "INTERFACE_INCLUDE_DIRECTORIES"
  765. || propertyName == "INCLUDE_DIRECTORIES")
  766. {
  767. interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES";
  768. }
  769. else if (propertyName == "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")
  770. {
  771. interfacePropertyName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES";
  772. }
  773. else if (propertyName == "INTERFACE_COMPILE_DEFINITIONS"
  774. || propertyName == "COMPILE_DEFINITIONS"
  775. || strncmp(propertyName.c_str(), "COMPILE_DEFINITIONS_", 20) == 0)
  776. {
  777. interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
  778. }
  779. else if (propertyName == "INTERFACE_COMPILE_OPTIONS"
  780. || propertyName == "COMPILE_OPTIONS")
  781. {
  782. interfacePropertyName = "INTERFACE_COMPILE_OPTIONS";
  783. }
  784. cmTarget *headTarget = context->HeadTarget ? context->HeadTarget : target;
  785. const char **transBegin = targetPropertyTransitiveWhitelist + 1;
  786. const char **transEnd = targetPropertyTransitiveWhitelist
  787. + (sizeof(targetPropertyTransitiveWhitelist) /
  788. sizeof(*targetPropertyTransitiveWhitelist));
  789. if (std::find_if(transBegin, transEnd,
  790. TransitiveWhitelistCompare(propertyName)) != transEnd)
  791. {
  792. std::vector<std::string> libs;
  793. target->GetTransitivePropertyLinkLibraries(context->Config,
  794. headTarget, libs);
  795. if (!libs.empty())
  796. {
  797. linkedTargetsContent =
  798. getLinkedTargetsContent(libs, target,
  799. headTarget,
  800. context, &dagChecker,
  801. interfacePropertyName);
  802. }
  803. }
  804. else if (std::find_if(transBegin, transEnd,
  805. TransitiveWhitelistCompare(interfacePropertyName)) != transEnd)
  806. {
  807. const cmTarget::LinkImplementation *impl = target->GetLinkImplementation(
  808. context->Config,
  809. headTarget);
  810. if(impl)
  811. {
  812. linkedTargetsContent =
  813. getLinkedTargetsContent(impl->Libraries, target,
  814. headTarget,
  815. context, &dagChecker,
  816. interfacePropertyName);
  817. }
  818. }
  819. linkedTargetsContent =
  820. cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
  821. if (!prop)
  822. {
  823. if (target->IsImported())
  824. {
  825. return linkedTargetsContent;
  826. }
  827. if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
  828. context->Config))
  829. {
  830. context->HadContextSensitiveCondition = true;
  831. return target->GetLinkInterfaceDependentBoolProperty(
  832. propertyName,
  833. context->Config) ? "1" : "0";
  834. }
  835. if (target->IsLinkInterfaceDependentStringProperty(propertyName,
  836. context->Config))
  837. {
  838. context->HadContextSensitiveCondition = true;
  839. const char *propContent =
  840. target->GetLinkInterfaceDependentStringProperty(
  841. propertyName,
  842. context->Config);
  843. return propContent ? propContent : "";
  844. }
  845. return linkedTargetsContent;
  846. }
  847. for (size_t i = 1;
  848. i < (sizeof(targetPropertyTransitiveWhitelist) /
  849. sizeof(*targetPropertyTransitiveWhitelist));
  850. ++i)
  851. {
  852. if (targetPropertyTransitiveWhitelist[i] == interfacePropertyName)
  853. {
  854. cmGeneratorExpression ge(context->Backtrace);
  855. cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
  856. std::string result = cge->Evaluate(context->Makefile,
  857. context->Config,
  858. context->Quiet,
  859. headTarget,
  860. target,
  861. &dagChecker);
  862. if (cge->GetHadContextSensitiveCondition())
  863. {
  864. context->HadContextSensitiveCondition = true;
  865. }
  866. if (!linkedTargetsContent.empty())
  867. {
  868. result += (result.empty() ? "" : ";") + linkedTargetsContent;
  869. }
  870. return result;
  871. }
  872. }
  873. return prop;
  874. }
  875. } targetPropertyNode;
  876. //----------------------------------------------------------------------------
  877. static const struct TargetNameNode : public cmGeneratorExpressionNode
  878. {
  879. TargetNameNode() {}
  880. virtual bool GeneratesContent() const { return true; }
  881. virtual bool AcceptsArbitraryContentParameter() const { return true; }
  882. virtual bool RequiresLiteralInput() const { return true; }
  883. std::string Evaluate(const std::vector<std::string> &parameters,
  884. cmGeneratorExpressionContext *,
  885. const GeneratorExpressionContent *,
  886. cmGeneratorExpressionDAGChecker *) const
  887. {
  888. return parameters.front();
  889. }
  890. virtual int NumExpectedParameters() const { return 1; }
  891. } targetNameNode;
  892. //----------------------------------------------------------------------------
  893. static const char* targetPolicyWhitelist[] = {
  894. 0
  895. #define TARGET_POLICY_STRING(POLICY) \
  896. , #POLICY
  897. CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
  898. #undef TARGET_POLICY_STRING
  899. };
  900. cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
  901. {
  902. #define RETURN_POLICY(POLICY) \
  903. if (strcmp(policy, #POLICY) == 0) \
  904. { \
  905. return tgt->GetPolicyStatus ## POLICY (); \
  906. } \
  907. CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
  908. #undef RETURN_POLICY
  909. assert("!Unreachable code. Not a valid policy");
  910. return cmPolicies::WARN;
  911. }
  912. cmPolicies::PolicyID policyForString(const char *policy_id)
  913. {
  914. #define RETURN_POLICY_ID(POLICY_ID) \
  915. if (strcmp(policy_id, #POLICY_ID) == 0) \
  916. { \
  917. return cmPolicies:: POLICY_ID; \
  918. } \
  919. CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
  920. #undef RETURN_POLICY_ID
  921. assert("!Unreachable code. Not a valid policy");
  922. return cmPolicies::CMP0002;
  923. }
  924. //----------------------------------------------------------------------------
  925. static const struct TargetPolicyNode : public cmGeneratorExpressionNode
  926. {
  927. TargetPolicyNode() {}
  928. virtual int NumExpectedParameters() const { return 1; }
  929. std::string Evaluate(const std::vector<std::string> &parameters,
  930. cmGeneratorExpressionContext *context ,
  931. const GeneratorExpressionContent *content,
  932. cmGeneratorExpressionDAGChecker *) const
  933. {
  934. if (!context->HeadTarget)
  935. {
  936. reportError(context, content->GetOriginalExpression(),
  937. "$<TARGET_POLICY:prop> may only be used with targets. It may not "
  938. "be used with add_custom_command.");
  939. return std::string();
  940. }
  941. context->HadContextSensitiveCondition = true;
  942. for (size_t i = 1;
  943. i < (sizeof(targetPolicyWhitelist) /
  944. sizeof(*targetPolicyWhitelist));
  945. ++i)
  946. {
  947. const char *policy = targetPolicyWhitelist[i];
  948. if (parameters.front() == policy)
  949. {
  950. cmMakefile *mf = context->HeadTarget->GetMakefile();
  951. switch(statusForTarget(context->HeadTarget, policy))
  952. {
  953. case cmPolicies::WARN:
  954. mf->IssueMessage(cmake::AUTHOR_WARNING,
  955. mf->GetPolicies()->
  956. GetPolicyWarning(policyForString(policy)));
  957. case cmPolicies::REQUIRED_IF_USED:
  958. case cmPolicies::REQUIRED_ALWAYS:
  959. case cmPolicies::OLD:
  960. return "0";
  961. case cmPolicies::NEW:
  962. return "1";
  963. }
  964. }
  965. }
  966. reportError(context, content->GetOriginalExpression(),
  967. "$<TARGET_POLICY:prop> may only be used with a limited number of "
  968. "policies. Currently it may be used with the following policies:\n"
  969. #define STRINGIFY_HELPER(X) #X
  970. #define STRINGIFY(X) STRINGIFY_HELPER(X)
  971. #define TARGET_POLICY_LIST_ITEM(POLICY) \
  972. " * " STRINGIFY(POLICY) "\n"
  973. CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
  974. #undef TARGET_POLICY_LIST_ITEM
  975. );
  976. return std::string();
  977. }
  978. } targetPolicyNode;
  979. //----------------------------------------------------------------------------
  980. static const struct InstallPrefixNode : public cmGeneratorExpressionNode
  981. {
  982. InstallPrefixNode() {}
  983. virtual bool GeneratesContent() const { return true; }
  984. virtual int NumExpectedParameters() const { return 0; }
  985. std::string Evaluate(const std::vector<std::string> &,
  986. cmGeneratorExpressionContext *context,
  987. const GeneratorExpressionContent *content,
  988. cmGeneratorExpressionDAGChecker *) const
  989. {
  990. reportError(context, content->GetOriginalExpression(),
  991. "INSTALL_PREFIX is a marker for install(EXPORT) only. It "
  992. "should never be evaluated.");
  993. return std::string();
  994. }
  995. } installPrefixNode;
  996. //----------------------------------------------------------------------------
  997. template<bool linker, bool soname>
  998. struct TargetFilesystemArtifactResultCreator
  999. {
  1000. static std::string Create(cmTarget* target,
  1001. cmGeneratorExpressionContext *context,
  1002. const GeneratorExpressionContent *content);
  1003. };
  1004. //----------------------------------------------------------------------------
  1005. template<>
  1006. struct TargetFilesystemArtifactResultCreator<false, true>
  1007. {
  1008. static std::string Create(cmTarget* target,
  1009. cmGeneratorExpressionContext *context,
  1010. const GeneratorExpressionContent *content)
  1011. {
  1012. // The target soname file (.so.1).
  1013. if(target->IsDLLPlatform())
  1014. {
  1015. ::reportError(context, content->GetOriginalExpression(),
  1016. "TARGET_SONAME_FILE is not allowed "
  1017. "for DLL target platforms.");
  1018. return std::string();
  1019. }
  1020. if(target->GetType() != cmTarget::SHARED_LIBRARY)
  1021. {
  1022. ::reportError(context, content->GetOriginalExpression(),
  1023. "TARGET_SONAME_FILE is allowed only for "
  1024. "SHARED libraries.");
  1025. return std::string();
  1026. }
  1027. std::string result = target->GetDirectory(context->Config);
  1028. result += "/";
  1029. result += target->GetSOName(context->Config);
  1030. return result;
  1031. }
  1032. };
  1033. //----------------------------------------------------------------------------
  1034. template<>
  1035. struct TargetFilesystemArtifactResultCreator<true, false>
  1036. {
  1037. static std::string Create(cmTarget* target,
  1038. cmGeneratorExpressionContext *context,
  1039. const GeneratorExpressionContent *content)
  1040. {
  1041. // The file used to link to the target (.so, .lib, .a).
  1042. if(!target->IsLinkable())
  1043. {
  1044. ::reportError(context, content->GetOriginalExpression(),
  1045. "TARGET_LINKER_FILE is allowed only for libraries and "
  1046. "executables with ENABLE_EXPORTS.");
  1047. return std::string();
  1048. }
  1049. return target->GetFullPath(context->Config,
  1050. target->HasImportLibrary());
  1051. }
  1052. };
  1053. //----------------------------------------------------------------------------
  1054. template<>
  1055. struct TargetFilesystemArtifactResultCreator<false, false>
  1056. {
  1057. static std::string Create(cmTarget* target,
  1058. cmGeneratorExpressionContext *context,
  1059. const GeneratorExpressionContent *)
  1060. {
  1061. return target->GetFullPath(context->Config, false, true);
  1062. }
  1063. };
  1064. //----------------------------------------------------------------------------
  1065. template<bool dirQual, bool nameQual>
  1066. struct TargetFilesystemArtifactResultGetter
  1067. {
  1068. static std::string Get(const std::string &result);
  1069. };
  1070. //----------------------------------------------------------------------------
  1071. template<>
  1072. struct TargetFilesystemArtifactResultGetter<false, true>
  1073. {
  1074. static std::string Get(const std::string &result)
  1075. { return cmSystemTools::GetFilenameName(result); }
  1076. };
  1077. //----------------------------------------------------------------------------
  1078. template<>
  1079. struct TargetFilesystemArtifactResultGetter<true, false>
  1080. {
  1081. static std::string Get(const std::string &result)
  1082. { return cmSystemTools::GetFilenamePath(result); }
  1083. };
  1084. //----------------------------------------------------------------------------
  1085. template<>
  1086. struct TargetFilesystemArtifactResultGetter<false, false>
  1087. {
  1088. static std::string Get(const std::string &result)
  1089. { return result; }
  1090. };
  1091. //----------------------------------------------------------------------------
  1092. template<bool linker, bool soname, bool dirQual, bool nameQual>
  1093. struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
  1094. {
  1095. TargetFilesystemArtifact() {}
  1096. virtual int NumExpectedParameters() const { return 1; }
  1097. std::string Evaluate(const std::vector<std::string> &parameters,
  1098. cmGeneratorExpressionContext *context,
  1099. const GeneratorExpressionContent *content,
  1100. cmGeneratorExpressionDAGChecker *dagChecker) const
  1101. {
  1102. // Lookup the referenced target.
  1103. std::string name = *parameters.begin();
  1104. if (!cmGeneratorExpression::IsValidTargetName(name))
  1105. {
  1106. ::reportError(context, content->GetOriginalExpression(),
  1107. "Expression syntax not recognized.");
  1108. return std::string();
  1109. }
  1110. cmTarget* target = context->Makefile->FindTargetToUse(name.c_str());
  1111. if(!target)
  1112. {
  1113. ::reportError(context, content->GetOriginalExpression(),
  1114. "No target \"" + name + "\"");
  1115. return std::string();
  1116. }
  1117. if(target->GetType() >= cmTarget::UTILITY &&
  1118. target->GetType() != cmTarget::UNKNOWN_LIBRARY)
  1119. {
  1120. ::reportError(context, content->GetOriginalExpression(),
  1121. "Target \"" + name + "\" is not an executable or library.");
  1122. return std::string();
  1123. }
  1124. if (dagChecker && dagChecker->EvaluatingLinkLibraries(name.c_str()))
  1125. {
  1126. ::reportError(context, content->GetOriginalExpression(),
  1127. "Expressions which require the linker language may not "
  1128. "be used while evaluating link libraries");
  1129. return std::string();
  1130. }
  1131. context->DependTargets.insert(target);
  1132. context->AllTargets.insert(target);
  1133. std::string result =
  1134. TargetFilesystemArtifactResultCreator<linker, soname>::Create(
  1135. target,
  1136. context,
  1137. content);
  1138. if (context->HadError)
  1139. {
  1140. return std::string();
  1141. }
  1142. return
  1143. TargetFilesystemArtifactResultGetter<dirQual, nameQual>::Get(result);
  1144. }
  1145. };
  1146. //----------------------------------------------------------------------------
  1147. static const
  1148. TargetFilesystemArtifact<false, false, false, false> targetFileNode;
  1149. static const
  1150. TargetFilesystemArtifact<true, false, false, false> targetLinkerFileNode;
  1151. static const
  1152. TargetFilesystemArtifact<false, true, false, false> targetSoNameFileNode;
  1153. static const
  1154. TargetFilesystemArtifact<false, false, false, true> targetFileNameNode;
  1155. static const
  1156. TargetFilesystemArtifact<true, false, false, true> targetLinkerFileNameNode;
  1157. static const
  1158. TargetFilesystemArtifact<false, true, false, true> targetSoNameFileNameNode;
  1159. static const
  1160. TargetFilesystemArtifact<false, false, true, false> targetFileDirNode;
  1161. static const
  1162. TargetFilesystemArtifact<true, false, true, false> targetLinkerFileDirNode;
  1163. static const
  1164. TargetFilesystemArtifact<false, true, true, false> targetSoNameFileDirNode;
  1165. //----------------------------------------------------------------------------
  1166. static const
  1167. cmGeneratorExpressionNode* GetNode(const std::string &identifier)
  1168. {
  1169. if (identifier == "0")
  1170. return &zeroNode;
  1171. else if (identifier == "1")
  1172. return &oneNode;
  1173. else if (identifier == "AND")
  1174. return &andNode;
  1175. else if (identifier == "OR")
  1176. return &orNode;
  1177. else if (identifier == "NOT")
  1178. return &notNode;
  1179. else if (identifier == "C_COMPILER_ID")
  1180. return &cCompilerIdNode;
  1181. else if (identifier == "CXX_COMPILER_ID")
  1182. return &cxxCompilerIdNode;
  1183. else if (identifier == "VERSION_GREATER")
  1184. return &versionGreaterNode;
  1185. else if (identifier == "VERSION_LESS")
  1186. return &versionLessNode;
  1187. else if (identifier == "VERSION_EQUAL")
  1188. return &versionEqualNode;
  1189. else if (identifier == "C_COMPILER_VERSION")
  1190. return &cCompilerVersionNode;
  1191. else if (identifier == "CXX_COMPILER_VERSION")
  1192. return &cxxCompilerVersionNode;
  1193. else if (identifier == "CONFIGURATION")
  1194. return &configurationNode;
  1195. else if (identifier == "CONFIG")
  1196. return &configurationTestNode;
  1197. else if (identifier == "TARGET_FILE")
  1198. return &targetFileNode;
  1199. else if (identifier == "TARGET_LINKER_FILE")
  1200. return &targetLinkerFileNode;
  1201. else if (identifier == "TARGET_SONAME_FILE")
  1202. return &targetSoNameFileNode;
  1203. else if (identifier == "TARGET_FILE_NAME")
  1204. return &targetFileNameNode;
  1205. else if (identifier == "TARGET_LINKER_FILE_NAME")
  1206. return &targetLinkerFileNameNode;
  1207. else if (identifier == "TARGET_SONAME_FILE_NAME")
  1208. return &targetSoNameFileNameNode;
  1209. else if (identifier == "TARGET_FILE_DIR")
  1210. return &targetFileDirNode;
  1211. else if (identifier == "TARGET_LINKER_FILE_DIR")
  1212. return &targetLinkerFileDirNode;
  1213. else if (identifier == "TARGET_SONAME_FILE_DIR")
  1214. return &targetSoNameFileDirNode;
  1215. else if (identifier == "STREQUAL")
  1216. return &strEqualNode;
  1217. else if (identifier == "BOOL")
  1218. return &boolNode;
  1219. else if (identifier == "ANGLE-R")
  1220. return &angle_rNode;
  1221. else if (identifier == "COMMA")
  1222. return &commaNode;
  1223. else if (identifier == "SEMICOLON")
  1224. return &semicolonNode;
  1225. else if (identifier == "TARGET_PROPERTY")
  1226. return &targetPropertyNode;
  1227. else if (identifier == "TARGET_NAME")
  1228. return &targetNameNode;
  1229. else if (identifier == "TARGET_POLICY")
  1230. return &targetPolicyNode;
  1231. else if (identifier == "BUILD_INTERFACE")
  1232. return &buildInterfaceNode;
  1233. else if (identifier == "INSTALL_INTERFACE")
  1234. return &installInterfaceNode;
  1235. else if (identifier == "INSTALL_PREFIX")
  1236. return &installPrefixNode;
  1237. else if (identifier == "JOIN")
  1238. return &joinNode;
  1239. else if (identifier == "LINK_ONLY")
  1240. return &linkOnlyNode;
  1241. return 0;
  1242. }
  1243. //----------------------------------------------------------------------------
  1244. GeneratorExpressionContent::GeneratorExpressionContent(
  1245. const char *startContent,
  1246. unsigned int length)
  1247. : StartContent(startContent), ContentLength(length)
  1248. {
  1249. }
  1250. //----------------------------------------------------------------------------
  1251. std::string GeneratorExpressionContent::GetOriginalExpression() const
  1252. {
  1253. return std::string(this->StartContent, this->ContentLength);
  1254. }
  1255. //----------------------------------------------------------------------------
  1256. std::string GeneratorExpressionContent::ProcessArbitraryContent(
  1257. const cmGeneratorExpressionNode *node,
  1258. const std::string &identifier,
  1259. cmGeneratorExpressionContext *context,
  1260. cmGeneratorExpressionDAGChecker *dagChecker,
  1261. std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
  1262. pit) const
  1263. {
  1264. std::string result;
  1265. const
  1266. std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
  1267. pend = this->ParamChildren.end();
  1268. for ( ; pit != pend; ++pit)
  1269. {
  1270. std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
  1271. = pit->begin();
  1272. const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
  1273. = pit->end();
  1274. for ( ; it != end; ++it)
  1275. {
  1276. if (node->RequiresLiteralInput())
  1277. {
  1278. if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
  1279. {
  1280. reportError(context, this->GetOriginalExpression(),
  1281. "$<" + identifier + "> expression requires literal input.");
  1282. return std::string();
  1283. }
  1284. }
  1285. result += (*it)->Evaluate(context, dagChecker);
  1286. if (context->HadError)
  1287. {
  1288. return std::string();
  1289. }
  1290. }
  1291. if ((pit + 1) != pend)
  1292. {
  1293. result += ",";
  1294. }
  1295. }
  1296. if (node->RequiresLiteralInput())
  1297. {
  1298. std::vector<std::string> parameters;
  1299. parameters.push_back(result);
  1300. return node->Evaluate(parameters, context, this, dagChecker);
  1301. }
  1302. return result;
  1303. }
  1304. //----------------------------------------------------------------------------
  1305. std::string GeneratorExpressionContent::Evaluate(
  1306. cmGeneratorExpressionContext *context,
  1307. cmGeneratorExpressionDAGChecker *dagChecker) const
  1308. {
  1309. std::string identifier;
  1310. {
  1311. std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
  1312. = this->IdentifierChildren.begin();
  1313. const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
  1314. = this->IdentifierChildren.end();
  1315. for ( ; it != end; ++it)
  1316. {
  1317. identifier += (*it)->Evaluate(context, dagChecker);
  1318. if (context->HadError)
  1319. {
  1320. return std::string();
  1321. }
  1322. }
  1323. }
  1324. const cmGeneratorExpressionNode *node = GetNode(identifier);
  1325. if (!node)
  1326. {
  1327. reportError(context, this->GetOriginalExpression(),
  1328. "Expression did not evaluate to a known generator expression");
  1329. return std::string();
  1330. }
  1331. if (!node->GeneratesContent())
  1332. {
  1333. if (node->NumExpectedParameters() == 1
  1334. && node->AcceptsArbitraryContentParameter())
  1335. {
  1336. if (this->ParamChildren.empty())
  1337. {
  1338. reportError(context, this->GetOriginalExpression(),
  1339. "$<" + identifier + "> expression requires a parameter.");
  1340. }
  1341. }
  1342. else
  1343. {
  1344. std::vector<std::string> parameters;
  1345. this->EvaluateParameters(node, identifier, context, dagChecker,
  1346. parameters);
  1347. }
  1348. return std::string();
  1349. }
  1350. if (node->NumExpectedParameters() == 1
  1351. && node->AcceptsArbitraryContentParameter())
  1352. {
  1353. return this->ProcessArbitraryContent(node, identifier, context,
  1354. dagChecker,
  1355. this->ParamChildren.begin());
  1356. }
  1357. std::vector<std::string> parameters;
  1358. this->EvaluateParameters(node, identifier, context, dagChecker, parameters);
  1359. if (context->HadError)
  1360. {
  1361. return std::string();
  1362. }
  1363. return node->Evaluate(parameters, context, this, dagChecker);
  1364. }
  1365. //----------------------------------------------------------------------------
  1366. std::string GeneratorExpressionContent::EvaluateParameters(
  1367. const cmGeneratorExpressionNode *node,
  1368. const std::string &identifier,
  1369. cmGeneratorExpressionContext *context,
  1370. cmGeneratorExpressionDAGChecker *dagChecker,
  1371. std::vector<std::string> &parameters) const
  1372. {
  1373. const int numExpected = node->NumExpectedParameters();
  1374. {
  1375. std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
  1376. pit = this->ParamChildren.begin();
  1377. const
  1378. std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
  1379. pend = this->ParamChildren.end();
  1380. const bool acceptsArbitraryContent
  1381. = node->AcceptsArbitraryContentParameter();
  1382. for ( ; pit != pend; ++pit)
  1383. {
  1384. std::string parameter;
  1385. std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
  1386. pit->begin();
  1387. const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
  1388. pit->end();
  1389. for ( ; it != end; ++it)
  1390. {
  1391. parameter += (*it)->Evaluate(context, dagChecker);
  1392. if (context->HadError)
  1393. {
  1394. return std::string();
  1395. }
  1396. }
  1397. parameters.push_back(parameter);
  1398. if (acceptsArbitraryContent
  1399. && parameters.size() == (unsigned int)numExpected - 1)
  1400. {
  1401. assert(pit != pend);
  1402. std::string lastParam = this->ProcessArbitraryContent(node, identifier,
  1403. context,
  1404. dagChecker,
  1405. pit + 1);
  1406. parameters.push_back(lastParam);
  1407. return std::string();
  1408. }
  1409. }
  1410. }
  1411. if ((numExpected > cmGeneratorExpressionNode::DynamicParameters
  1412. && (unsigned int)numExpected != parameters.size()))
  1413. {
  1414. if (numExpected == 0)
  1415. {
  1416. reportError(context, this->GetOriginalExpression(),
  1417. "$<" + identifier + "> expression requires no parameters.");
  1418. }
  1419. else if (numExpected == 1)
  1420. {
  1421. reportError(context, this->GetOriginalExpression(),
  1422. "$<" + identifier + "> expression requires "
  1423. "exactly one parameter.");
  1424. }
  1425. else
  1426. {
  1427. cmOStringStream e;
  1428. e << "$<" + identifier + "> expression requires "
  1429. << numExpected
  1430. << " comma separated parameters, but got "
  1431. << parameters.size() << " instead.";
  1432. reportError(context, this->GetOriginalExpression(), e.str());
  1433. }
  1434. return std::string();
  1435. }
  1436. if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters
  1437. && parameters.empty())
  1438. {
  1439. reportError(context, this->GetOriginalExpression(), "$<" + identifier
  1440. + "> expression requires at least one parameter.");
  1441. }
  1442. return std::string();
  1443. }
  1444. //----------------------------------------------------------------------------
  1445. static void deleteAll(const std::vector<cmGeneratorExpressionEvaluator*> &c)
  1446. {
  1447. std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
  1448. = c.begin();
  1449. const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
  1450. = c.end();
  1451. for ( ; it != end; ++it)
  1452. {
  1453. delete *it;
  1454. }
  1455. }
  1456. //----------------------------------------------------------------------------
  1457. GeneratorExpressionContent::~GeneratorExpressionContent()
  1458. {
  1459. deleteAll(this->IdentifierChildren);
  1460. typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
  1461. std::vector<EvaluatorVector>::const_iterator pit =
  1462. this->ParamChildren.begin();
  1463. const std::vector<EvaluatorVector>::const_iterator pend =
  1464. this->ParamChildren.end();
  1465. for ( ; pit != pend; ++pit)
  1466. {
  1467. deleteAll(*pit);
  1468. }
  1469. }