| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #include "cmExportInstallFileGenerator.h" | |
| #include <algorithm> | |
| #include <cassert> | |
| #include <cstddef> | |
| #include <memory> | |
| #include <set> | |
| #include <sstream> | |
| #include <utility> | |
| #include "cmExportSet.h" | |
| #include "cmGeneratedFileStream.h" | |
| #include "cmGeneratorFileSet.h" | |
| #include "cmGeneratorFileSets.h" | |
| #include "cmGeneratorTarget.h" | |
| #include "cmGlobalGenerator.h" | |
| #include "cmInstallTargetGenerator.h" | |
| #include "cmList.h" | |
| #include "cmLocalGenerator.h" | |
| #include "cmMakefile.h" | |
| #include "cmMessageType.h" | |
| #include "cmStringAlgorithms.h" | |
| #include "cmSystemTools.h" | |
| #include "cmTarget.h" | |
| #include "cmTargetExport.h" | |
| #include "cmValue.h" | |
| cmExportInstallFileGenerator::cmExportInstallFileGenerator( | |
| cmInstallExportGenerator* iegen) | |
| : IEGen(iegen) | |
| { | |
| } | |
| void cmExportInstallFileGenerator::ReplaceInstallPrefix( | |
| std::string& input) const | |
| { | |
| cmGeneratorExpression::ReplaceInstallPrefix(input, this->GetInstallPrefix()); | |
| } | |
| void cmExportInstallFileGenerator::PopulateImportProperties( | |
| std::string const& config, std::string const& suffix, | |
| cmTargetExport const* targetExport, ImportPropertyMap& properties, | |
| std::set<std::string>& importedLocations) | |
| { | |
| this->SetImportLocationProperty(config, suffix, | |
| targetExport->ArchiveGenerator, properties, | |
| importedLocations); | |
| this->SetImportLocationProperty(config, suffix, | |
| targetExport->LibraryGenerator, properties, | |
| importedLocations); | |
| this->SetImportLocationProperty(config, suffix, | |
| targetExport->RuntimeGenerator, properties, | |
| importedLocations); | |
| this->SetImportLocationProperty(config, suffix, | |
| targetExport->ObjectsGenerator, properties, | |
| importedLocations); | |
| this->SetImportLocationProperty(config, suffix, | |
| targetExport->FrameworkGenerator, properties, | |
| importedLocations); | |
| this->SetImportLocationProperty(config, suffix, | |
| targetExport->BundleGenerator, properties, | |
| importedLocations); | |
| // If any file location was set for the target add it to the | |
| // import file. | |
| if (!properties.empty()) { | |
| // Get the rest of the target details. | |
| cmGeneratorTarget const* const gtgt = targetExport->Target; | |
| this->SetImportDetailProperties(config, suffix, gtgt, properties); | |
| // TODO: PUBLIC_HEADER_LOCATION | |
| // This should wait until the build feature propagation stuff is done. | |
| // Then this can be a propagated include directory. | |
| // this->GenerateImportProperty(config, te->HeaderGenerator, properties); | |
| } | |
| } | |
| std::string cmExportInstallFileGenerator::GetImportXcFrameworkLocation( | |
| std::string const& config, cmTargetExport const* targetExport) const | |
| { | |
| std::string importedXcFrameworkLocation = targetExport->XcFrameworkLocation; | |
| if (!importedXcFrameworkLocation.empty()) { | |
| importedXcFrameworkLocation = cmGeneratorExpression::Preprocess( | |
| importedXcFrameworkLocation, | |
| cmGeneratorExpression::PreprocessContext::InstallInterface, | |
| this->GetImportPrefixWithSlash()); | |
| importedXcFrameworkLocation = cmGeneratorExpression::Evaluate( | |
| importedXcFrameworkLocation, targetExport->Target->GetLocalGenerator(), | |
| config, targetExport->Target, nullptr, targetExport->Target); | |
| if (!importedXcFrameworkLocation.empty() && | |
| !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) && | |
| !cmHasPrefix(importedXcFrameworkLocation, | |
| this->GetImportPrefixWithSlash())) { | |
| return cmStrCat(this->GetImportPrefixWithSlash(), | |
| importedXcFrameworkLocation); | |
| } | |
| } | |
| return importedXcFrameworkLocation; | |
| } | |
| bool cmExportInstallFileGenerator::GenerateImportFileConfig( | |
| std::string const& config) | |
| { | |
| // Skip configurations not enabled for this export. | |
| if (!this->IEGen->InstallsForConfig(config)) { | |
| return true; | |
| } | |
| // Construct the name of the file to generate. | |
| std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase, | |
| this->GetConfigFileNameSeparator()); | |
| if (!config.empty()) { | |
| fileName += cmSystemTools::LowerCase(config); | |
| } else { | |
| fileName += "noconfig"; | |
| } | |
| fileName += this->FileExt; | |
| // Open the output file to generate it. | |
| cmGeneratedFileStream exportFileStream(fileName, true); | |
| if (!exportFileStream) { | |
| std::string se = cmSystemTools::GetLastSystemError(); | |
| cmSystemTools::Error( | |
| cmStrCat("cannot write to file \"", fileName, "\": ", se)); | |
| return false; | |
| } | |
| exportFileStream.SetCopyIfDifferent(true); | |
| std::ostream& os = exportFileStream; | |
| // Generate the per-config target information. | |
| this->GenerateImportConfig(os, config); | |
| // Record this per-config import file. | |
| this->ConfigImportFiles[config] = fileName; | |
| return true; | |
| } | |
| void cmExportInstallFileGenerator::SetImportLocationProperty( | |
| std::string const& config, std::string const& suffix, | |
| cmInstallTargetGenerator* itgen, ImportPropertyMap& properties, | |
| std::set<std::string>& importedLocations) | |
| { | |
| // Skip rules that do not match this configuration. | |
| if (!(itgen && itgen->InstallsForConfig(config))) { | |
| return; | |
| } | |
| // Get the target to be installed. | |
| cmGeneratorTarget* target = itgen->GetTarget(); | |
| // Construct the installed location of the target. | |
| std::string dest = itgen->GetDestination(config); | |
| std::string value; | |
| if (!cmSystemTools::FileIsFullPath(dest)) { | |
| // The target is installed relative to the installation prefix. | |
| value = std::string{ this->GetImportPrefixWithSlash() }; | |
| } | |
| value += dest; | |
| value += "/"; | |
| if (itgen->IsImportLibrary()) { | |
| // Construct the property name. | |
| std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix); | |
| // Append the installed file name. | |
| value += cmInstallTargetGenerator::GetInstallFilename( | |
| target, config, cmInstallTargetGenerator::NameImplibReal); | |
| // Store the property. | |
| properties[prop] = value; | |
| importedLocations.insert(prop); | |
| } else if (itgen->GetTarget()->GetType() == cm::TargetType::OBJECT_LIBRARY) { | |
| // Construct the property name. | |
| std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix); | |
| // Compute all the object files inside this target and setup | |
| // IMPORTED_OBJECTS as a list of object files | |
| std::vector<std::string> objects; | |
| itgen->GetInstallObjectNames(config, objects); | |
| for (std::string& obj : objects) { | |
| obj = cmStrCat(value, std::move(obj)); | |
| } | |
| // Store the property. | |
| properties[prop] = cmList::to_string(objects); | |
| importedLocations.insert(prop); | |
| } else { | |
| if (target->IsFrameworkOnApple() && target->HasImportLibrary(config)) { | |
| // store as well IMPLIB value | |
| auto importProp = cmStrCat("IMPORTED_IMPLIB", suffix); | |
| auto importValue = | |
| cmStrCat(value, | |
| cmInstallTargetGenerator::GetInstallFilename( | |
| target, config, cmInstallTargetGenerator::NameImplibReal)); | |
| // Store the property. | |
| properties[importProp] = importValue; | |
| importedLocations.insert(importProp); | |
| } | |
| // Construct the property name. | |
| std::string prop = cmStrCat("IMPORTED_LOCATION", suffix); | |
| // Append the installed file name. | |
| if (target->IsAppBundleOnApple()) { | |
| value += cmInstallTargetGenerator::GetInstallFilename(target, config); | |
| value += ".app/"; | |
| if (!target->Makefile->PlatformIsAppleEmbedded()) { | |
| value += "Contents/MacOS/"; | |
| } | |
| value += cmInstallTargetGenerator::GetInstallFilename(target, config); | |
| } else { | |
| value += cmInstallTargetGenerator::GetInstallFilename( | |
| target, config, cmInstallTargetGenerator::NameReal); | |
| } | |
| // Store the property. | |
| properties[prop] = value; | |
| importedLocations.insert(prop); | |
| } | |
| } | |
| cm::TargetType cmExportInstallFileGenerator::GetExportTargetType( | |
| cmTargetExport const* targetExport) const | |
| { | |
| cm::TargetType targetType = targetExport->Target->GetType(); | |
| // An OBJECT library installed with no OBJECTS DESTINATION | |
| // is transformed to an INTERFACE library. | |
| if (targetType == cm::TargetType::OBJECT_LIBRARY && | |
| !targetExport->ObjectsGenerator) { | |
| targetType = cm::TargetType::INTERFACE_LIBRARY; | |
| } | |
| return targetType; | |
| } | |
| std::string const& cmExportInstallFileGenerator::GetExportName() const | |
| { | |
| return this->GetExportSet()->GetName(); | |
| } | |
| void cmExportInstallFileGenerator::HandleMissingTarget( | |
| std::string& link_libs, cmGeneratorTarget const* depender, | |
| cmGeneratorTarget* dependee) | |
| { | |
| auto const& exportInfo = this->FindExportInfo(dependee); | |
| if (exportInfo.Namespaces.size() == 1 && exportInfo.Sets.size() == 1) { | |
| std::string missingTarget = *exportInfo.Namespaces.begin(); | |
| missingTarget += dependee->GetExportName(); | |
| link_libs += missingTarget; | |
| this->MissingTargets.emplace_back(std::move(missingTarget)); | |
| } else { | |
| // All exported targets should be known here and should be unique. | |
| // This is probably user-error. | |
| this->ComplainAboutMissingTarget(depender, dependee, exportInfo); | |
| } | |
| } | |
| cmExportFileGenerator::ExportInfo cmExportInstallFileGenerator::FindExportInfo( | |
| cmGeneratorTarget const* target) const | |
| { | |
| return target->GetLocalGenerator() | |
| ->GetGlobalGenerator() | |
| ->FindInstallExportInfo(target); | |
| } | |
| void cmExportInstallFileGenerator::ComplainAboutMissingTarget( | |
| cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee, | |
| ExportInfo const& exportInfo) const | |
| { | |
| std::ostringstream e; | |
| e << "install(" << this->IEGen->InstallSubcommand() << " \"" | |
| << this->GetExportName() << "\" ...) " << "includes target \"" | |
| << depender->GetName() << "\" which requires target \"" | |
| << dependee->GetName() << "\" "; | |
| if (exportInfo.Sets.empty()) { | |
| e << "that is not in any export set."; | |
| } else { | |
| if (exportInfo.Sets.size() == 1) { | |
| e << "that is not in this export set, but in another export set which " | |
| "is " | |
| "exported multiple times with different namespaces: "; | |
| } else { | |
| e << "that is not in this export set, but in multiple other export " | |
| "sets: "; | |
| } | |
| e << cmJoin(exportInfo.Files, ", ") << ".\n" | |
| << "An exported target cannot depend upon another target which is " | |
| "exported in more than one export set or with more than one " | |
| "namespace. " | |
| "Consider consolidating the exports of the \"" | |
| << dependee->GetName() << "\" target to a single export."; | |
| } | |
| this->ReportError(e.str()); | |
| } | |
| void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget( | |
| std::string const& targetName) const | |
| { | |
| this->ReportError(cmStrCat("install(", this->IEGen->InstallSubcommand(), | |
| " \"", this->GetExportName(), | |
| "\" ...) includes target \"", targetName, | |
| "\" more than once in the export set.")); | |
| } | |
| void cmExportInstallFileGenerator::IssueMessage( | |
| MessageType type, std::string const& message) const | |
| { | |
| cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator(); | |
| lg->GetMakefile()->IssueMessage(type, message); | |
| } | |
| void cmExportInstallFileGenerator::IssueDiagnostic( | |
| cmDiagnosticCategory category, std::string const& message) const | |
| { | |
| cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator(); | |
| lg->GetMakefile()->IssueDiagnostic(category, message, | |
| this->IEGen->GetDiagnosticContext()); | |
| } | |
| std::string cmExportInstallFileGenerator::InstallNameDir( | |
| cmGeneratorTarget const* target, std::string const& config) | |
| { | |
| std::string install_name_dir; | |
| cmMakefile* mf = target->Target->GetMakefile(); | |
| if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { | |
| auto const& prefix = this->GetInstallPrefix(); | |
| install_name_dir = target->GetInstallNameDirForInstallTree(config, prefix); | |
| } | |
| return install_name_dir; | |
| } | |
| std::string cmExportInstallFileGenerator::GetCxxModuleFile() const | |
| { | |
| return this->GetCxxModuleFile(this->GetExportSet()->GetName()); | |
| } | |
| bool cmExportInstallFileGenerator::CollectExports( | |
| std::function<void(cmTargetExport const*)> const& visitor) | |
| { | |
| auto pred = [&](std::unique_ptr<cmTargetExport> const& te) -> bool { | |
| if (te->NamelinkOnly) { | |
| return true; | |
| } | |
| if (this->ExportedTargets.insert(te->Target).second) { | |
| visitor(te.get()); | |
| return true; | |
| } | |
| this->ComplainAboutDuplicateTarget(te->Target->GetName()); | |
| return false; | |
| }; | |
| auto const& targets = this->GetExportSet()->GetTargetExports(); | |
| return std::all_of(targets.begin(), targets.end(), pred); | |
| } | |
| bool cmExportInstallFileGenerator::PopulateInterfaceProperties( | |
| cmTargetExport const* targetExport, ImportPropertyMap& properties) | |
| { | |
| cmGeneratorTarget const* const gt = targetExport->Target; | |
| std::string includesDestinationDirs; | |
| this->PopulateSystemIncludeDirectoriesInterface( | |
| gt, cmGeneratorExpression::InstallInterface, properties); | |
| this->PopulateIncludeDirectoriesInterface( | |
| gt, cmGeneratorExpression::InstallInterface, properties, *targetExport, | |
| includesDestinationDirs); | |
| this->PopulateLinkDirectoriesInterface( | |
| gt, cmGeneratorExpression::InstallInterface, properties); | |
| this->PopulateLinkDependsInterface( | |
| gt, cmGeneratorExpression::InstallInterface, properties); | |
| this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface, | |
| properties); | |
| return this->PopulateInterfaceProperties( | |
| gt, includesDestinationDirs, cmGeneratorExpression::InstallInterface, | |
| properties); | |
| } | |
| bool cmExportInstallFileGenerator::PopulateFileSetInterfaceProperties( | |
| cmTargetExport const* targetExport, ImportFileSetPropertyMap& properties) | |
| { | |
| cmGeneratorTarget const* const gt = targetExport->Target; | |
| cmGeneratorFileSets const* const gfs = gt->GetGeneratorFileSets(); | |
| bool result = true; | |
| for (auto const& type : gfs->GetInterfaceFileSetTypes()) { | |
| for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) { | |
| ImportPropertyMap& fsProperties = properties[fileSet->GetName()]; | |
| this->PopulateFileSetIncludeDirectoriesInterface( | |
| gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties); | |
| result = result && | |
| this->PopulateFileSetInterfaceProperties( | |
| gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties); | |
| } | |
| } | |
| return result; | |
| } | |
| namespace { | |
| bool isSubDirectory(std::string const& a, std::string const& b) | |
| { | |
| return (cmSystemTools::ComparePath(a, b) || | |
| cmSystemTools::IsSubDirectory(a, b)); | |
| } | |
| } | |
| bool cmExportInstallFileGenerator::CheckInterfaceDirs( | |
| std::string const& prepro, cmGeneratorTarget const* target, | |
| std::string const& prop) const | |
| { | |
| std::string const& installDir = | |
| target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); | |
| std::string const& topSourceDir = | |
| target->GetLocalGenerator()->GetSourceDirectory(); | |
| std::string const& topBinaryDir = | |
| target->GetLocalGenerator()->GetBinaryDirectory(); | |
| std::vector<std::string> parts; | |
| cmGeneratorExpression::Split(prepro, parts); | |
| bool const inSourceBuild = topSourceDir == topBinaryDir; | |
| bool hadFatalError = false; | |
| for (std::string const& li : parts) { | |
| size_t genexPos = cmGeneratorExpression::Find(li); | |
| if (genexPos == 0) { | |
| continue; | |
| } | |
| if (cmHasPrefix(li, this->GetImportPrefixWithSlash())) { | |
| continue; | |
| } | |
| if (genexPos != std::string::npos) { | |
| hadFatalError = true; | |
| } | |
| if (!cmSystemTools::FileIsFullPath(li)) { | |
| target->GetLocalGenerator()->IssueMessage( | |
| MessageType::FATAL_ERROR, | |
| cmStrCat("Target \"", target->GetName(), "\" ", prop, | |
| " property contains relative path:\n" | |
| " \"", | |
| li, '"')); | |
| } | |
| bool inBinary = isSubDirectory(li, topBinaryDir); | |
| bool inSource = isSubDirectory(li, topSourceDir); | |
| if (isSubDirectory(li, installDir)) { | |
| // The include directory is inside the install tree. If the | |
| // install tree is inside the source tree or build tree then do not | |
| // fall through to the checks below that the include directory is not | |
| // also inside the source tree or build tree. | |
| if ((!inBinary || isSubDirectory(installDir, topBinaryDir)) && | |
| (!inSource || isSubDirectory(installDir, topSourceDir))) { | |
| continue; | |
| } | |
| } | |
| if (inBinary) { | |
| target->GetLocalGenerator()->IssueMessage( | |
| MessageType::FATAL_ERROR, | |
| cmStrCat("Target \"", target->GetName(), "\" ", prop, | |
| " property contains path:\n" | |
| " \"", | |
| li, "\"\nwhich is prefixed in the build directory.")); | |
| } | |
| if (!inSourceBuild) { | |
| if (inSource) { | |
| target->GetLocalGenerator()->IssueMessage( | |
| MessageType::FATAL_ERROR, | |
| cmStrCat("Target \"", target->GetName(), "\" ", prop, | |
| " property contains path:\n" | |
| " \"", | |
| li, "\"\nwhich is prefixed in the source directory.")); | |
| } | |
| } | |
| } | |
| return !hadFatalError; | |
| } | |
| void cmExportInstallFileGenerator::PopulateSourcesInterface( | |
| cmGeneratorTarget const* gt, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties) | |
| { | |
| assert(preprocessRule == cmGeneratorExpression::InstallInterface); | |
| char const* const propName = "INTERFACE_SOURCES"; | |
| cmValue input = gt->GetProperty(propName); | |
| if (!input) { | |
| return; | |
| } | |
| if (input->empty()) { | |
| properties[propName].clear(); | |
| return; | |
| } | |
| std::string prepro = cmGeneratorExpression::Preprocess( | |
| *input, preprocessRule, this->GetImportPrefixWithSlash()); | |
| if (!prepro.empty()) { | |
| this->ResolveTargetsInGeneratorExpressions(prepro, gt); | |
| if (!this->CheckInterfaceDirs(prepro, gt, propName)) { | |
| return; | |
| } | |
| properties[propName] = prepro; | |
| } | |
| } | |
| void cmExportInstallFileGenerator::PopulateSystemIncludeDirectoriesInterface( | |
| cmGeneratorTarget const* target, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties) | |
| { | |
| assert(preprocessRule == cmGeneratorExpression::InstallInterface); | |
| char const* const propName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"; | |
| cmValue input = target->GetProperty(propName); | |
| if (!input) { | |
| return; | |
| } | |
| if (input->empty()) { | |
| // Set to empty | |
| properties[propName].clear(); | |
| return; | |
| } | |
| std::string includes = (input ? *input : ""); | |
| std::string prepro = cmGeneratorExpression::Preprocess( | |
| includes, preprocessRule, this->GetImportPrefixWithSlash()); | |
| if (!prepro.empty()) { | |
| this->ResolveTargetsInGeneratorExpressions(prepro, target); | |
| if (!this->CheckInterfaceDirs(prepro, target, propName)) { | |
| return; | |
| } | |
| properties[propName] = prepro; | |
| } | |
| } | |
| void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface( | |
| cmGeneratorTarget const* target, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties, cmTargetExport const& te, | |
| std::string& includesDestinationDirs) | |
| { | |
| assert(preprocessRule == cmGeneratorExpression::InstallInterface); | |
| includesDestinationDirs.clear(); | |
| char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES"; | |
| cmValue input = target->GetProperty(propName); | |
| cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance()); | |
| std::string dirs = cmGeneratorExpression::Preprocess( | |
| cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)), | |
| preprocessRule, this->GetImportPrefixWithSlash()); | |
| this->ReplaceInstallPrefix(dirs); | |
| std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs); | |
| std::string exportDirs = | |
| cge->Evaluate(target->GetLocalGenerator(), "", target); | |
| if (cge->GetHadContextSensitiveCondition()) { | |
| cmLocalGenerator* lg = target->GetLocalGenerator(); | |
| lg->IssueMessage( | |
| MessageType::FATAL_ERROR, | |
| cmStrCat("Target \"", target->GetName(), | |
| "\" is installed with " | |
| "INCLUDES DESTINATION set to a context sensitive path. Paths " | |
| "which depend on the configuration, policy values or the link " | |
| "interface are not supported. Consider using " | |
| "target_include_directories instead.")); | |
| return; | |
| } | |
| if (!input && exportDirs.empty()) { | |
| return; | |
| } | |
| if ((input && input->empty()) && exportDirs.empty()) { | |
| // Set to empty | |
| properties[propName].clear(); | |
| return; | |
| } | |
| this->AddImportPrefix(exportDirs); | |
| includesDestinationDirs = exportDirs; | |
| std::string includes = (input ? *input : ""); | |
| char const* const sep = input ? ";" : ""; | |
| includes = cmStrCat(std::move(includes), sep, exportDirs); | |
| std::string prepro = cmGeneratorExpression::Preprocess( | |
| includes, preprocessRule, this->GetImportPrefixWithSlash()); | |
| if (!prepro.empty()) { | |
| this->ResolveTargetsInGeneratorExpressions(prepro, target); | |
| if (!this->CheckInterfaceDirs(prepro, target, propName)) { | |
| return; | |
| } | |
| properties[propName] = prepro; | |
| } | |
| } | |
| void cmExportInstallFileGenerator::PopulateFileSetIncludeDirectoriesInterface( | |
| cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties) | |
| { | |
| assert(preprocessRule == cmGeneratorExpression::InstallInterface); | |
| char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES"; | |
| cmValue includes = fileSet->GetProperty(propName); | |
| if (!includes) { | |
| return; | |
| } | |
| if (includes && includes->empty()) { | |
| // Set to empty | |
| properties[propName].clear(); | |
| return; | |
| } | |
| std::string prepro = cmGeneratorExpression::Preprocess( | |
| *includes, preprocessRule, this->GetImportPrefixWithSlash()); | |
| if (!prepro.empty()) { | |
| this->ResolveTargetsInGeneratorExpressions(prepro, target); | |
| if (!this->CheckInterfaceDirs(prepro, target, propName)) { | |
| return; | |
| } | |
| properties[propName] = prepro; | |
| } | |
| } | |
| void cmExportInstallFileGenerator::PopulateLinkDependsInterface( | |
| cmGeneratorTarget const* gt, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties) | |
| { | |
| assert(preprocessRule == cmGeneratorExpression::InstallInterface); | |
| char const* const propName = "INTERFACE_LINK_DEPENDS"; | |
| cmValue input = gt->GetProperty(propName); | |
| if (!input) { | |
| return; | |
| } | |
| if (input->empty()) { | |
| properties[propName].clear(); | |
| return; | |
| } | |
| std::string prepro = cmGeneratorExpression::Preprocess( | |
| *input, preprocessRule, this->GetImportPrefixWithSlash()); | |
| if (!prepro.empty()) { | |
| this->ResolveTargetsInGeneratorExpressions(prepro, gt); | |
| if (!this->CheckInterfaceDirs(prepro, gt, propName)) { | |
| return; | |
| } | |
| properties[propName] = prepro; | |
| } | |
| } | |
| void cmExportInstallFileGenerator::PopulateLinkDirectoriesInterface( | |
| cmGeneratorTarget const* gt, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties) | |
| { | |
| assert(preprocessRule == cmGeneratorExpression::InstallInterface); | |
| char const* const propName = "INTERFACE_LINK_DIRECTORIES"; | |
| cmValue input = gt->GetProperty(propName); | |
| if (!input) { | |
| return; | |
| } | |
| if (input->empty()) { | |
| properties[propName].clear(); | |
| return; | |
| } | |
| std::string prepro = cmGeneratorExpression::Preprocess( | |
| *input, preprocessRule, this->GetImportPrefixWithSlash()); | |
| if (!prepro.empty()) { | |
| this->ResolveTargetsInGeneratorExpressions(prepro, gt); | |
| if (!this->CheckInterfaceDirs(prepro, gt, propName)) { | |
| return; | |
| } | |
| properties[propName] = prepro; | |
| } | |
| } |