cmGeneratorExpressionEvaluator.cxx 57 KB

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