cmGeneratorExpressionNode.cxx 61 KB

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