cmGeneratorTarget_CompatibleInterface.cxx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. /* clang-format off */
  4. #include "cmGeneratorTarget.h"
  5. /* clang-format on */
  6. #include <algorithm>
  7. #include <cassert>
  8. #include <cerrno>
  9. #include <cstdlib>
  10. #include <cstring>
  11. #include <iterator>
  12. #include <map>
  13. #include <set>
  14. #include <sstream>
  15. #include <string>
  16. #include <utility>
  17. #include <vector>
  18. #include <cm/memory>
  19. #include <cmext/algorithm>
  20. #include "cmComputeLinkInformation.h"
  21. #include "cmGeneratorExpression.h"
  22. #include "cmList.h"
  23. #include "cmLocalGenerator.h"
  24. #include "cmMessageType.h"
  25. #include "cmRange.h"
  26. #include "cmStateTypes.h"
  27. #include "cmStringAlgorithms.h"
  28. #include "cmSystemTools.h"
  29. #include "cmValue.h"
  30. namespace {
  31. using UseTo = cmGeneratorTarget::UseTo;
  32. }
  33. const cmGeneratorTarget::CompatibleInterfacesBase&
  34. cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const
  35. {
  36. cmGeneratorTarget::CompatibleInterfaces& compat =
  37. this->CompatibleInterfacesMap[config];
  38. if (!compat.Done) {
  39. compat.Done = true;
  40. compat.PropsBool.insert("POSITION_INDEPENDENT_CODE");
  41. compat.PropsString.insert("AUTOUIC_OPTIONS");
  42. std::vector<cmGeneratorTarget const*> const& deps =
  43. this->GetLinkImplementationClosure(config, UseTo::Compile);
  44. for (cmGeneratorTarget const* li : deps) {
  45. #define CM_READ_COMPATIBLE_INTERFACE(X, x) \
  46. if (cmValue prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \
  47. cmList props(*prop); \
  48. compat.Props##x.insert(props.begin(), props.end()); \
  49. }
  50. CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool)
  51. CM_READ_COMPATIBLE_INTERFACE(STRING, String)
  52. CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin)
  53. CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax)
  54. #undef CM_READ_COMPATIBLE_INTERFACE
  55. }
  56. }
  57. return compat;
  58. }
  59. bool cmGeneratorTarget::IsLinkInterfaceDependentBoolProperty(
  60. const std::string& p, const std::string& config) const
  61. {
  62. if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
  63. this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
  64. return false;
  65. }
  66. return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0;
  67. }
  68. bool cmGeneratorTarget::IsLinkInterfaceDependentStringProperty(
  69. const std::string& p, const std::string& config) const
  70. {
  71. if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
  72. this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
  73. return false;
  74. }
  75. return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0;
  76. }
  77. bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMinProperty(
  78. const std::string& p, const std::string& config) const
  79. {
  80. if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
  81. this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
  82. return false;
  83. }
  84. return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0;
  85. }
  86. bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMaxProperty(
  87. const std::string& p, const std::string& config) const
  88. {
  89. if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
  90. this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
  91. return false;
  92. }
  93. return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0;
  94. }
  95. enum CompatibleType
  96. {
  97. BoolType,
  98. StringType,
  99. NumberMinType,
  100. NumberMaxType
  101. };
  102. template <typename PropertyType>
  103. PropertyType getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
  104. const std::string& prop,
  105. const std::string& config,
  106. CompatibleType, PropertyType*);
  107. template <>
  108. bool getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
  109. const std::string& prop,
  110. const std::string& config,
  111. CompatibleType /*unused*/,
  112. bool* /*unused*/)
  113. {
  114. return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
  115. }
  116. template <>
  117. const char* getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
  118. const std::string& prop,
  119. const std::string& config,
  120. CompatibleType t,
  121. const char** /*unused*/)
  122. {
  123. switch (t) {
  124. case BoolType:
  125. assert(false &&
  126. "String compatibility check function called for boolean");
  127. return nullptr;
  128. case StringType:
  129. return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
  130. case NumberMinType:
  131. return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config);
  132. case NumberMaxType:
  133. return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config);
  134. }
  135. assert(false && "Unreachable!");
  136. return nullptr;
  137. }
  138. template <typename PropertyType>
  139. void checkPropertyConsistency(cmGeneratorTarget const* depender,
  140. cmGeneratorTarget const* dependee,
  141. const std::string& propName,
  142. std::set<std::string>& emitted,
  143. const std::string& config, CompatibleType t,
  144. PropertyType* /*unused*/)
  145. {
  146. cmValue prop = dependee->GetProperty(propName);
  147. if (!prop) {
  148. return;
  149. }
  150. cmList props{ *prop };
  151. std::string pdir =
  152. cmStrCat(cmSystemTools::GetCMakeRoot(), "/Help/prop_tgt/");
  153. for (std::string const& p : props) {
  154. std::string pname = cmSystemTools::HelpFileName(p);
  155. std::string pfile = pdir + pname + ".rst";
  156. if (cmSystemTools::FileExists(pfile, true)) {
  157. std::ostringstream e;
  158. e << "Target \"" << dependee->GetName() << "\" has property \"" << p
  159. << "\" listed in its " << propName
  160. << " property. "
  161. "This is not allowed. Only user-defined properties may appear "
  162. "listed in the "
  163. << propName << " property.";
  164. depender->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
  165. e.str());
  166. return;
  167. }
  168. if (emitted.insert(p).second) {
  169. getLinkInterfaceDependentProperty<PropertyType>(depender, p, config, t,
  170. nullptr);
  171. if (cmSystemTools::GetErrorOccurredFlag()) {
  172. return;
  173. }
  174. }
  175. }
  176. }
  177. namespace {
  178. std::string intersect(const std::set<std::string>& s1,
  179. const std::set<std::string>& s2)
  180. {
  181. std::set<std::string> intersect;
  182. std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),
  183. std::inserter(intersect, intersect.begin()));
  184. if (!intersect.empty()) {
  185. return *intersect.begin();
  186. }
  187. return "";
  188. }
  189. std::string intersect(const std::set<std::string>& s1,
  190. const std::set<std::string>& s2,
  191. const std::set<std::string>& s3)
  192. {
  193. std::string result;
  194. result = intersect(s1, s2);
  195. if (!result.empty()) {
  196. return result;
  197. }
  198. result = intersect(s1, s3);
  199. if (!result.empty()) {
  200. return result;
  201. }
  202. return intersect(s2, s3);
  203. }
  204. std::string intersect(const std::set<std::string>& s1,
  205. const std::set<std::string>& s2,
  206. const std::set<std::string>& s3,
  207. const std::set<std::string>& s4)
  208. {
  209. std::string result;
  210. result = intersect(s1, s2);
  211. if (!result.empty()) {
  212. return result;
  213. }
  214. result = intersect(s1, s3);
  215. if (!result.empty()) {
  216. return result;
  217. }
  218. result = intersect(s1, s4);
  219. if (!result.empty()) {
  220. return result;
  221. }
  222. return intersect(s2, s3, s4);
  223. }
  224. }
  225. void cmGeneratorTarget::CheckPropertyCompatibility(
  226. cmComputeLinkInformation& info, const std::string& config) const
  227. {
  228. const cmComputeLinkInformation::ItemVector& deps = info.GetItems();
  229. std::set<std::string> emittedBools;
  230. static const std::string strBool = "COMPATIBLE_INTERFACE_BOOL";
  231. std::set<std::string> emittedStrings;
  232. static const std::string strString = "COMPATIBLE_INTERFACE_STRING";
  233. std::set<std::string> emittedMinNumbers;
  234. static const std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN";
  235. std::set<std::string> emittedMaxNumbers;
  236. static const std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX";
  237. for (auto const& dep : deps) {
  238. if (!dep.Target || dep.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
  239. continue;
  240. }
  241. checkPropertyConsistency<bool>(this, dep.Target, strBool, emittedBools,
  242. config, BoolType, nullptr);
  243. if (cmSystemTools::GetErrorOccurredFlag()) {
  244. return;
  245. }
  246. checkPropertyConsistency<const char*>(this, dep.Target, strString,
  247. emittedStrings, config, StringType,
  248. nullptr);
  249. if (cmSystemTools::GetErrorOccurredFlag()) {
  250. return;
  251. }
  252. checkPropertyConsistency<const char*>(this, dep.Target, strNumMin,
  253. emittedMinNumbers, config,
  254. NumberMinType, nullptr);
  255. if (cmSystemTools::GetErrorOccurredFlag()) {
  256. return;
  257. }
  258. checkPropertyConsistency<const char*>(this, dep.Target, strNumMax,
  259. emittedMaxNumbers, config,
  260. NumberMaxType, nullptr);
  261. if (cmSystemTools::GetErrorOccurredFlag()) {
  262. return;
  263. }
  264. }
  265. std::string prop = intersect(emittedBools, emittedStrings, emittedMinNumbers,
  266. emittedMaxNumbers);
  267. if (!prop.empty()) {
  268. // Use a sorted std::vector to keep the error message sorted.
  269. std::vector<std::string> props;
  270. auto i = emittedBools.find(prop);
  271. if (i != emittedBools.end()) {
  272. props.push_back(strBool);
  273. }
  274. i = emittedStrings.find(prop);
  275. if (i != emittedStrings.end()) {
  276. props.push_back(strString);
  277. }
  278. i = emittedMinNumbers.find(prop);
  279. if (i != emittedMinNumbers.end()) {
  280. props.push_back(strNumMin);
  281. }
  282. i = emittedMaxNumbers.find(prop);
  283. if (i != emittedMaxNumbers.end()) {
  284. props.push_back(strNumMax);
  285. }
  286. std::sort(props.begin(), props.end());
  287. std::string propsString = cmStrCat(
  288. cmJoin(cmMakeRange(props).retreat(1), ", "), " and the ", props.back());
  289. std::ostringstream e;
  290. e << "Property \"" << prop << "\" appears in both the " << propsString
  291. << " property in the dependencies of target \"" << this->GetName()
  292. << "\". This is not allowed. A property may only require "
  293. "compatibility "
  294. "in a boolean interpretation, a numeric minimum, a numeric maximum "
  295. "or a "
  296. "string interpretation, but not a mixture.";
  297. this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str());
  298. }
  299. }
  300. template <typename PropertyType>
  301. std::string valueAsString(PropertyType);
  302. template <>
  303. std::string valueAsString<bool>(bool value)
  304. {
  305. return value ? "TRUE" : "FALSE";
  306. }
  307. template <>
  308. std::string valueAsString<const char*>(const char* value)
  309. {
  310. return value ? value : "(unset)";
  311. }
  312. template <>
  313. std::string valueAsString<std::string>(std::string value)
  314. {
  315. return value;
  316. }
  317. template <>
  318. std::string valueAsString<cmValue>(cmValue value)
  319. {
  320. return value ? *value : std::string("(unset)");
  321. }
  322. template <>
  323. std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
  324. {
  325. return "(unset)";
  326. }
  327. static std::string compatibilityType(CompatibleType t)
  328. {
  329. switch (t) {
  330. case BoolType:
  331. return "Boolean compatibility";
  332. case StringType:
  333. return "String compatibility";
  334. case NumberMaxType:
  335. return "Numeric maximum compatibility";
  336. case NumberMinType:
  337. return "Numeric minimum compatibility";
  338. }
  339. assert(false && "Unreachable!");
  340. return "";
  341. }
  342. static std::string compatibilityAgree(CompatibleType t, bool dominant)
  343. {
  344. switch (t) {
  345. case BoolType:
  346. case StringType:
  347. return dominant ? "(Disagree)\n" : "(Agree)\n";
  348. case NumberMaxType:
  349. case NumberMinType:
  350. return dominant ? "(Dominant)\n" : "(Ignored)\n";
  351. }
  352. assert(false && "Unreachable!");
  353. return "";
  354. }
  355. template <typename PropertyType>
  356. PropertyType getTypedProperty(
  357. cmGeneratorTarget const* tgt, const std::string& prop,
  358. cmGeneratorExpressionInterpreter* genexInterpreter = nullptr);
  359. template <>
  360. bool getTypedProperty<bool>(cmGeneratorTarget const* tgt,
  361. const std::string& prop,
  362. cmGeneratorExpressionInterpreter* genexInterpreter)
  363. {
  364. if (!genexInterpreter) {
  365. return tgt->GetPropertyAsBool(prop);
  366. }
  367. cmValue value = tgt->GetProperty(prop);
  368. return cmIsOn(genexInterpreter->Evaluate(value ? *value : "", prop));
  369. }
  370. template <>
  371. const char* getTypedProperty<const char*>(
  372. cmGeneratorTarget const* tgt, const std::string& prop,
  373. cmGeneratorExpressionInterpreter* genexInterpreter)
  374. {
  375. cmValue value = tgt->GetProperty(prop);
  376. if (!genexInterpreter) {
  377. return value.GetCStr();
  378. }
  379. return genexInterpreter->Evaluate(value ? *value : "", prop).c_str();
  380. }
  381. template <>
  382. std::string getTypedProperty<std::string>(
  383. cmGeneratorTarget const* tgt, const std::string& prop,
  384. cmGeneratorExpressionInterpreter* genexInterpreter)
  385. {
  386. cmValue value = tgt->GetProperty(prop);
  387. if (!genexInterpreter) {
  388. return valueAsString(value);
  389. }
  390. return genexInterpreter->Evaluate(value ? *value : "", prop);
  391. }
  392. template <typename PropertyType>
  393. PropertyType impliedValue(PropertyType);
  394. template <>
  395. bool impliedValue<bool>(bool /*unused*/)
  396. {
  397. return false;
  398. }
  399. template <>
  400. const char* impliedValue<const char*>(const char* /*unused*/)
  401. {
  402. return "";
  403. }
  404. template <>
  405. std::string impliedValue<std::string>(std::string /*unused*/) // NOLINT(*)
  406. {
  407. return std::string();
  408. }
  409. template <typename PropertyType>
  410. std::pair<bool, PropertyType> consistentProperty(PropertyType lhs,
  411. PropertyType rhs,
  412. CompatibleType t);
  413. template <>
  414. std::pair<bool, bool> consistentProperty(bool lhs, bool rhs,
  415. CompatibleType /*unused*/)
  416. {
  417. return { lhs == rhs, lhs };
  418. }
  419. static std::pair<bool, const char*> consistentStringProperty(const char* lhs,
  420. const char* rhs)
  421. {
  422. const bool b = strcmp(lhs, rhs) == 0;
  423. return { b, b ? lhs : nullptr };
  424. }
  425. static std::pair<bool, std::string> consistentStringProperty(
  426. const std::string& lhs, const std::string& rhs)
  427. {
  428. const bool b = lhs == rhs;
  429. return { b, b ? lhs : valueAsString(nullptr) };
  430. }
  431. static std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
  432. const char* rhs,
  433. CompatibleType t)
  434. {
  435. char* pEnd;
  436. long lnum = strtol(lhs, &pEnd, 0);
  437. if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) {
  438. return { false, nullptr };
  439. }
  440. long rnum = strtol(rhs, &pEnd, 0);
  441. if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) {
  442. return { false, nullptr };
  443. }
  444. if (t == NumberMaxType) {
  445. return { true, std::max(lnum, rnum) == lnum ? lhs : rhs };
  446. }
  447. return { true, std::min(lnum, rnum) == lnum ? lhs : rhs };
  448. }
  449. template <>
  450. std::pair<bool, const char*> consistentProperty(const char* lhs,
  451. const char* rhs,
  452. CompatibleType t)
  453. {
  454. if (!lhs && !rhs) {
  455. return { true, lhs };
  456. }
  457. if (!lhs) {
  458. return { true, rhs };
  459. }
  460. if (!rhs) {
  461. return { true, lhs };
  462. }
  463. switch (t) {
  464. case BoolType: {
  465. bool same = cmIsOn(lhs) == cmIsOn(rhs);
  466. return { same, same ? lhs : nullptr };
  467. }
  468. case StringType:
  469. return consistentStringProperty(lhs, rhs);
  470. case NumberMinType:
  471. case NumberMaxType:
  472. return consistentNumberProperty(lhs, rhs, t);
  473. }
  474. assert(false && "Unreachable!");
  475. return { false, nullptr };
  476. }
  477. static std::pair<bool, std::string> consistentProperty(const std::string& lhs,
  478. const std::string& rhs,
  479. CompatibleType t)
  480. {
  481. const std::string null_ptr = valueAsString(nullptr);
  482. if (lhs == null_ptr && rhs == null_ptr) {
  483. return { true, lhs };
  484. }
  485. if (lhs == null_ptr) {
  486. return { true, rhs };
  487. }
  488. if (rhs == null_ptr) {
  489. return { true, lhs };
  490. }
  491. switch (t) {
  492. case BoolType: {
  493. bool same = cmIsOn(lhs) == cmIsOn(rhs);
  494. return { same, same ? lhs : null_ptr };
  495. }
  496. case StringType:
  497. return consistentStringProperty(lhs, rhs);
  498. case NumberMinType:
  499. case NumberMaxType: {
  500. auto value = consistentNumberProperty(lhs.c_str(), rhs.c_str(), t);
  501. return { value.first,
  502. value.first ? std::string(value.second) : null_ptr };
  503. }
  504. }
  505. assert(false && "Unreachable!");
  506. return { false, null_ptr };
  507. }
  508. template <typename PropertyType>
  509. PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
  510. const std::string& p,
  511. const std::string& config,
  512. const char* defaultValue,
  513. CompatibleType t,
  514. PropertyType* /*unused*/)
  515. {
  516. PropertyType propContent = getTypedProperty<PropertyType>(tgt, p);
  517. std::vector<std::string> headPropKeys = tgt->GetPropertyKeys();
  518. const bool explicitlySet = cm::contains(headPropKeys, p);
  519. const bool impliedByUse = tgt->IsNullImpliedByLinkLibraries(p);
  520. assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet));
  521. std::vector<cmGeneratorTarget const*> const& deps =
  522. tgt->GetLinkImplementationClosure(config, UseTo::Compile);
  523. if (deps.empty()) {
  524. return propContent;
  525. }
  526. bool propInitialized = explicitlySet;
  527. std::string report = cmStrCat(" * Target \"", tgt->GetName());
  528. if (explicitlySet) {
  529. report += "\" has property content \"";
  530. report += valueAsString<PropertyType>(propContent);
  531. report += "\"\n";
  532. } else if (impliedByUse) {
  533. report += "\" property is implied by use.\n";
  534. } else {
  535. report += "\" property not set.\n";
  536. }
  537. std::string interfaceProperty = "INTERFACE_" + p;
  538. std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter;
  539. if (p == "POSITION_INDEPENDENT_CODE") {
  540. // Corresponds to EvaluatingPICExpression.
  541. genexInterpreter = cm::make_unique<cmGeneratorExpressionInterpreter>(
  542. tgt->GetLocalGenerator(), config, tgt);
  543. }
  544. for (cmGeneratorTarget const* theTarget : deps) {
  545. // An error should be reported if one dependency
  546. // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
  547. // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the
  548. // target itself has a POSITION_INDEPENDENT_CODE which disagrees
  549. // with a dependency.
  550. std::vector<std::string> propKeys = theTarget->GetPropertyKeys();
  551. const bool ifaceIsSet = cm::contains(propKeys, interfaceProperty);
  552. PropertyType ifacePropContent = getTypedProperty<PropertyType>(
  553. theTarget, interfaceProperty, genexInterpreter.get());
  554. std::string reportEntry;
  555. if (ifaceIsSet) {
  556. reportEntry += " * Target \"";
  557. reportEntry += theTarget->GetName();
  558. reportEntry += "\" property value \"";
  559. reportEntry += valueAsString<PropertyType>(ifacePropContent);
  560. reportEntry += "\" ";
  561. }
  562. if (explicitlySet) {
  563. if (ifaceIsSet) {
  564. std::pair<bool, PropertyType> consistent =
  565. consistentProperty(propContent, ifacePropContent, t);
  566. report += reportEntry;
  567. report += compatibilityAgree(t, propContent != consistent.second);
  568. if (!consistent.first) {
  569. std::ostringstream e;
  570. e << "Property " << p << " on target \"" << tgt->GetName()
  571. << "\" does\nnot match the "
  572. "INTERFACE_"
  573. << p
  574. << " property requirement\nof "
  575. "dependency \""
  576. << theTarget->GetName() << "\".\n";
  577. cmSystemTools::Error(e.str());
  578. break;
  579. }
  580. propContent = consistent.second;
  581. continue;
  582. }
  583. // Explicitly set on target and not set in iface. Can't disagree.
  584. continue;
  585. }
  586. if (impliedByUse) {
  587. propContent = impliedValue<PropertyType>(propContent);
  588. if (ifaceIsSet) {
  589. std::pair<bool, PropertyType> consistent =
  590. consistentProperty(propContent, ifacePropContent, t);
  591. report += reportEntry;
  592. report += compatibilityAgree(t, propContent != consistent.second);
  593. if (!consistent.first) {
  594. std::ostringstream e;
  595. e << "Property " << p << " on target \"" << tgt->GetName()
  596. << "\" is\nimplied to be " << defaultValue
  597. << " because it was used to determine the link libraries\n"
  598. "already. The INTERFACE_"
  599. << p << " property on\ndependency \"" << theTarget->GetName()
  600. << "\" is in conflict.\n";
  601. cmSystemTools::Error(e.str());
  602. break;
  603. }
  604. propContent = consistent.second;
  605. continue;
  606. }
  607. // Implicitly set on target and not set in iface. Can't disagree.
  608. continue;
  609. }
  610. if (ifaceIsSet) {
  611. if (propInitialized) {
  612. std::pair<bool, PropertyType> consistent =
  613. consistentProperty(propContent, ifacePropContent, t);
  614. report += reportEntry;
  615. report += compatibilityAgree(t, propContent != consistent.second);
  616. if (!consistent.first) {
  617. std::ostringstream e;
  618. e << "The INTERFACE_" << p << " property of \""
  619. << theTarget->GetName() << "\" does\nnot agree with the value of "
  620. << p << " already determined\nfor \"" << tgt->GetName() << "\".\n";
  621. cmSystemTools::Error(e.str());
  622. break;
  623. }
  624. propContent = consistent.second;
  625. continue;
  626. }
  627. report += reportEntry + "(Interface set)\n";
  628. propContent = ifacePropContent;
  629. propInitialized = true;
  630. } else {
  631. // Not set. Nothing to agree on.
  632. continue;
  633. }
  634. }
  635. tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent),
  636. report, compatibilityType(t));
  637. return propContent;
  638. }
  639. bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty(
  640. const std::string& p, const std::string& config) const
  641. {
  642. return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
  643. BoolType, nullptr);
  644. }
  645. std::string cmGeneratorTarget::GetLinkInterfaceDependentStringAsBoolProperty(
  646. const std::string& p, const std::string& config) const
  647. {
  648. return checkInterfacePropertyCompatibility<std::string>(
  649. this, p, config, "FALSE", BoolType, nullptr);
  650. }
  651. const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty(
  652. const std::string& p, const std::string& config) const
  653. {
  654. return checkInterfacePropertyCompatibility<const char*>(
  655. this, p, config, "empty", StringType, nullptr);
  656. }
  657. const char* cmGeneratorTarget::GetLinkInterfaceDependentNumberMinProperty(
  658. const std::string& p, const std::string& config) const
  659. {
  660. return checkInterfacePropertyCompatibility<const char*>(
  661. this, p, config, "empty", NumberMinType, nullptr);
  662. }
  663. const char* cmGeneratorTarget::GetLinkInterfaceDependentNumberMaxProperty(
  664. const std::string& p, const std::string& config) const
  665. {
  666. return checkInterfacePropertyCompatibility<const char*>(
  667. this, p, config, "empty", NumberMaxType, nullptr);
  668. }