| 3373 | int NumExpectedParameters() const override { return OneOrMoreParameters; } |
| 3374 | |
| 3375 | std::string Evaluate( |
| 3376 | std::vector<std::string> const& parameters, cm::GenEx::Evaluation* eval, |
| 3377 | GeneratorExpressionContent const* content, |
| 3378 | cmGeneratorExpressionDAGChecker* dagChecker) const override |
| 3379 | { |
| 3380 | using ForGenex = cmGeneratorExpressionDAGChecker::ForGenex; |
| 3381 | |
| 3382 | if (!eval->HeadTarget || !dagChecker || |
| 3383 | !dagChecker->EvaluatingLinkLibraries(nullptr, |
| 3384 | ForGenex::LINK_LIBRARY)) { |
| 3385 | reportError(eval, content->GetOriginalExpression(), |
| 3386 | "$<LINK_LIBRARY:...> may only be used with binary targets " |
| 3387 | "to specify link libraries through 'LINK_LIBRARIES', " |
| 3388 | "'INTERFACE_LINK_LIBRARIES', and " |
| 3389 | "'INTERFACE_LINK_LIBRARIES_DIRECT' properties."); |
| 3390 | return std::string(); |
| 3391 | } |
| 3392 | |
| 3393 | cmList list{ parameters.begin(), parameters.end() }; |
| 3394 | if (list.empty()) { |
| 3395 | reportError( |
| 3396 | eval, content->GetOriginalExpression(), |
| 3397 | "$<LINK_LIBRARY:...> expects a feature name as first argument."); |
| 3398 | return std::string(); |
| 3399 | } |
| 3400 | if (list.size() == 1) { |
| 3401 | // no libraries specified, ignore this genex |
| 3402 | return std::string(); |
| 3403 | } |
| 3404 | |
| 3405 | static cmsys::RegularExpression featureNameValidator("^[A-Za-z0-9_]+$"); |
| 3406 | auto const& feature = list.front(); |
| 3407 | if (!featureNameValidator.find(feature)) { |
| 3408 | reportError(eval, content->GetOriginalExpression(), |
| 3409 | cmStrCat("The feature name '", feature, |
| 3410 | "' contains invalid characters.")); |
| 3411 | return std::string(); |
| 3412 | } |
| 3413 | |
| 3414 | auto const LL_BEGIN = cmStrCat("<LINK_LIBRARY:", feature, '>'); |
| 3415 | auto const LL_END = cmStrCat("</LINK_LIBRARY:", feature, '>'); |
| 3416 | |
| 3417 | // filter out $<LINK_LIBRARY:..> tags with same feature |
| 3418 | // and raise an error for any different feature |
| 3419 | cm::erase_if(list, [&](std::string const& item) -> bool { |
| 3420 | return item == LL_BEGIN || item == LL_END; |
| 3421 | }); |
| 3422 | auto it = |
| 3423 | std::find_if(list.cbegin() + 1, list.cend(), |
| 3424 | [&feature](std::string const& item) -> bool { |
| 3425 | return cmHasPrefix(item, "<LINK_LIBRARY:"_s) && |
| 3426 | item.substr(14, item.find('>', 14) - 14) != feature; |
| 3427 | }); |
| 3428 | if (it != list.cend()) { |
| 3429 | reportError( |
| 3430 | eval, content->GetOriginalExpression(), |
| 3431 | "$<LINK_LIBRARY:...> with different features cannot be nested."); |
| 3432 | return std::string(); |
nothing calls this directly
no test coverage detected