| 4431 | int NumExpectedParameters() const override { return OneOrMoreParameters; } |
| 4432 | |
| 4433 | std::string Evaluate( |
| 4434 | std::vector<std::string> const& parameters, cm::GenEx::Evaluation* eval, |
| 4435 | GeneratorExpressionContent const* content, |
| 4436 | cmGeneratorExpressionDAGChecker* dagChecker) const override |
| 4437 | { |
| 4438 | cmGeneratorTarget const* target = eval->HeadTarget; |
| 4439 | if (!target) { |
| 4440 | reportError( |
| 4441 | eval, content->GetOriginalExpression(), |
| 4442 | "$<COMPILE_FEATURE> may only be used with binary targets. It may " |
| 4443 | "not be used with add_custom_command or add_custom_target."); |
| 4444 | return std::string(); |
| 4445 | } |
| 4446 | eval->HadHeadSensitiveCondition = true; |
| 4447 | |
| 4448 | using LangMap = std::map<std::string, cmList>; |
| 4449 | static LangMap availableFeatures; |
| 4450 | |
| 4451 | LangMap testedFeatures; |
| 4452 | cmStandardLevelResolver standardResolver(eval->Context.LG->GetMakefile()); |
| 4453 | for (std::string const& p : parameters) { |
| 4454 | std::string error; |
| 4455 | std::string lang; |
| 4456 | if (!standardResolver.CompileFeatureKnown( |
| 4457 | eval->HeadTarget->Target->GetName(), p, lang, &error)) { |
| 4458 | reportError(eval, content->GetOriginalExpression(), error); |
| 4459 | return std::string(); |
| 4460 | } |
| 4461 | testedFeatures[lang].push_back(p); |
| 4462 | |
| 4463 | if (availableFeatures.find(lang) == availableFeatures.end()) { |
| 4464 | cmValue featuresKnown = |
| 4465 | standardResolver.CompileFeaturesAvailable(lang, &error); |
| 4466 | if (!featuresKnown) { |
| 4467 | reportError(eval, content->GetOriginalExpression(), error); |
| 4468 | return std::string(); |
| 4469 | } |
| 4470 | availableFeatures[lang].assign(featuresKnown); |
| 4471 | } |
| 4472 | } |
| 4473 | |
| 4474 | bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries(); |
| 4475 | |
| 4476 | for (auto const& lit : testedFeatures) { |
| 4477 | std::vector<std::string> const& langAvailable = |
| 4478 | availableFeatures[lit.first]; |
| 4479 | cmValue standardDefault = eval->Context.LG->GetMakefile()->GetDefinition( |
| 4480 | cmStrCat("CMAKE_", lit.first, "_STANDARD_DEFAULT")); |
| 4481 | for (std::string const& it : lit.second) { |
| 4482 | if (!cm::contains(langAvailable, it)) { |
| 4483 | return "0"; |
| 4484 | } |
| 4485 | if (standardDefault && standardDefault->empty()) { |
| 4486 | // This compiler has no notion of language standard levels. |
| 4487 | // All features known for the language are always available. |
| 4488 | continue; |
| 4489 | } |
| 4490 | if (!standardResolver.HaveStandardAvailable( |
nothing calls this directly
no test coverage detected