From 84e5f5a004fc4659504f25a2d23984b2bceb1a9f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 6 Feb 2014 11:24:37 +0100 Subject: cmTarget: Move SourceFileFlags to cmGeneratorTarget. --- Source/cmGeneratorTarget.cxx | 106 ++++++++++++++++++++++++++++++++++++- Source/cmGeneratorTarget.h | 29 ++++++++++ Source/cmGlobalXCodeGenerator.cxx | 28 +++++----- Source/cmOSXBundleGenerator.cxx | 32 +++++------ Source/cmOSXBundleGenerator.h | 2 +- Source/cmTarget.cxx | 108 -------------------------------------- Source/cmTarget.h | 29 ---------- 7 files changed, 166 insertions(+), 168 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 175bb0e..4db27ca 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -25,7 +25,8 @@ #include "assert.h" //---------------------------------------------------------------------------- -cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) +cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t), + SourceFileFlagsConstructed(false) { this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); @@ -876,3 +877,106 @@ bool cmStrictTargetComparison::operator()(cmTarget const* t1, } return nameResult < 0; } + +//---------------------------------------------------------------------------- +struct cmGeneratorTarget::SourceFileFlags +cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const +{ + struct SourceFileFlags flags; + this->ConstructSourceFileFlags(); + std::map::iterator si = + this->SourceFlagsMap.find(sf); + if(si != this->SourceFlagsMap.end()) + { + flags = si->second; + } + return flags; +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ConstructSourceFileFlags() const +{ + if(this->SourceFileFlagsConstructed) + { + return; + } + this->SourceFileFlagsConstructed = true; + + // Process public headers to mark the source files. + if(const char* files = this->Target->GetProperty("PUBLIC_HEADER")) + { + std::vector relFiles; + cmSystemTools::ExpandListArgument(files, relFiles); + for(std::vector::iterator it = relFiles.begin(); + it != relFiles.end(); ++it) + { + if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) + { + SourceFileFlags& flags = this->SourceFlagsMap[sf]; + flags.MacFolder = "Headers"; + flags.Type = cmGeneratorTarget::SourceFileTypePublicHeader; + } + } + } + + // Process private headers after public headers so that they take + // precedence if a file is listed in both. + if(const char* files = this->Target->GetProperty("PRIVATE_HEADER")) + { + std::vector relFiles; + cmSystemTools::ExpandListArgument(files, relFiles); + for(std::vector::iterator it = relFiles.begin(); + it != relFiles.end(); ++it) + { + if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) + { + SourceFileFlags& flags = this->SourceFlagsMap[sf]; + flags.MacFolder = "PrivateHeaders"; + flags.Type = cmGeneratorTarget::SourceFileTypePrivateHeader; + } + } + } + + // Mark sources listed as resources. + if(const char* files = this->Target->GetProperty("RESOURCE")) + { + std::vector relFiles; + cmSystemTools::ExpandListArgument(files, relFiles); + for(std::vector::iterator it = relFiles.begin(); + it != relFiles.end(); ++it) + { + if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) + { + SourceFileFlags& flags = this->SourceFlagsMap[sf]; + flags.MacFolder = "Resources"; + flags.Type = cmGeneratorTarget::SourceFileTypeResource; + } + } + } + + // Handle the MACOSX_PACKAGE_LOCATION property on source files that + // were not listed in one of the other lists. + std::vector sources; + this->GetSourceFiles(sources); + for(std::vector::const_iterator si = sources.begin(); + si != sources.end(); ++si) + { + cmSourceFile* sf = *si; + if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) + { + SourceFileFlags& flags = this->SourceFlagsMap[sf]; + if(flags.Type == cmGeneratorTarget::SourceFileTypeNormal) + { + flags.MacFolder = location; + if(strcmp(location, "Resources") == 0) + { + flags.Type = cmGeneratorTarget::SourceFileTypeResource; + } + else + { + flags.Type = cmGeneratorTarget::SourceFileTypeMacContent; + } + } + } + } +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index a4caba1..9a3339d 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -88,6 +88,31 @@ public: /** Get sources that must be built before the given source. */ std::vector const* GetSourceDepends(cmSourceFile* sf) const; + /** + * Flags for a given source file as used in this target. Typically assigned + * via SET_TARGET_PROPERTIES when the property is a list of source files. + */ + enum SourceFileType + { + SourceFileTypeNormal, + SourceFileTypePrivateHeader, // is in "PRIVATE_HEADER" target property + SourceFileTypePublicHeader, // is in "PUBLIC_HEADER" target property + SourceFileTypeResource, // is in "RESOURCE" target property *or* + // has MACOSX_PACKAGE_LOCATION=="Resources" + SourceFileTypeMacContent // has MACOSX_PACKAGE_LOCATION!="Resources" + }; + struct SourceFileFlags + { + SourceFileFlags(): Type(SourceFileTypeNormal), MacFolder(0) {} + SourceFileFlags(SourceFileFlags const& r): + Type(r.Type), MacFolder(r.MacFolder) {} + SourceFileType Type; + const char* MacFolder; // location inside Mac content folders + }; + + struct SourceFileFlags + GetTargetSourceFileFlags(const cmSourceFile* sf) const; + private: friend class cmTargetTraceDependencies; struct SourceEntry { std::vector Depends; }; @@ -107,6 +132,10 @@ private: std::vector ObjectLibraries; mutable std::map > SystemIncludesCache; + void ConstructSourceFileFlags() const; + mutable bool SourceFileFlagsConstructed; + mutable std::map SourceFlagsMap; + cmGeneratorTarget(cmGeneratorTarget const&); void operator=(cmGeneratorTarget const&); }; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 484b28f..004f7ac 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -713,22 +713,23 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, // Is this a resource file in this target? Add it to the resources group... // - cmTarget::SourceFileFlags tsFlags = cmtarget.GetTargetSourceFileFlags(sf); - bool isResource = (tsFlags.Type == cmTarget::SourceFileTypeResource); + cmGeneratorTarget::SourceFileFlags tsFlags = + this->GetGeneratorTarget(&cmtarget)->GetTargetSourceFileFlags(sf); + bool isResource = tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource; // Is this a "private" or "public" framework header file? // Set the ATTRIBUTES attribute appropriately... // if(cmtarget.IsFrameworkOnApple()) { - if(tsFlags.Type == cmTarget::SourceFileTypePrivateHeader) + if(tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) { cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); attrs->AddObject(this->CreateString("Private")); settings->AddAttribute("ATTRIBUTES", attrs); isResource = true; } - else if(tsFlags.Type == cmTarget::SourceFileTypePublicHeader) + else if(tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader) { cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); attrs->AddObject(this->CreateString("Public")); @@ -973,6 +974,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) { cmTarget& cmtarget = l->second; + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget); // make sure ALL_BUILD, INSTALL, etc are only done once if(this->SpecialTargetEmitted(l->first.c_str())) @@ -1011,8 +1013,8 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); - cmTarget::SourceFileFlags tsFlags = - cmtarget.GetTargetSourceFileFlags(*i); + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(*i); if(filetype && strcmp(filetype->GetString(), "compiled.mach-o.objfile") == 0) @@ -1020,12 +1022,12 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, externalObjFiles.push_back(xsf); } else if(this->IsHeaderFile(*i) || - (tsFlags.Type == cmTarget::SourceFileTypePrivateHeader) || - (tsFlags.Type == cmTarget::SourceFileTypePublicHeader)) + (tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) || + (tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader)) { headerFiles.push_back(xsf); } - else if(tsFlags.Type == cmTarget::SourceFileTypeResource) + else if(tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { resourceFiles.push_back(xsf); } @@ -1048,7 +1050,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, // the externalObjFiles above, except each one is not a cmSourceFile // within the target.) std::vector objs; - this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs); + gtgt->UseObjectLibraries(objs); for(std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { @@ -1138,9 +1140,9 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, for(std::vector::const_iterator i = classes.begin(); i != classes.end(); ++i) { - cmTarget::SourceFileFlags tsFlags = - cmtarget.GetTargetSourceFileFlags(*i); - if(tsFlags.Type == cmTarget::SourceFileTypeMacContent) + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(*i); + if(tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { bundleFiles[tsFlags.MacFolder].push_back(*i); } diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 9a340dc..78b59b3 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -20,7 +20,7 @@ cmOSXBundleGenerator:: cmOSXBundleGenerator(cmGeneratorTarget* target, const char* configName) - : Target(target->Target) + : GT(target) , Makefile(target->Target->GetMakefile()) , LocalGenerator(Makefile->GetLocalGenerator()) , ConfigName(configName) @@ -34,7 +34,7 @@ cmOSXBundleGenerator(cmGeneratorTarget* target, //---------------------------------------------------------------------------- bool cmOSXBundleGenerator::MustSkip() { - return !this->Target->HaveWellDefinedOutputFiles(); + return !this->GT->Target->HaveWellDefinedOutputFiles(); } //---------------------------------------------------------------------------- @@ -47,7 +47,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // Compute bundle directory names. std::string out = outpath; out += "/"; - out += this->Target->GetAppBundleDirectory(this->ConfigName, false); + out += this->GT->Target->GetAppBundleDirectory(this->ConfigName, false); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); @@ -57,9 +57,9 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // to be set. std::string plist = outpath; plist += "/"; - plist += this->Target->GetAppBundleDirectory(this->ConfigName, true); + plist += this->GT->Target->GetAppBundleDirectory(this->ConfigName, true); plist += "/Info.plist"; - this->LocalGenerator->GenerateAppleInfoPList(this->Target, + this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target, targetName.c_str(), plist.c_str()); this->Makefile->AddCMakeOutputFile(plist); @@ -77,20 +77,20 @@ void cmOSXBundleGenerator::CreateFramework( // Compute the location of the top-level foo.framework directory. std::string contentdir = outpath + "/" + - this->Target->GetFrameworkDirectory(this->ConfigName, true); + this->GT->Target->GetFrameworkDirectory(this->ConfigName, true); contentdir += "/"; std::string newoutpath = outpath + "/" + - this->Target->GetFrameworkDirectory(this->ConfigName, false); + this->GT->Target->GetFrameworkDirectory(this->ConfigName, false); - std::string frameworkVersion = this->Target->GetFrameworkVersion(); + std::string frameworkVersion = this->GT->Target->GetFrameworkVersion(); // Configure the Info.plist file into the Resources directory. this->MacContentFolders->insert("Resources"); std::string plist = newoutpath; plist += "/Resources/Info.plist"; std::string name = cmSystemTools::GetFilenameName(targetName); - this->LocalGenerator->GenerateFrameworkInfoPList(this->Target, + this->LocalGenerator->GenerateFrameworkInfoPList(this->GT->Target, name.c_str(), plist.c_str()); @@ -172,16 +172,16 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, // Compute bundle directory names. std::string out = root; out += "/"; - out += this->Target->GetCFBundleDirectory(this->ConfigName, false); + out += this->GT->Target->GetCFBundleDirectory(this->ConfigName, false); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. std::string plist = - this->Target->GetCFBundleDirectory(this->ConfigName, true); + this->GT->Target->GetCFBundleDirectory(this->ConfigName, true); plist += "/Info.plist"; - this->LocalGenerator->GenerateAppleInfoPList(this->Target, + this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target, targetName.c_str(), plist.c_str()); this->Makefile->AddCMakeOutputFile(plist); @@ -199,9 +199,9 @@ GenerateMacOSXContentStatements(std::vector const& sources, for(std::vector::const_iterator si = sources.begin(); si != sources.end(); ++si) { - cmTarget::SourceFileFlags tsFlags = - this->Target->GetTargetSourceFileFlags(*si); - if(tsFlags.Type != cmTarget::SourceFileTypeNormal) + cmGeneratorTarget::SourceFileFlags tsFlags = + this->GT->GetTargetSourceFileFlags(*si); + if(tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) { (*generator)(**si, tsFlags.MacFolder); } @@ -215,7 +215,7 @@ cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc) // Construct the full path to the content subdirectory. std::string macdir = - this->Target->GetMacContentDirectory(this->ConfigName, + this->GT->Target->GetMacContentDirectory(this->ConfigName, /*implib*/ false); macdir += "/"; macdir += pkgloc; diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 29b7611..2f36394 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -59,7 +59,7 @@ private: bool MustSkip(); private: - cmTarget* Target; + cmGeneratorTarget* GT; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; const char* ConfigName; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index db34bd8..61f05a1 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -83,17 +83,12 @@ public: cmTargetInternals() { this->PolicyWarnedCMP0022 = false; - this->SourceFileFlagsConstructed = false; } cmTargetInternals(cmTargetInternals const&) { this->PolicyWarnedCMP0022 = false; - this->SourceFileFlagsConstructed = false; } ~cmTargetInternals(); - typedef cmTarget::SourceFileFlags SourceFileFlags; - mutable std::map SourceFlagsMap; - mutable bool SourceFileFlagsConstructed; // The backtrace when the target was created. cmListFileBacktrace Backtrace; @@ -648,109 +643,6 @@ void cmTarget::ProcessSourceExpression(std::string const& expr) } //---------------------------------------------------------------------------- -struct cmTarget::SourceFileFlags -cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const -{ - struct SourceFileFlags flags; - this->ConstructSourceFileFlags(); - std::map::iterator si = - this->Internal->SourceFlagsMap.find(sf); - if(si != this->Internal->SourceFlagsMap.end()) - { - flags = si->second; - } - return flags; -} - -//---------------------------------------------------------------------------- -void cmTarget::ConstructSourceFileFlags() const -{ - if(this->Internal->SourceFileFlagsConstructed) - { - return; - } - this->Internal->SourceFileFlagsConstructed = true; - - // Process public headers to mark the source files. - if(const char* files = this->GetProperty("PUBLIC_HEADER")) - { - std::vector relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); - for(std::vector::iterator it = relFiles.begin(); - it != relFiles.end(); ++it) - { - if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) - { - SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf]; - flags.MacFolder = "Headers"; - flags.Type = cmTarget::SourceFileTypePublicHeader; - } - } - } - - // Process private headers after public headers so that they take - // precedence if a file is listed in both. - if(const char* files = this->GetProperty("PRIVATE_HEADER")) - { - std::vector relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); - for(std::vector::iterator it = relFiles.begin(); - it != relFiles.end(); ++it) - { - if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) - { - SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf]; - flags.MacFolder = "PrivateHeaders"; - flags.Type = cmTarget::SourceFileTypePrivateHeader; - } - } - } - - // Mark sources listed as resources. - if(const char* files = this->GetProperty("RESOURCE")) - { - std::vector relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); - for(std::vector::iterator it = relFiles.begin(); - it != relFiles.end(); ++it) - { - if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) - { - SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf]; - flags.MacFolder = "Resources"; - flags.Type = cmTarget::SourceFileTypeResource; - } - } - } - - // Handle the MACOSX_PACKAGE_LOCATION property on source files that - // were not listed in one of the other lists. - std::vector sources; - this->GetSourceFiles(sources); - for(std::vector::const_iterator si = sources.begin(); - si != sources.end(); ++si) - { - cmSourceFile* sf = *si; - if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) - { - SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf]; - if(flags.Type == cmTarget::SourceFileTypeNormal) - { - flags.MacFolder = location; - if(strcmp(location, "Resources") == 0) - { - flags.Type = cmTarget::SourceFileTypeResource; - } - else - { - flags.Type = cmTarget::SourceFileTypeMacContent; - } - } - } - } -} - -//---------------------------------------------------------------------------- void cmTarget::MergeLinkLibraries( cmMakefile& mf, const char *selfname, const LinkLibraryVectorType& libs ) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 271824b..a02ed09 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -140,34 +140,6 @@ public: } /** - * Flags for a given source file as used in this target. Typically assigned - * via SET_TARGET_PROPERTIES when the property is a list of source files. - */ - enum SourceFileType - { - SourceFileTypeNormal, - SourceFileTypePrivateHeader, // is in "PRIVATE_HEADER" target property - SourceFileTypePublicHeader, // is in "PUBLIC_HEADER" target property - SourceFileTypeResource, // is in "RESOURCE" target property *or* - // has MACOSX_PACKAGE_LOCATION=="Resources" - SourceFileTypeMacContent // has MACOSX_PACKAGE_LOCATION!="Resources" - }; - struct SourceFileFlags - { - SourceFileFlags(): Type(SourceFileTypeNormal), MacFolder(0) {} - SourceFileFlags(SourceFileFlags const& r): - Type(r.Type), MacFolder(r.MacFolder) {} - SourceFileType Type; - const char* MacFolder; // location inside Mac content folders - }; - - /** - * Get the flags for a given source file as used in this target - */ - struct SourceFileFlags - GetTargetSourceFileFlags(const cmSourceFile* sf) const; - - /** * Add sources to the target. */ void AddSources(std::vector const& srcs); @@ -756,7 +728,6 @@ private: friend class cmTargetTraceDependencies; cmTargetInternalPointer Internal; - void ConstructSourceFileFlags() const; void ComputeVersionedName(std::string& vName, std::string const& prefix, std::string const& base, -- cgit v0.12 From f81eb49e8be851cef5e75a5074ff46435c941301 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 14 Feb 2014 12:07:34 +0100 Subject: cmTarget: Find source files on request. In a follow-up, the list of sources will become dependent on the config, so check for existence in cmTarget::GetSourceFiles instead of up-front with cmGlobalGenerator::CheckTargets(). --- Source/cmGlobalGenerator.cxx | 35 ----------------------------------- Source/cmGlobalGenerator.h | 1 - Source/cmTarget.cxx | 14 ++++---------- Source/cmTarget.h | 5 ----- 4 files changed, 4 insertions(+), 51 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 4f3328d..e143eba 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1148,12 +1148,6 @@ void cmGlobalGenerator::Generate() return; } - // Check that all targets are valid. - if(!this->CheckTargets()) - { - return; - } - this->FinalizeTargetCompileInfo(); #ifdef CMAKE_BUILD_WITH_CMAKE @@ -1306,35 +1300,6 @@ bool cmGlobalGenerator::ComputeTargetDepends() } //---------------------------------------------------------------------------- -bool cmGlobalGenerator::CheckTargets() -{ - // Make sure all targets can find their source files. - for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) - { - cmTargets& targets = - this->LocalGenerators[i]->GetMakefile()->GetTargets(); - for(cmTargets::iterator ti = targets.begin(); - ti != targets.end(); ++ti) - { - cmTarget& target = ti->second; - if(target.GetType() == cmTarget::EXECUTABLE || - target.GetType() == cmTarget::STATIC_LIBRARY || - target.GetType() == cmTarget::SHARED_LIBRARY || - target.GetType() == cmTarget::MODULE_LIBRARY || - target.GetType() == cmTarget::OBJECT_LIBRARY || - target.GetType() == cmTarget::UTILITY) - { - if(!target.FindSourceFiles()) - { - return false; - } - } - } - } - return true; -} - -//---------------------------------------------------------------------------- void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens) { #ifdef CMAKE_BUILD_WITH_CMAKE diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 753eebf..b66f01e 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -340,7 +340,6 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const; - bool CheckTargets(); typedef std::vector > AutogensType; void CreateQtAutoGeneratorsTargets(AutogensType& autogens); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 61f05a1..5fa9276 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -522,10 +522,11 @@ bool cmTarget::IsBundleOnApple() const } //---------------------------------------------------------------------------- -bool cmTarget::FindSourceFiles() +void cmTarget::GetSourceFiles(std::vector &files) const { + assert(this->GetType() != INTERFACE_LIBRARY); for(std::vector::const_iterator - si = this->SourceFiles.begin(); + si = this->SourceFiles.begin(); si != this->SourceFiles.end(); ++si) { std::string e; @@ -537,16 +538,9 @@ bool cmTarget::FindSourceFiles() cm->IssueMessage(cmake::FATAL_ERROR, e, this->GetBacktrace()); } - return false; + return; } } - return true; -} - -//---------------------------------------------------------------------------- -void cmTarget::GetSourceFiles(std::vector &files) const -{ - assert(this->GetType() != INTERFACE_LIBRARY); files = this->SourceFiles; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index a02ed09..4d487f7 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -330,11 +330,6 @@ public: void GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const; - /** - * Make sure the full path to all source files is known. - */ - bool FindSourceFiles(); - ///! Return the preferred linker language for this target const char* GetLinkerLanguage(const char* config = 0, cmTarget const* head = 0) const; -- cgit v0.12 From 21e91350b06b562ac2668c6ff2a3b220e41d4bc1 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 13 Feb 2014 09:53:27 +0100 Subject: cmTarget: Change GetTransitivePropertyLinkLibraries to output targets. The callers already skip non-targets, so unify the target search. Change supporting functions to accept a container of targets instead of strings where possible. --- Source/cmGeneratorExpressionEvaluator.cxx | 51 +++++++++++++++++++++---------- Source/cmGeneratorTarget.cxx | 32 ++++++++----------- Source/cmTarget.cxx | 26 +++++++++++++--- Source/cmTarget.h | 4 +-- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 7036992..ebedf65 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -800,7 +800,7 @@ static const char* targetPropertyTransitiveWhitelist[] = { #undef TRANSITIVE_PROPERTY_NAME -std::string getLinkedTargetsContent(const std::vector &libraries, +std::string getLinkedTargetsContent(const std::vector &targets, cmTarget const* target, cmTarget const* headTarget, cmGeneratorExpressionContext *context, @@ -811,23 +811,21 @@ std::string getLinkedTargetsContent(const std::vector &libraries, std::string sep; std::string depString; - for (std::vector::const_iterator - it = libraries.begin(); - it != libraries.end(); ++it) + for (std::vector::const_iterator + it = targets.begin(); + it != targets.end(); ++it) { - if (*it == target->GetName()) + if (*it == target) { // Broken code can have a target in its own link interface. // Don't follow such link interface entries so as not to create a // self-referencing loop. continue; } - if (context->Makefile->FindTargetToUse(*it)) - { - depString += - sep + "$"; - sep = ";"; - } + depString += + sep + "$GetName() + "," + interfacePropertyName + ">"; + sep = ";"; } cmsys::auto_ptr cge = ge.Parse(depString); std::string linkedTargetsContent = cge->Evaluate(context->Makefile, @@ -843,6 +841,27 @@ std::string getLinkedTargetsContent(const std::vector &libraries, return linkedTargetsContent; } +std::string getLinkedTargetsContent(const std::vector &libraries, + cmTarget const* target, + cmTarget const* headTarget, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string &interfacePropertyName) +{ + std::vector tgts; + for (std::vector::const_iterator + it = libraries.begin(); + it != libraries.end(); ++it) + { + if (cmTarget *tgt = context->Makefile->FindTargetToUse(*it)) + { + tgts.push_back(tgt); + } + } + return getLinkedTargetsContent(tgts, target, headTarget, context, + dagChecker, interfacePropertyName); +} + //---------------------------------------------------------------------------- static const struct TargetPropertyNode : public cmGeneratorExpressionNode { @@ -1065,13 +1084,13 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode cmStrCmp(propertyName)) != transEnd) { - std::vector libs; - target->GetTransitivePropertyLinkLibraries(context->Config, - headTarget, libs); - if (!libs.empty()) + std::vector tgts; + target->GetTransitivePropertyTargets(context->Config, + headTarget, tgts); + if (!tgts.empty()) { linkedTargetsContent = - getLinkedTargetsContent(libs, target, + getLinkedTargetsContent(tgts, target, headTarget, context, &dagChecker, interfacePropertyName); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 4db27ca..6223ed1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -63,19 +63,12 @@ cmGeneratorTarget::GetSourceDepends(cmSourceFile* sf) const return 0; } -static void handleSystemIncludesDep(cmMakefile *mf, const std::string &name, +static void handleSystemIncludesDep(cmMakefile *mf, cmTarget* depTgt, const char *config, cmTarget *headTarget, cmGeneratorExpressionDAGChecker *dagChecker, std::vector& result, bool excludeImported) { - cmTarget* depTgt = mf->FindTargetToUse(name); - - if (!depTgt) - { - return; - } - cmListFileBacktrace lfbt; if (const char* dirs = @@ -225,26 +218,25 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir, &dagChecker), result); } - std::set uniqueDeps; + std::set uniqueDeps; for(std::vector::const_iterator li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { - if (uniqueDeps.insert(*li).second) + cmTarget* tgt = this->Makefile->FindTargetToUse(*li); + if (!tgt) { - cmTarget* tgt = this->Makefile->FindTargetToUse(*li); - - if (!tgt) - { - continue; - } + continue; + } - handleSystemIncludesDep(this->Makefile, *li, config, this->Target, + if (uniqueDeps.insert(tgt).second) + { + handleSystemIncludesDep(this->Makefile, tgt, config, this->Target, &dagChecker, result, excludeImported); - std::vector deps; - tgt->GetTransitivePropertyLinkLibraries(config, this->Target, deps); + std::vector deps; + tgt->GetTransitivePropertyTargets(config, this->Target, deps); - for(std::vector::const_iterator di = deps.begin(); + for(std::vector::const_iterator di = deps.begin(); di != deps.end(); ++di) { if (uniqueDeps.insert(*di).second) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 5fa9276..faf53c1 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -5213,10 +5213,9 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config, } //---------------------------------------------------------------------------- -void cmTarget::GetTransitivePropertyLinkLibraries( - const char* config, +void cmTarget::GetTransitivePropertyTargets(const char* config, cmTarget const* headTarget, - std::vector &libs) const + std::vector &tgts) const { cmTarget::LinkInterface const* iface = this->GetLinkInterface(config, headTarget); @@ -5228,7 +5227,15 @@ void cmTarget::GetTransitivePropertyLinkLibraries( || this->GetPolicyStatusCMP0022() == cmPolicies::WARN || this->GetPolicyStatusCMP0022() == cmPolicies::OLD) { - libs = iface->Libraries; + for(std::vector::const_iterator it = iface->Libraries.begin(); + it != iface->Libraries.end(); ++it) + { + if (cmTarget* tgt = headTarget->GetMakefile() + ->FindTargetToUse(it->c_str())) + { + tgts.push_back(tgt); + } + } return; } @@ -5246,12 +5253,23 @@ void cmTarget::GetTransitivePropertyLinkLibraries( cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), linkIfaceProp, 0, 0); dagChecker.SetTransitivePropertiesOnly(); + std::vector libs; cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate( this->Makefile, config, false, headTarget, this, &dagChecker), libs); + + for(std::vector::const_iterator it = libs.begin(); + it != libs.end(); ++it) + { + if (cmTarget* tgt = headTarget->GetMakefile() + ->FindTargetToUse(it->c_str())) + { + tgts.push_back(tgt); + } + } } //---------------------------------------------------------------------------- diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 4d487f7..0d85259 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -264,9 +264,9 @@ public: if the target cannot be linked. */ LinkInterface const* GetLinkInterface(const char* config, cmTarget const* headTarget) const; - void GetTransitivePropertyLinkLibraries(const char* config, + void GetTransitivePropertyTargets(const char* config, cmTarget const* headTarget, - std::vector &libs) const; + std::vector &libs) const; /** The link implementation specifies the direct library dependencies needed by the object files of the target. */ -- cgit v0.12 From 326d07d27ec173d3e67a314010764ebbe7b2aa9c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 13 Feb 2014 11:26:08 +0100 Subject: cmTarget: Extract a ComputeLinkImplementationLanguages method. --- Source/cmTarget.cxx | 6 ++++++ Source/cmTarget.h | 1 + 2 files changed, 7 insertions(+) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index faf53c1..bc57c51 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -5537,6 +5537,7 @@ cmTarget::GetLinkImplementation(const char* config, cmTarget const* head) const // Compute the link implementation for this configuration. LinkImplementation impl; this->ComputeLinkImplementation(config, impl, head); + this->ComputeLinkImplementationLanguages(impl); // Store the information for this configuration. cmTargetInternals::LinkImplMapType::value_type entry(key, impl); @@ -5619,7 +5620,12 @@ void cmTarget::ComputeLinkImplementation(const char* config, impl.WrongConfigLibraries.push_back(item); } } +} +//---------------------------------------------------------------------------- +void +cmTarget::ComputeLinkImplementationLanguages(LinkImplementation& impl) const +{ // This target needs runtime libraries for its source languages. std::set languages; // Get languages used in our source files. diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 0d85259..234adba 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -696,6 +696,7 @@ private: void ComputeLinkImplementation(const char* config, LinkImplementation& impl, cmTarget const* head) const; + void ComputeLinkImplementationLanguages(LinkImplementation& impl) const; void ComputeLinkClosure(const char* config, LinkClosure& lc, cmTarget const* head) const; -- cgit v0.12 From 3bcb197c11be54445db3282e9811dc29f2321c70 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 13 Feb 2014 15:11:07 +0100 Subject: cmTarget: Re-arrange the ComputeLinkInterface method. Arrange the logic so that the part which deals with libraries only is at the top. In a follow-up commit, this will be split into two methods. Ensure that the explanatory CMP0022 comment is only present in one location. --- Source/cmTarget.cxx | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index bc57c51..edef7a0 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -5366,7 +5366,22 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, false, headTarget, this, &dagChecker), iface.Libraries); + } + else if (this->PolicyStatusCMP0022 == cmPolicies::WARN + || this->PolicyStatusCMP0022 == cmPolicies::OLD) + // If CMP0022 is NEW then the plain tll signature sets the + // INTERFACE_LINK_LIBRARIES, so if we get here then the project + // cleared the property explicitly and we should not fall back + // to the link implementation. + { + // The link implementation is the default link interface. + LinkImplementation const* impl = this->GetLinkImplementation(config, + headTarget); + iface.Libraries = impl->Libraries; + } + if(explicitLibraries) + { if(this->GetType() == cmTarget::SHARED_LIBRARY || this->GetType() == cmTarget::STATIC_LIBRARY || this->GetType() == cmTarget::INTERFACE_LIBRARY) @@ -5415,16 +5430,11 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, } else if (this->PolicyStatusCMP0022 == cmPolicies::WARN || this->PolicyStatusCMP0022 == cmPolicies::OLD) - // If CMP0022 is NEW then the plain tll signature sets the - // INTERFACE_LINK_LIBRARIES, so if we get here then the project - // cleared the property explicitly and we should not fall back - // to the link implementation. { // The link implementation is the default link interface. LinkImplementation const* impl = this->GetLinkImplementation(config, headTarget); iface.ImplementationIsInterface = true; - iface.Libraries = impl->Libraries; iface.WrongConfigLibraries = impl->WrongConfigLibraries; if(this->LinkLanguagePropagatesToDependents()) { -- cgit v0.12 From d93e1af2928cbb06a66ad67d56c3a5cb217f3963 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 13 Feb 2014 11:07:22 +0100 Subject: cmTarget: Extract a ComputeLinkInterfaceLibraries method. When evaluating the SOURCES property, we will need to be able to access the link libraries without accessing the link languages, as the languages depend on the SOURCES. --- Source/cmTarget.cxx | 161 +++++++++++++++++++++++++++++----------------------- Source/cmTarget.h | 10 +++- 2 files changed, 99 insertions(+), 72 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index edef7a0..f203312 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -5202,7 +5202,9 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config, { // Compute the link interface for this configuration. cmTargetInternals::OptionalLinkInterface iface; - iface.Exists = this->ComputeLinkInterface(config, iface, head); + const char* explicitLibraries = + this->ComputeLinkInterfaceLibraries(config, iface, head, iface.Exists); + this->ComputeLinkInterface(config, iface, head, explicitLibraries); // Store the information for this configuration. cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); @@ -5273,8 +5275,10 @@ void cmTarget::GetTransitivePropertyTargets(const char* config, } //---------------------------------------------------------------------------- -bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, - cmTarget const* headTarget) const +const char* cmTarget::ComputeLinkInterfaceLibraries(const char* config, + LinkInterface& iface, + cmTarget const* headTarget, + bool &exists) const { // Construct the property name suffix for this configuration. std::string suffix = "_"; @@ -5350,8 +5354,10 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, (this->GetType() == cmTarget::EXECUTABLE || (this->GetType() == cmTarget::MODULE_LIBRARY))) { - return false; + exists = false; + return 0; } + exists = true; if(explicitLibraries) { @@ -5378,70 +5384,6 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, LinkImplementation const* impl = this->GetLinkImplementation(config, headTarget); iface.Libraries = impl->Libraries; - } - - if(explicitLibraries) - { - if(this->GetType() == cmTarget::SHARED_LIBRARY - || this->GetType() == cmTarget::STATIC_LIBRARY - || this->GetType() == cmTarget::INTERFACE_LIBRARY) - { - // Shared libraries may have runtime implementation dependencies - // on other shared libraries that are not in the interface. - std::set emitted; - for(std::vector::const_iterator - li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li) - { - emitted.insert(*li); - } - if (this->GetType() != cmTarget::INTERFACE_LIBRARY) - { - LinkImplementation const* impl = this->GetLinkImplementation(config, - headTarget); - for(std::vector::const_iterator - li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) - { - if(emitted.insert(*li).second) - { - if(cmTarget* tgt = this->Makefile->FindTargetToUse(*li)) - { - // This is a runtime dependency on another shared library. - if(tgt->GetType() == cmTarget::SHARED_LIBRARY) - { - iface.SharedDeps.push_back(*li); - } - } - else - { - // TODO: Recognize shared library file names. Perhaps this - // should be moved to cmComputeLinkInformation, but that creates - // a chicken-and-egg problem since this list is needed for its - // construction. - } - } - } - if(this->LinkLanguagePropagatesToDependents()) - { - // Targets using this archive need its language runtime libraries. - iface.Languages = impl->Languages; - } - } - } - } - else if (this->PolicyStatusCMP0022 == cmPolicies::WARN - || this->PolicyStatusCMP0022 == cmPolicies::OLD) - { - // The link implementation is the default link interface. - LinkImplementation const* impl = this->GetLinkImplementation(config, - headTarget); - iface.ImplementationIsInterface = true; - iface.WrongConfigLibraries = impl->WrongConfigLibraries; - if(this->LinkLanguagePropagatesToDependents()) - { - // Targets using this archive need its language runtime libraries. - iface.Languages = impl->Languages; - } - if(this->PolicyStatusCMP0022 == cmPolicies::WARN && !this->Internal->PolicyWarnedCMP0022) { @@ -5506,9 +5448,90 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, } } } + return explicitLibraries; +} + +//---------------------------------------------------------------------------- +void cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, + cmTarget const* headTarget, + const char* explicitLibraries) const +{ + if(explicitLibraries) + { + if(this->GetType() == cmTarget::SHARED_LIBRARY + || this->GetType() == cmTarget::STATIC_LIBRARY + || this->GetType() == cmTarget::INTERFACE_LIBRARY) + { + // Shared libraries may have runtime implementation dependencies + // on other shared libraries that are not in the interface. + std::set emitted; + for(std::vector::const_iterator + li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li) + { + emitted.insert(*li); + } + if (this->GetType() != cmTarget::INTERFACE_LIBRARY) + { + LinkImplementation const* impl = this->GetLinkImplementation(config, + headTarget); + for(std::vector::const_iterator + li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) + { + if(emitted.insert(*li).second) + { + if(cmTarget* tgt = this->Makefile->FindTargetToUse(*li)) + { + // This is a runtime dependency on another shared library. + if(tgt->GetType() == cmTarget::SHARED_LIBRARY) + { + iface.SharedDeps.push_back(*li); + } + } + else + { + // TODO: Recognize shared library file names. Perhaps this + // should be moved to cmComputeLinkInformation, but that creates + // a chicken-and-egg problem since this list is needed for its + // construction. + } + } + } + if(this->LinkLanguagePropagatesToDependents()) + { + // Targets using this archive need its language runtime libraries. + iface.Languages = impl->Languages; + } + } + } + } + else if (this->PolicyStatusCMP0022 == cmPolicies::WARN + || this->PolicyStatusCMP0022 == cmPolicies::OLD) + { + // The link implementation is the default link interface. + LinkImplementation const* impl = this->GetLinkImplementation(config, + headTarget); + iface.ImplementationIsInterface = true; + iface.WrongConfigLibraries = impl->WrongConfigLibraries; + if(this->LinkLanguagePropagatesToDependents()) + { + // Targets using this archive need its language runtime libraries. + iface.Languages = impl->Languages; + } + } if(this->GetType() == cmTarget::STATIC_LIBRARY) { + // Construct the property name suffix for this configuration. + std::string suffix = "_"; + if(config && *config) + { + suffix += cmSystemTools::UpperCase(config); + } + else + { + suffix += "NOCONFIG"; + } + // How many repetitions are needed if this library has cyclic // dependencies? std::string propName = "LINK_INTERFACE_MULTIPLICITY"; @@ -5523,8 +5546,6 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, sscanf(reps, "%u", &iface.Multiplicity); } } - - return true; } //---------------------------------------------------------------------------- diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 234adba..09c6f74 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -690,8 +690,14 @@ private: void CheckPropertyCompatibility(cmComputeLinkInformation *info, const char* config) const; - bool ComputeLinkInterface(const char* config, LinkInterface& iface, - cmTarget const* head) const; + void ComputeLinkInterface(const char* config, LinkInterface& iface, + cmTarget const* head, + const char *explicitLibraries) const; + + const char* ComputeLinkInterfaceLibraries(const char* config, + LinkInterface& iface, + cmTarget const* head, + bool &exists) const; void ComputeLinkImplementation(const char* config, LinkImplementation& impl, -- cgit v0.12 From 01bca553b83cd8c3a4a4d0348bd317d118a98995 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 13 Feb 2014 16:00:55 +0100 Subject: cmTarget: Move ComputeLinkInterface to the internal class. In a follow-up, this will use the OptionalLinkInterface in its API. That class is in the cmTargetInternals class. --- Source/cmTarget.cxx | 48 ++++++++++++++++++++++++++++-------------------- Source/cmTarget.h | 4 ---- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index f203312..0a192e6 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -99,6 +99,11 @@ public: OptionalLinkInterface(): Exists(false) {} bool Exists; }; + void ComputeLinkInterface(cmTarget const* thisTarget, + const char* config, OptionalLinkInterface& iface, + cmTarget const* head, + const char *explicitLibraries) const; + typedef std::map LinkInterfaceMapType; LinkInterfaceMapType LinkInterfaceMap; @@ -5204,7 +5209,8 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config, cmTargetInternals::OptionalLinkInterface iface; const char* explicitLibraries = this->ComputeLinkInterfaceLibraries(config, iface, head, iface.Exists); - this->ComputeLinkInterface(config, iface, head, explicitLibraries); + this->Internal->ComputeLinkInterface(this, config, iface, + head, explicitLibraries); // Store the information for this configuration. cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); @@ -5452,15 +5458,17 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const char* config, } //---------------------------------------------------------------------------- -void cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, - cmTarget const* headTarget, - const char* explicitLibraries) const +void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, + const char* config, + OptionalLinkInterface& iface, + cmTarget const* headTarget, + const char* explicitLibraries) const { if(explicitLibraries) { - if(this->GetType() == cmTarget::SHARED_LIBRARY - || this->GetType() == cmTarget::STATIC_LIBRARY - || this->GetType() == cmTarget::INTERFACE_LIBRARY) + if(thisTarget->GetType() == cmTarget::SHARED_LIBRARY + || thisTarget->GetType() == cmTarget::STATIC_LIBRARY + || thisTarget->GetType() == cmTarget::INTERFACE_LIBRARY) { // Shared libraries may have runtime implementation dependencies // on other shared libraries that are not in the interface. @@ -5470,16 +5478,16 @@ void cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, { emitted.insert(*li); } - if (this->GetType() != cmTarget::INTERFACE_LIBRARY) + if (thisTarget->GetType() != cmTarget::INTERFACE_LIBRARY) { - LinkImplementation const* impl = this->GetLinkImplementation(config, - headTarget); + cmTarget::LinkImplementation const* impl = + thisTarget->GetLinkImplementation(config, headTarget); for(std::vector::const_iterator li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { if(emitted.insert(*li).second) { - if(cmTarget* tgt = this->Makefile->FindTargetToUse(*li)) + if(cmTarget* tgt = thisTarget->Makefile->FindTargetToUse(*li)) { // This is a runtime dependency on another shared library. if(tgt->GetType() == cmTarget::SHARED_LIBRARY) @@ -5496,7 +5504,7 @@ void cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, } } } - if(this->LinkLanguagePropagatesToDependents()) + if(thisTarget->LinkLanguagePropagatesToDependents()) { // Targets using this archive need its language runtime libraries. iface.Languages = impl->Languages; @@ -5504,22 +5512,22 @@ void cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, } } } - else if (this->PolicyStatusCMP0022 == cmPolicies::WARN - || this->PolicyStatusCMP0022 == cmPolicies::OLD) + else if (thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN + || thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD) { // The link implementation is the default link interface. - LinkImplementation const* impl = this->GetLinkImplementation(config, - headTarget); + cmTarget::LinkImplementation const* + impl = thisTarget->GetLinkImplementation(config, headTarget); iface.ImplementationIsInterface = true; iface.WrongConfigLibraries = impl->WrongConfigLibraries; - if(this->LinkLanguagePropagatesToDependents()) + if(thisTarget->LinkLanguagePropagatesToDependents()) { // Targets using this archive need its language runtime libraries. iface.Languages = impl->Languages; } } - if(this->GetType() == cmTarget::STATIC_LIBRARY) + if(thisTarget->GetType() == cmTarget::STATIC_LIBRARY) { // Construct the property name suffix for this configuration. std::string suffix = "_"; @@ -5536,12 +5544,12 @@ void cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, // dependencies? std::string propName = "LINK_INTERFACE_MULTIPLICITY"; propName += suffix; - if(const char* config_reps = this->GetProperty(propName.c_str())) + if(const char* config_reps = thisTarget->GetProperty(propName.c_str())) { sscanf(config_reps, "%u", &iface.Multiplicity); } else if(const char* reps = - this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) + thisTarget->GetProperty("LINK_INTERFACE_MULTIPLICITY")) { sscanf(reps, "%u", &iface.Multiplicity); } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 09c6f74..8bc5af4 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -690,10 +690,6 @@ private: void CheckPropertyCompatibility(cmComputeLinkInformation *info, const char* config) const; - void ComputeLinkInterface(const char* config, LinkInterface& iface, - cmTarget const* head, - const char *explicitLibraries) const; - const char* ComputeLinkInterfaceLibraries(const char* config, LinkInterface& iface, cmTarget const* head, -- cgit v0.12 From b8b99cc1e5efa8f1513ceb3025c66f3b28fc5bab Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 13 Feb 2014 15:02:09 +0100 Subject: cmTarget: Avoid computing languages when computing transitive targets. For the OLD CMP0022 behavior, we need to treat the implementation as the interface when computing the interface libraries. Make it possible to do that without computing the link languages by adding a new GetLinkImplementationLibraries method. Extend the existing GetLinkImplementation method to populate the languages if the libraries have already been computed and cached. Change GetTransitivePropertyTargets to invoke GetLinkInterfaceLibraries instead of GetLinkInterface. This is key, as it is a method called by cmGeneratorExpressionEvaluator. Change the cmGeneratorExpressionEvaluator to invoke GetLinkImplementationLibraries instead of GetLinkImplementation. --- Source/cmGeneratorExpressionEvaluator.cxx | 6 +- Source/cmTarget.cxx | 109 +++++++++++++++++++++++++++--- Source/cmTarget.h | 5 ++ 3 files changed, 108 insertions(+), 12 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index ebedf65..bdefcfb 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -1099,9 +1099,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode else if (std::find_if(transBegin, transEnd, cmStrCmp(interfacePropertyName)) != transEnd) { - const cmTarget::LinkImplementation *impl = target->GetLinkImplementation( - context->Config, - headTarget); + const cmTarget::LinkImplementation *impl + = target->GetLinkImplementationLibraries(context->Config, + headTarget); if(impl) { linkedTargetsContent = diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 0a192e6..ea031cd 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -96,8 +96,11 @@ public: // Cache link interface computation from each configuration. struct OptionalLinkInterface: public cmTarget::LinkInterface { - OptionalLinkInterface(): Exists(false) {} + OptionalLinkInterface(): + Exists(false), Complete(false), ExplicitLibraries(0) {} bool Exists; + bool Complete; + const char* ExplicitLibraries; }; void ComputeLinkInterface(cmTarget const* thisTarget, const char* config, OptionalLinkInterface& iface, @@ -5207,17 +5210,70 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config, { // Compute the link interface for this configuration. cmTargetInternals::OptionalLinkInterface iface; - const char* explicitLibraries = + iface.ExplicitLibraries = this->ComputeLinkInterfaceLibraries(config, iface, head, iface.Exists); - this->Internal->ComputeLinkInterface(this, config, iface, - head, explicitLibraries); + if (iface.Exists) + { + this->Internal->ComputeLinkInterface(this, config, iface, + head, iface.ExplicitLibraries); + } + + // Store the information for this configuration. + cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); + i = this->Internal->LinkInterfaceMap.insert(entry).first; + } + else if(!i->second.Complete && i->second.Exists) + { + this->Internal->ComputeLinkInterface(this, config, i->second, head, + i->second.ExplicitLibraries); + } + + return i->second.Exists ? &i->second : 0; +} + +//---------------------------------------------------------------------------- +cmTarget::LinkInterface const* +cmTarget::GetLinkInterfaceLibraries(const char* config, + cmTarget const* head) const +{ + // Imported targets have their own link interface. + if(this->IsImported()) + { + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head)) + { + return &info->LinkInterface; + } + return 0; + } + + // Link interfaces are not supported for executables that do not + // export symbols. + if(this->GetType() == cmTarget::EXECUTABLE && + !this->IsExecutableWithExports()) + { + return 0; + } + + // Lookup any existing link interface for this configuration. + TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : "")); + + cmTargetInternals::LinkInterfaceMapType::iterator + i = this->Internal->LinkInterfaceMap.find(key); + if(i == this->Internal->LinkInterfaceMap.end()) + { + // Compute the link interface for this configuration. + cmTargetInternals::OptionalLinkInterface iface; + iface.ExplicitLibraries = this->ComputeLinkInterfaceLibraries(config, + iface, + head, + iface.Exists); // Store the information for this configuration. cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); i = this->Internal->LinkInterfaceMap.insert(entry).first; } - return i->second.Exists? &i->second : 0; + return i->second.Exists ? &i->second : 0; } //---------------------------------------------------------------------------- @@ -5225,8 +5281,8 @@ void cmTarget::GetTransitivePropertyTargets(const char* config, cmTarget const* headTarget, std::vector &tgts) const { - cmTarget::LinkInterface const* iface = this->GetLinkInterface(config, - headTarget); + cmTarget::LinkInterface const* iface + = this->GetLinkInterfaceLibraries(config, headTarget); if (!iface) { return; @@ -5387,8 +5443,8 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const char* config, // to the link implementation. { // The link implementation is the default link interface. - LinkImplementation const* impl = this->GetLinkImplementation(config, - headTarget); + LinkImplementation const* impl = + this->GetLinkImplementationLibraries(config, headTarget); iface.Libraries = impl->Libraries; if(this->PolicyStatusCMP0022 == cmPolicies::WARN && !this->Internal->PolicyWarnedCMP0022) @@ -5554,6 +5610,7 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, sscanf(reps, "%u", &iface.Multiplicity); } } + iface.Complete = true; } //---------------------------------------------------------------------------- @@ -5582,6 +5639,40 @@ cmTarget::GetLinkImplementation(const char* config, cmTarget const* head) const cmTargetInternals::LinkImplMapType::value_type entry(key, impl); i = this->Internal->LinkImplMap.insert(entry).first; } + else if (i->second.Languages.empty()) + { + this->ComputeLinkImplementationLanguages(i->second); + } + + return &i->second; +} + +//---------------------------------------------------------------------------- +cmTarget::LinkImplementation const* +cmTarget::GetLinkImplementationLibraries(const char* config, + cmTarget const* head) const +{ + // There is no link implementation for imported targets. + if(this->IsImported()) + { + return 0; + } + + // Lookup any existing link implementation for this configuration. + TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : "")); + + cmTargetInternals::LinkImplMapType::iterator + i = this->Internal->LinkImplMap.find(key); + if(i == this->Internal->LinkImplMap.end()) + { + // Compute the link implementation for this configuration. + LinkImplementation impl; + this->ComputeLinkImplementation(config, impl, head); + + // Store the information for this configuration. + cmTargetInternals::LinkImplMapType::value_type entry(key, impl); + i = this->Internal->LinkImplMap.insert(entry).first; + } return &i->second; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 8bc5af4..f3cd874 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -264,6 +264,8 @@ public: if the target cannot be linked. */ LinkInterface const* GetLinkInterface(const char* config, cmTarget const* headTarget) const; + LinkInterface const* GetLinkInterfaceLibraries(const char* config, + cmTarget const* headTarget) const; void GetTransitivePropertyTargets(const char* config, cmTarget const* headTarget, std::vector &libs) const; @@ -285,6 +287,9 @@ public: LinkImplementation const* GetLinkImplementation(const char* config, cmTarget const* head) const; + LinkImplementation const* GetLinkImplementationLibraries(const char* config, + cmTarget const* head) const; + /** Link information from the transitive closure of the link implementation and the interfaces of its dependencies. */ struct LinkClosure -- cgit v0.12 From a6dd4990dbfa1afadbaeea33250e52affa5e00d9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 12 Feb 2014 13:48:47 +0100 Subject: cmTarget: Create a temporary cmTarget in checkInterfacePropertyCompatibility This simplifies further refactoring. --- Source/cmTarget.cxx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ea031cd..eca8bb7 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4459,23 +4459,24 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, // target itself has a POSITION_INDEPENDENT_CODE which disagrees // with a dependency. - if (!li->Target) + cmTarget const* theTarget = li->Target; + if (!theTarget) { continue; } - const bool ifaceIsSet = li->Target->GetProperties() + const bool ifaceIsSet = theTarget->GetProperties() .find("INTERFACE_" + p) - != li->Target->GetProperties().end(); + != theTarget->GetProperties().end(); PropertyType ifacePropContent = - getTypedProperty(li->Target, + getTypedProperty(theTarget, ("INTERFACE_" + p).c_str(), 0); std::string reportEntry; if (ifaceIsSet) { reportEntry += " * Target \""; - reportEntry += li->Target->GetName(); + reportEntry += theTarget->GetName(); reportEntry += "\" property value \""; reportEntry += valueAsString(ifacePropContent); reportEntry += "\" "; @@ -4496,7 +4497,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, e << "Property " << p << " on target \"" << tgt->GetName() << "\" does\nnot match the " "INTERFACE_" << p << " property requirement\nof " - "dependency \"" << li->Target->GetName() << "\".\n"; + "dependency \"" << theTarget->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); break; } @@ -4530,7 +4531,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, << tgt->GetName() << "\" is\nimplied to be " << defaultValue << " because it was used to determine the link libraries\n" "already. The INTERFACE_" << p << " property on\ndependency \"" - << li->Target->GetName() << "\" is in conflict.\n"; + << theTarget->GetName() << "\" is in conflict.\n"; cmSystemTools::Error(e.str().c_str()); break; } @@ -4561,7 +4562,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, { cmOStringStream e; e << "The INTERFACE_" << p << " property of \"" - << li->Target->GetName() << "\" does\nnot agree with the value " + << theTarget->GetName() << "\" does\nnot agree with the value " "of " << p << " already determined\nfor \"" << tgt->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); -- cgit v0.12 From 5771f81d91d232a143345dc05835323f36ab7ecc Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 13 Feb 2014 18:27:31 +0100 Subject: cmTarget: Add GetTransitiveTargetClosure method. Replace calls to GetLinkInformation with calls to a method to get only the target closure, not the link languages etc. The replaced calls are used while evaluating generator expressions only. This makes transitive generator expression evaluation independent from the languages of a target. In a follow-up topic, it will be possible to make the languages depend on generator expression evaluation, via evaluation of the SOURCES and INTERFACE_SOURCES target properties. Because the order of entries is not the same as the final link line, the order of debug output is different in the RunCMake.CompatibleInterface test, because the BOOL_PROP7 target property is evaluated first. Adjust the test to account for that new order. --- Source/cmTarget.cxx | 76 ++++++++++++++++------ Source/cmTarget.h | 3 + .../CompatibleInterface/DebugProperties-stderr.txt | 14 ++-- 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index eca8bb7..7df2928 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4424,12 +4424,13 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet)); - cmComputeLinkInformation *info = tgt->GetLinkInformation(config); - if(!info) + std::vector deps; + tgt->GetTransitiveTargetClosure(config, tgt, deps); + + if(deps.empty()) { return propContent; } - const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); bool propInitialized = explicitlySet; std::string report = " * Target \""; @@ -4449,7 +4450,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, report += "\" property not set.\n"; } - for(cmComputeLinkInformation::ItemVector::const_iterator li = + for(std::vector::const_iterator li = deps.begin(); li != deps.end(); ++li) { @@ -4459,11 +4460,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, // target itself has a POSITION_INDEPENDENT_CODE which disagrees // with a dependency. - cmTarget const* theTarget = li->Target; - if (!theTarget) - { - continue; - } + cmTarget const* theTarget = *li; const bool ifaceIsSet = theTarget->GetProperties() .find("INTERFACE_" + p) @@ -4643,23 +4640,19 @@ bool isLinkDependentProperty(cmTarget const* tgt, const std::string &p, const char *interfaceProperty, const char *config) { - cmComputeLinkInformation *info = tgt->GetLinkInformation(config); - if(!info) + std::vector deps; + tgt->GetTransitiveTargetClosure(config, tgt, deps); + + if(deps.empty()) { return false; } - const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); - - for(cmComputeLinkInformation::ItemVector::const_iterator li = + for(std::vector::const_iterator li = deps.begin(); li != deps.end(); ++li) { - if (!li->Target) - { - continue; - } - const char *prop = li->Target->GetProperty(interfaceProperty); + const char *prop = (*li)->GetProperty(interfaceProperty); if (!prop) { continue; @@ -5278,6 +5271,51 @@ cmTarget::GetLinkInterfaceLibraries(const char* config, } //---------------------------------------------------------------------------- +void processILibs(const char* config, + cmTarget const* headTarget, + std::string const& name, + std::vector& tgts, std::set& emitted) +{ + if (cmTarget* tgt = headTarget->GetMakefile() + ->FindTargetToUse(name.c_str())) + { + if (emitted.insert(tgt).second) + { + tgts.push_back(tgt); + std::vector ilibs; + cmTarget::LinkInterface const* iface = + tgt->GetLinkInterfaceLibraries(config, headTarget); + if (iface) + { + for(std::vector::const_iterator + it = iface->Libraries.begin(); + it != iface->Libraries.end(); ++it) + { + processILibs(config, headTarget, *it, tgts, emitted); + } + } + } + } +} + +//---------------------------------------------------------------------------- +void cmTarget::GetTransitiveTargetClosure(const char* config, + cmTarget const* headTarget, + std::vector &tgts) const +{ + std::set emitted; + + cmTarget::LinkImplementation const* impl + = this->GetLinkImplementationLibraries(config, headTarget); + + for(std::vector::const_iterator it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) + { + processILibs(config, headTarget, *it, tgts, emitted); + } +} + +//---------------------------------------------------------------------------- void cmTarget::GetTransitivePropertyTargets(const char* config, cmTarget const* headTarget, std::vector &tgts) const diff --git a/Source/cmTarget.h b/Source/cmTarget.h index f3cd874..5dec9e2 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -269,6 +269,9 @@ public: void GetTransitivePropertyTargets(const char* config, cmTarget const* headTarget, std::vector &libs) const; + void GetTransitiveTargetClosure(const char* config, + cmTarget const* headTarget, + std::vector &libs) const; /** The link implementation specifies the direct library dependencies needed by the object files of the target. */ diff --git a/Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt b/Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt index 17b8a5c..82a34d5 100644 --- a/Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt +++ b/Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt @@ -1,4 +1,11 @@ CMake Debug Log: + Boolean compatibility of property "BOOL_PROP7" for target + "CompatibleInterface" \(result: "FALSE"\): + + \* Target "CompatibleInterface" property is implied by use. + \* Target "iface1" property value "FALSE" \(Agree\) ++ +CMake Debug Log: Boolean compatibility of property "BOOL_PROP1" for target "CompatibleInterface" \(result: "TRUE"\): @@ -40,13 +47,6 @@ CMake Debug Log: \* Target "iface2" property value "FALSE" \(Agree\) + CMake Debug Log: - Boolean compatibility of property "BOOL_PROP7" for target - "CompatibleInterface" \(result: "FALSE"\): - - \* Target "CompatibleInterface" property is implied by use. - \* Target "iface1" property value "FALSE" \(Agree\) -+ -CMake Debug Log: String compatibility of property "STRING_PROP1" for target "CompatibleInterface" \(result: "prop1"\): -- cgit v0.12 From d3682d8647789db759270a2f9c96493167468e61 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 14 Feb 2014 10:23:23 +0100 Subject: cmGeneratorTarget: Use a method to access the definition file. --- Source/cmGeneratorTarget.cxx | 6 ++++++ Source/cmGeneratorTarget.h | 3 ++- Source/cmMakefileTargetGenerator.cxx | 11 ++++++----- Source/cmNinjaTargetGenerator.cxx | 6 +++--- Source/cmVisualStudio10TargetGenerator.cxx | 6 +++--- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6223ed1..e2810ac 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -431,6 +431,12 @@ void cmGeneratorTarget::LookupObjectLibraries() } //---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetModuleDefinitionFile() const +{ + return this->ModuleDefinitionFile; +} + +//---------------------------------------------------------------------------- void cmGeneratorTarget::UseObjectLibraries(std::vector& objs) const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 9a3339d..51d51f3 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -52,7 +52,7 @@ public: cmLocalGenerator* LocalGenerator; cmGlobalGenerator const* GlobalGenerator; - std::string ModuleDefinitionFile; + std::string GetModuleDefinitionFile() const; /** Full path with trailing slash to the top-level directory holding object files for this target. Includes the build @@ -118,6 +118,7 @@ private: struct SourceEntry { std::vector Depends; }; typedef std::map SourceEntriesType; SourceEntriesType SourceEntries; + std::string ModuleDefinitionFile; std::vector CustomCommands; std::vector ExtraSources; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index c3ca85d..5a841ed 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1650,9 +1650,10 @@ void cmMakefileTargetGenerator this->AppendTargetDepends(depends); // Add a dependency on the link definitions file, if any. - if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + if(!def.empty()) { - depends.push_back(this->GeneratorTarget->ModuleDefinitionFile); + depends.push_back(def); } // Add user-specified dependencies. @@ -2019,7 +2020,8 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags) //---------------------------------------------------------------------------- void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) { - if(this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + if(def.empty()) { return; } @@ -2035,8 +2037,7 @@ void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) // Append the flag and value. Use ConvertToLinkReference to help // vs6's "cl -link" pass it to the linker. std::string flag = defFileFlag; - flag += (this->LocalGenerator->ConvertToLinkReference( - this->GeneratorTarget->ModuleDefinitionFile.c_str())); + flag += (this->LocalGenerator->ConvertToLinkReference(def.c_str())); this->LocalGenerator->AppendFlags(flags, flag.c_str()); } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 900af8d..5f6fc2d 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -498,10 +498,10 @@ cmNinjaTargetGenerator { this->WriteObjectBuildStatement(*si); } - if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + if(!def.empty()) { - this->ModuleDefinitionFile = this->ConvertToNinjaPath( - this->GeneratorTarget->ModuleDefinitionFile.c_str()); + this->ModuleDefinitionFile = this->ConvertToNinjaPath(def.c_str()); } { diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index ed7e243..d760b3f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1666,10 +1666,10 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) linkOptions.AddFlag("ImportLibrary", imLib.c_str()); linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str()); linkOptions.Parse(flags.c_str()); - if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + if(!def.empty()) { - linkOptions.AddFlag("ModuleDefinitionFile", - this->GeneratorTarget->ModuleDefinitionFile.c_str()); + linkOptions.AddFlag("ModuleDefinitionFile", def.c_str()); } this->LinkOptions[config] = pOptions.release(); -- cgit v0.12 From 64d398416ad678c1c57fbd3a7981623e28d69bca Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 13 Feb 2014 21:07:31 +0100 Subject: cmGeneratorTarget: Classify sources on demand, not up front. Implement a Visitor to hold the sequence of source file tests for populating outputs. Use VS 6 and 7 workaround from Brad King for lack of partial template specialization and function template specialization capabilities. This will make it possible to use context dependent generator expressions to determine the sources of a target. --- Source/cmGeneratorTarget.cxx | 349 +++++++++++++++++++++++++++++-------------- Source/cmGeneratorTarget.h | 17 +-- Source/cmGlobalGenerator.cxx | 1 - 3 files changed, 241 insertions(+), 126 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index e2810ac..4cb1904 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -25,6 +25,194 @@ #include "assert.h" //---------------------------------------------------------------------------- +void reportBadObjLib(std::vector const& badObjLib, + cmTarget *target, cmake *cm) +{ + if(!badObjLib.empty()) + { + cmOStringStream e; + e << "OBJECT library \"" << target->GetName() << "\" contains:\n"; + for(std::vector::const_iterator i = badObjLib.begin(); + i != badObjLib.end(); ++i) + { + e << " " << (*i)->GetLocation().GetName() << "\n"; + } + e << "but may contain only headers and sources that compile."; + cm->IssueMessage(cmake::FATAL_ERROR, e.str(), + target->GetBacktrace()); + } +} + +struct ObjectSourcesTag {}; +struct CustomCommandsTag {}; +struct ExtraSourcesTag {}; +struct HeaderSourcesTag {}; +struct ExternalObjectsTag {}; +struct IDLSourcesTag {}; +struct ResxTag {}; +struct ModuleDefinitionFileTag {}; + +#if !defined(_MSC_VER) || _MSC_VER >= 1310 +template +struct IsSameTag +{ + enum { + Result = false + }; +}; + +template +struct IsSameTag +{ + enum { + Result = true + }; +}; +#else +struct IsSameTagBase +{ + typedef char (&no_type)[1]; + typedef char (&yes_type)[2]; + template struct Check; + template static yes_type check(Check*, Check*); + static no_type check(...); +}; +template +struct IsSameTag: public IsSameTagBase +{ + enum { + Result = (sizeof(check(static_cast< Check* >(0), + static_cast< Check* >(0))) == + sizeof(yes_type)) + }; +}; +#endif + +template +struct DoAccept +{ + template static void Do(T&, cmSourceFile*) {} +}; + +template<> +struct DoAccept +{ + static void Do(std::vector& files, cmSourceFile* f) + { + files.push_back(f); + } + static void Do(cmGeneratorTarget::ResxData& data, cmSourceFile* f) + { + // Build and save the name of the corresponding .h file + // This relationship will be used later when building the project files. + // Both names would have been auto generated from Visual Studio + // where the user supplied the file name and Visual Studio + // appended the suffix. + std::string resx = f->GetFullPath(); + std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h"; + data.ExpectedResxHeaders.insert(hFileName); + data.ResxSources.push_back(f); + } + static void Do(std::string& data, cmSourceFile* f) + { + data = f->GetFullPath(); + } +}; + +//---------------------------------------------------------------------------- +template > +struct TagVisitor +{ + DataType& Data; + std::vector BadObjLibFiles; + cmTarget *Target; + cmGlobalGenerator *GlobalGenerator; + cmsys::RegularExpression Header; + bool IsObjLib; + + TagVisitor(cmTarget *target, DataType& data) + : Data(data), Target(target), + GlobalGenerator(target->GetMakefile() + ->GetLocalGenerator()->GetGlobalGenerator()), + Header(CM_HEADER_REGEX), + IsObjLib(target->GetType() == cmTarget::OBJECT_LIBRARY) + { + } + + ~TagVisitor() + { + reportBadObjLib(this->BadObjLibFiles, this->Target, + this->GlobalGenerator->GetCMakeInstance()); + } + + void Accept(cmSourceFile *sf) + { + std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); + if(sf->GetCustomCommand()) + { + DoAccept::Result>::Do(this->Data, sf); + } + else if(this->Target->GetType() == cmTarget::UTILITY) + { + DoAccept::Result>::Do(this->Data, sf); + } + else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY")) + { + DoAccept::Result>::Do(this->Data, sf); + } + else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT")) + { + DoAccept::Result>::Do(this->Data, sf); + if(this->IsObjLib) + { + this->BadObjLibFiles.push_back(sf); + } + } + else if(sf->GetLanguage()) + { + DoAccept::Result>::Do(this->Data, sf); + } + else if(ext == "def") + { + DoAccept::Result>::Do(this->Data, + sf); + if(this->IsObjLib) + { + this->BadObjLibFiles.push_back(sf); + } + } + else if(ext == "idl") + { + DoAccept::Result>::Do(this->Data, sf); + if(this->IsObjLib) + { + this->BadObjLibFiles.push_back(sf); + } + } + else if(ext == "resx") + { + DoAccept::Result>::Do(this->Data, sf); + } + else if(this->Header.find(sf->GetFullPath().c_str())) + { + DoAccept::Result>::Do(this->Data, sf); + } + else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) + { + DoAccept::Result>::Do(this->Data, sf); + } + else + { + DoAccept::Result>::Do(this->Data, sf); + if(this->IsObjLib && ext != "txt") + { + this->BadObjLibFiles.push_back(sf); + } + } + } +}; + +//---------------------------------------------------------------------------- cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t), SourceFileFlagsConstructed(false) { @@ -96,11 +284,34 @@ static void handleSystemIncludesDep(cmMakefile *mf, cmTarget* depTgt, } } +#define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE) \ + { \ + std::vector sourceFiles; \ + this->Target->GetSourceFiles(sourceFiles); \ + TagVisitor visitor(this->Target, data); \ + for(std::vector::const_iterator si = sourceFiles.begin(); \ + si != sourceFiles.end(); ++si) \ + { \ + visitor.Accept(*si); \ + } \ + } \ + + +#define IMPLEMENT_VISIT(DATA) \ + IMPLEMENT_VISIT_IMPL(DATA, EMPTY) \ + +#define EMPTY +#define COMMA , + //---------------------------------------------------------------------------- void -cmGeneratorTarget::GetObjectSources(std::vector &objs) const +cmGeneratorTarget::GetObjectSources(std::vector &data) const { - objs = this->ObjectSources; + IMPLEMENT_VISIT(ObjectSources); + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY) + { + this->ObjectSources = data; + } } //---------------------------------------------------------------------------- @@ -129,49 +340,53 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const } //---------------------------------------------------------------------------- -void cmGeneratorTarget::GetResxSources(std::vector& srcs) const +void cmGeneratorTarget::GetIDLSources(std::vector& data) const { - srcs = this->ResxSources; + IMPLEMENT_VISIT(IDLSources); } //---------------------------------------------------------------------------- -void cmGeneratorTarget::GetIDLSources(std::vector& srcs) const +void +cmGeneratorTarget::GetHeaderSources(std::vector& data) const { - srcs = this->IDLSources; + IMPLEMENT_VISIT(HeaderSources); } //---------------------------------------------------------------------------- -void -cmGeneratorTarget::GetHeaderSources(std::vector& srcs) const +void cmGeneratorTarget::GetExtraSources(std::vector& data) const { - srcs = this->HeaderSources; + IMPLEMENT_VISIT(ExtraSources); } //---------------------------------------------------------------------------- -void cmGeneratorTarget::GetExtraSources(std::vector& srcs) const +void +cmGeneratorTarget::GetCustomCommands(std::vector& data) const { - srcs = this->ExtraSources; + IMPLEMENT_VISIT(CustomCommands); } //---------------------------------------------------------------------------- void -cmGeneratorTarget::GetCustomCommands(std::vector& srcs) const +cmGeneratorTarget::GetExternalObjects(std::vector& data) const { - srcs = this->CustomCommands; + IMPLEMENT_VISIT(ExternalObjects); } //---------------------------------------------------------------------------- void cmGeneratorTarget::GetExpectedResxHeaders(std::set& srcs) const { - srcs = this->ExpectedResxHeaders; + ResxData data; + IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) + srcs = data.ExpectedResxHeaders; } //---------------------------------------------------------------------------- -void -cmGeneratorTarget::GetExternalObjects(std::vector& srcs) const +void cmGeneratorTarget::GetResxSources(std::vector& srcs) const { - srcs = this->ExternalObjects; + ResxData data; + IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) + srcs = data.ResxSources; } //---------------------------------------------------------------------------- @@ -283,102 +498,6 @@ void cmGeneratorTarget::GetSourceFiles(std::vector &files) const } //---------------------------------------------------------------------------- -void cmGeneratorTarget::ClassifySources() -{ - cmsys::RegularExpression header(CM_HEADER_REGEX); - - cmTarget::TargetType targetType = this->Target->GetType(); - bool isObjLib = targetType == cmTarget::OBJECT_LIBRARY; - - std::vector badObjLib; - std::vector sources; - this->Target->GetSourceFiles(sources); - for(std::vector::const_iterator si = sources.begin(); - si != sources.end(); ++si) - { - cmSourceFile* sf = *si; - std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); - if(sf->GetCustomCommand()) - { - this->CustomCommands.push_back(sf); - } - else if(targetType == cmTarget::UTILITY) - { - this->ExtraSources.push_back(sf); - } - else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY")) - { - this->HeaderSources.push_back(sf); - } - else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT")) - { - this->ExternalObjects.push_back(sf); - if(isObjLib) { badObjLib.push_back(sf); } - } - else if(sf->GetLanguage()) - { - this->ObjectSources.push_back(sf); - } - else if(ext == "def") - { - this->ModuleDefinitionFile = sf->GetFullPath(); - if(isObjLib) { badObjLib.push_back(sf); } - } - else if(ext == "idl") - { - this->IDLSources.push_back(sf); - if(isObjLib) { badObjLib.push_back(sf); } - } - else if(ext == "resx") - { - // Build and save the name of the corresponding .h file - // This relationship will be used later when building the project files. - // Both names would have been auto generated from Visual Studio - // where the user supplied the file name and Visual Studio - // appended the suffix. - std::string resx = sf->GetFullPath(); - std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h"; - this->ExpectedResxHeaders.insert(hFileName); - this->ResxSources.push_back(sf); - } - else if(header.find(sf->GetFullPath().c_str())) - { - this->HeaderSources.push_back(sf); - } - else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) - { - // We only get here if a source file is not an external object - // and has an extension that is listed as an ignored file type. - // No message or diagnosis should be given. - this->ExtraSources.push_back(sf); - } - else - { - this->ExtraSources.push_back(sf); - if(isObjLib && ext != "txt") - { - badObjLib.push_back(sf); - } - } - } - - if(!badObjLib.empty()) - { - cmOStringStream e; - e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n"; - for(std::vector::iterator i = badObjLib.begin(); - i != badObjLib.end(); ++i) - { - e << " " << (*i)->GetLocation().GetName() << "\n"; - } - e << "but may contain only headers and sources that compile."; - this->GlobalGenerator->GetCMakeInstance() - ->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); - } -} - -//---------------------------------------------------------------------------- void cmGeneratorTarget::LookupObjectLibraries() { std::vector const& objLibs = @@ -433,7 +552,9 @@ void cmGeneratorTarget::LookupObjectLibraries() //---------------------------------------------------------------------------- std::string cmGeneratorTarget::GetModuleDefinitionFile() const { - return this->ModuleDefinitionFile; + std::string data; + IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile, COMMA std::string) + return data; } //---------------------------------------------------------------------------- diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 51d51f3..1e6ce64 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -82,7 +82,6 @@ public: */ void TraceDependencies(); - void ClassifySources(); void LookupObjectLibraries(); /** Get sources that must be built before the given source. */ @@ -113,23 +112,19 @@ public: struct SourceFileFlags GetTargetSourceFileFlags(const cmSourceFile* sf) const; + struct ResxData { + mutable std::set ExpectedResxHeaders; + mutable std::vector ResxSources; + }; private: friend class cmTargetTraceDependencies; struct SourceEntry { std::vector Depends; }; typedef std::map SourceEntriesType; SourceEntriesType SourceEntries; - std::string ModuleDefinitionFile; - - std::vector CustomCommands; - std::vector ExtraSources; - std::vector HeaderSources; - std::vector ExternalObjects; - std::vector IDLSources; - std::vector ResxSources; + std::map Objects; std::set ExplicitObjectName; - std::set ExpectedResxHeaders; - std::vector ObjectSources; + mutable std::vector ObjectSources; std::vector ObjectLibraries; mutable std::map > SystemIncludesCache; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index e143eba..f76c6d1 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1439,7 +1439,6 @@ void cmGlobalGenerator::ComputeGeneratorTargetObjects() continue; } cmGeneratorTarget* gt = ti->second; - gt->ClassifySources(); gt->LookupObjectLibraries(); this->ComputeTargetObjects(gt); } -- cgit v0.12 From f9d5b1fd0fe1e1c5a0083c6518c7da6c36776042 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 14 Feb 2014 12:24:13 +0100 Subject: Handle Mac OSX source flags for individual files lazily. The actual list of files will become config dependent in a follow-up commit. --- Source/cmGeneratorTarget.cxx | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 4cb1904..a7b2fb6 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1009,6 +1009,23 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const { flags = si->second; } + else + { + // Handle the MACOSX_PACKAGE_LOCATION property on source files that + // were not listed in one of the other lists. + if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) + { + flags.MacFolder = location; + if(strcmp(location, "Resources") == 0) + { + flags.Type = cmGeneratorTarget::SourceFileTypeResource; + } + else + { + flags.Type = cmGeneratorTarget::SourceFileTypeMacContent; + } + } + } return flags; } @@ -1072,30 +1089,4 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const } } } - - // Handle the MACOSX_PACKAGE_LOCATION property on source files that - // were not listed in one of the other lists. - std::vector sources; - this->GetSourceFiles(sources); - for(std::vector::const_iterator si = sources.begin(); - si != sources.end(); ++si) - { - cmSourceFile* sf = *si; - if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) - { - SourceFileFlags& flags = this->SourceFlagsMap[sf]; - if(flags.Type == cmGeneratorTarget::SourceFileTypeNormal) - { - flags.MacFolder = location; - if(strcmp(location, "Resources") == 0) - { - flags.Type = cmGeneratorTarget::SourceFileTypeResource; - } - else - { - flags.Type = cmGeneratorTarget::SourceFileTypeMacContent; - } - } - } - } } -- cgit v0.12