diff options
Diffstat (limited to 'Source/cmExportFileGenerator.cxx')
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 365 |
1 files changed, 318 insertions, 47 deletions
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 3f738cc..4a7c6f9 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -107,7 +107,8 @@ bool cmExportFileGenerator::GenerateImportFile() //---------------------------------------------------------------------------- void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, - const char* config) + const char* config, + std::vector<std::string> &missingTargets) { // Construct the property configuration suffix. std::string suffix = "_"; @@ -121,7 +122,297 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, } // Generate the per-config target information. - this->GenerateImportTargetsConfig(os, config, suffix); + this->GenerateImportTargetsConfig(os, config, suffix, missingTargets); +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, + cmTarget *target, + ImportPropertyMap &properties) +{ + const char *input = target->GetProperty(propName); + if (input) + { + properties[propName] = input; + } +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, + const char *outputName, + cmTarget *target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap &properties, + std::vector<std::string> &missingTargets) +{ + const char *input = target->GetProperty(propName); + if (input) + { + if (!*input) + { + // Set to empty + properties[outputName] = ""; + return; + } + + std::string prepro = cmGeneratorExpression::Preprocess(input, + preprocessRule); + if (!prepro.empty()) + { + this->ResolveTargetsInGeneratorExpressions(prepro, target, + missingTargets); + properties[outputName] = prepro; + } + } +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, + cmTarget *target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap &properties, + std::vector<std::string> &missingTargets) +{ + this->PopulateInterfaceProperty(propName, propName, target, preprocessRule, + properties, missingTargets); +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target, + std::ostream& os, + const ImportPropertyMap &properties) +{ + if (!properties.empty()) + { + std::string targetName = this->Namespace; + targetName += target->GetName(); + os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n"; + for(ImportPropertyMap::const_iterator pi = properties.begin(); + pi != properties.end(); ++pi) + { + os << " " << pi->first << " \"" << pi->second << "\"\n"; + } + os << ")\n\n"; + } +} + +//---------------------------------------------------------------------------- +bool +cmExportFileGenerator::AddTargetNamespace(std::string &input, + cmTarget* target, + std::vector<std::string> &missingTargets) +{ + cmMakefile *mf = target->GetMakefile(); + + cmTarget *tgt = mf->FindTargetToUse(input.c_str()); + if (!tgt) + { + return false; + } + + if(tgt->IsImported()) + { + return true; + } + if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) + { + input = this->Namespace + input; + } + else + { + std::string namespacedTarget; + this->HandleMissingTarget(namespacedTarget, missingTargets, + mf, target, tgt); + if (!namespacedTarget.empty()) + { + input = namespacedTarget; + } + } + return true; +} + +//---------------------------------------------------------------------------- +static bool isGeneratorExpression(const std::string &lib) +{ + const std::string::size_type openpos = lib.find("$<"); + return (openpos != std::string::npos) + && (lib.find(">", openpos) != std::string::npos); +} + +//---------------------------------------------------------------------------- +void +cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( + std::string &input, + cmTarget* target, + std::vector<std::string> &missingTargets, + FreeTargetsReplace replace) +{ + if (replace == NoReplaceFreeTargets) + { + this->ResolveTargetsInGeneratorExpression(input, target, missingTargets); + return; + } + std::vector<std::string> parts; + cmGeneratorExpression::Split(input, parts); + + std::string sep; + input = ""; + for(std::vector<std::string>::iterator li = parts.begin(); + li != parts.end(); ++li) + { + if (!isGeneratorExpression(*li)) + { + this->AddTargetNamespace(*li, target, missingTargets); + } + else + { + this->ResolveTargetsInGeneratorExpression( + *li, + target, + missingTargets); + } + input += sep + *li; + sep = ";"; + } +} + +//---------------------------------------------------------------------------- +void +cmExportFileGenerator::ResolveTargetsInGeneratorExpression( + std::string &input, + cmTarget* target, + std::vector<std::string> &missingTargets) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + + cmMakefile *mf = target->GetMakefile(); + std::string errorString; + + while((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != input.npos) + { + std::string::size_type nameStartPos = pos + + sizeof("$<TARGET_PROPERTY:") - 1; + std::string::size_type closePos = input.find(">", nameStartPos); + std::string::size_type commaPos = input.find(",", nameStartPos); + std::string::size_type nextOpenPos = input.find("$<", nameStartPos); + if (commaPos == input.npos // Implied 'this' target + || closePos == input.npos // Imcomplete expression. + || closePos < commaPos // Implied 'this' target + || nextOpenPos < commaPos) // Non-literal + { + lastPos = nameStartPos; + continue; + } + + std::string targetName = input.substr(nameStartPos, + commaPos - nameStartPos); + + if (!this->AddTargetNamespace(targetName, target, missingTargets)) + { + errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires " + "its first parameter to be a reachable target."; + break; + } + input.replace(nameStartPos, commaPos - nameStartPos, targetName); + lastPos = pos + targetName.size(); + } + if (!errorString.empty()) + { + mf->IssueMessage(cmake::FATAL_ERROR, errorString); + return; + } + + pos = 0; + lastPos = pos; + while((pos = input.find("$<TARGET_NAME:", lastPos)) != input.npos) + { + std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1; + std::string::size_type endPos = input.find(">", nameStartPos); + if (endPos == input.npos) + { + errorString = "$<TARGET_NAME:...> expression incomplete"; + break; + } + std::string targetName = input.substr(nameStartPos, + endPos - nameStartPos); + if(targetName.find("$<") != input.npos) + { + errorString = "$<TARGET_NAME:...> requires its parameter to be a " + "literal."; + break; + } + if (!this->AddTargetNamespace(targetName, target, missingTargets)) + { + errorString = "$<TARGET_NAME:...> requires its parameter to be a " + "reachable target."; + break; + } + input.replace(pos, endPos - pos + 1, targetName); + lastPos = endPos; + } + if (!errorString.empty()) + { + mf->IssueMessage(cmake::FATAL_ERROR, errorString); + } +} + +//---------------------------------------------------------------------------- +void +cmExportFileGenerator +::SetImportLinkInterface(const char* config, std::string const& suffix, + cmGeneratorExpression::PreprocessContext preprocessRule, + cmTarget* target, ImportPropertyMap& properties, + std::vector<std::string>& missingTargets) +{ + // Add the transitive link dependencies for this configuration. + cmTarget::LinkInterface const* iface = target->GetLinkInterface(config, + target); + if (!iface) + { + return; + } + + if (iface->ImplementationIsInterface) + { + this->SetImportLinkProperty(suffix, target, + "IMPORTED_LINK_INTERFACE_LIBRARIES", + iface->Libraries, properties, missingTargets); + return; + } + + const char *propContent; + + if (const char *prop_suffixed = target->GetProperty( + ("LINK_INTERFACE_LIBRARIES" + suffix).c_str())) + { + propContent = prop_suffixed; + } + else if (const char *prop = target->GetProperty( + "LINK_INTERFACE_LIBRARIES")) + { + propContent = prop; + } + else + { + return; + } + + if (!*propContent) + { + properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = ""; + return; + } + + std::string prepro = cmGeneratorExpression::Preprocess(propContent, + preprocessRule); + if (!prepro.empty()) + { + this->ResolveTargetsInGeneratorExpressions(prepro, target, + missingTargets, + ReplaceFreeTargets); + properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro; + } } //---------------------------------------------------------------------------- @@ -162,14 +453,13 @@ cmExportFileGenerator } // Add the transitive link dependencies for this configuration. - if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config)) + if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config, + target)) { this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", iface->Languages, properties, missingTargets); - this->SetImportLinkProperty(suffix, target, - "IMPORTED_LINK_INTERFACE_LIBRARIES", - iface->Libraries, properties, missingTargets); + this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps, properties, missingTargets); @@ -201,9 +491,6 @@ cmExportFileGenerator return; } - // Get the makefile in which to lookup target information. - cmMakefile* mf = target->GetMakefile(); - // Construct the property value. std::string link_libs; const char* sep = ""; @@ -214,33 +501,9 @@ cmExportFileGenerator link_libs += sep; sep = ";"; - // Append this entry. - if(cmTarget* tgt = mf->FindTargetToUse(li->c_str())) - { - // This is a target. - if(tgt->IsImported()) - { - // The target is imported (and therefore is not in the - // export). Append the raw name. - link_libs += *li; - } - else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) - { - // The target is in the export. Append it with the export - // namespace. - link_libs += this->Namespace; - link_libs += *li; - } - else - { - this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt); - } - } - else - { - // Append the raw name. - link_libs += *li; - } + std::string temp = *li; + this->AddTargetNamespace(temp, target, missingTargets); + link_libs += temp; } // Store the property. @@ -415,21 +678,29 @@ cmExportFileGenerator void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os, const std::vector<std::string>& missingTargets) { + if (missingTargets.empty()) + { + return; + } os << "# Make sure the targets which have been exported in some other \n" "# export set exist.\n"; + std::set<std::string> emitted; for(unsigned int i=0; i<missingTargets.size(); ++i) { - os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n" - << " IF(CMAKE_FIND_PACKAGE_NAME)\n" - << " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n" - << " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE " - << "\"Required imported target \\\"" << missingTargets[i] - << "\\\" not found ! \")\n" - << " ELSE()\n" - << " MESSAGE(FATAL_ERROR \"Required imported target \\\"" - << missingTargets[i] << "\\\" not found ! \")\n" - << " ENDIF()\n" - << "ENDIF()\n"; + if (emitted.insert(missingTargets[i]).second) + { + os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n" + << " IF(CMAKE_FIND_PACKAGE_NAME)\n" + << " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n" + << " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE " + << "\"Required imported target \\\"" << missingTargets[i] + << "\\\" not found ! \")\n" + << " ELSE()\n" + << " MESSAGE(FATAL_ERROR \"Required imported target \\\"" + << missingTargets[i] << "\\\" not found ! \")\n" + << " ENDIF()\n" + << "ENDIF()\n"; + } } os << "\n"; } |