Merge topic 'target-SOURCES-refactor'

f9d5b1fd Handle Mac OSX source flags for individual files lazily.
64d39841 cmGeneratorTarget: Classify sources on demand, not up front.
d3682d86 cmGeneratorTarget: Use a method to access the definition file.
5771f81d cmTarget: Add GetTransitiveTargetClosure method.
a6dd4990 cmTarget: Create a temporary cmTarget in checkInterfacePropertyCompatibility
b8b99cc1 cmTarget: Avoid computing languages when computing transitive targets.
01bca553 cmTarget: Move ComputeLinkInterface to the internal class.
d93e1af2 cmTarget: Extract a ComputeLinkInterfaceLibraries method.
3bcb197c cmTarget: Re-arrange the ComputeLinkInterface method.
326d07d2 cmTarget: Extract a ComputeLinkImplementationLanguages method.
21e91350 cmTarget: Change GetTransitivePropertyLinkLibraries to output targets.
f81eb49e cmTarget: Find source files on request.
84e5f5a0 cmTarget: Move SourceFileFlags to cmGeneratorTarget.
This commit is contained in:
Brad King 2014-02-25 11:18:12 -05:00 committed by CMake Topic Stage
commit 049790c0eb
14 changed files with 786 additions and 506 deletions

View File

@ -800,7 +800,7 @@ static const char* targetPropertyTransitiveWhitelist[] = {
#undef TRANSITIVE_PROPERTY_NAME
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
std::string getLinkedTargetsContent(const std::vector<cmTarget*> &targets,
cmTarget const* target,
cmTarget const* headTarget,
cmGeneratorExpressionContext *context,
@ -811,23 +811,21 @@ std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
std::string sep;
std::string depString;
for (std::vector<std::string>::const_iterator
it = libraries.begin();
it != libraries.end(); ++it)
for (std::vector<cmTarget*>::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 + "$<TARGET_PROPERTY:" + *it + "," + interfacePropertyName + ">";
sep = ";";
}
depString +=
sep + "$<TARGET_PROPERTY:" +
(*it)->GetName() + "," + interfacePropertyName + ">";
sep = ";";
}
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString);
std::string linkedTargetsContent = cge->Evaluate(context->Makefile,
@ -843,6 +841,27 @@ std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
return linkedTargetsContent;
}
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
cmTarget const* target,
cmTarget const* headTarget,
cmGeneratorExpressionContext *context,
cmGeneratorExpressionDAGChecker *dagChecker,
const std::string &interfacePropertyName)
{
std::vector<cmTarget*> tgts;
for (std::vector<std::string>::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<std::string> libs;
target->GetTransitivePropertyLinkLibraries(context->Config,
headTarget, libs);
if (!libs.empty())
std::vector<cmTarget*> tgts;
target->GetTransitivePropertyTargets(context->Config,
headTarget, tgts);
if (!tgts.empty())
{
linkedTargetsContent =
getLinkedTargetsContent(libs, target,
getLinkedTargetsContent(tgts, target,
headTarget,
context, &dagChecker,
interfacePropertyName);
@ -1080,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 =

View File

@ -25,7 +25,196 @@
#include "assert.h"
//----------------------------------------------------------------------------
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib,
cmTarget *target, cmake *cm)
{
if(!badObjLib.empty())
{
cmOStringStream e;
e << "OBJECT library \"" << target->GetName() << "\" contains:\n";
for(std::vector<cmSourceFile*>::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<typename Tag, typename OtherTag>
struct IsSameTag
{
enum {
Result = false
};
};
template<typename Tag>
struct IsSameTag<Tag, Tag>
{
enum {
Result = true
};
};
#else
struct IsSameTagBase
{
typedef char (&no_type)[1];
typedef char (&yes_type)[2];
template<typename T> struct Check;
template<typename T> static yes_type check(Check<T>*, Check<T>*);
static no_type check(...);
};
template<typename Tag1, typename Tag2>
struct IsSameTag: public IsSameTagBase
{
enum {
Result = (sizeof(check(static_cast< Check<Tag1>* >(0),
static_cast< Check<Tag2>* >(0))) ==
sizeof(yes_type))
};
};
#endif
template<bool>
struct DoAccept
{
template <typename T> static void Do(T&, cmSourceFile*) {}
};
template<>
struct DoAccept<true>
{
static void Do(std::vector<cmSourceFile*>& 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<typename Tag, typename DataType = std::vector<cmSourceFile*> >
struct TagVisitor
{
DataType& Data;
std::vector<cmSourceFile*> 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<IsSameTag<Tag, CustomCommandsTag>::Result>::Do(this->Data, sf);
}
else if(this->Target->GetType() == cmTarget::UTILITY)
{
DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
}
else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY"))
{
DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
}
else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
{
DoAccept<IsSameTag<Tag, ExternalObjectsTag>::Result>::Do(this->Data, sf);
if(this->IsObjLib)
{
this->BadObjLibFiles.push_back(sf);
}
}
else if(sf->GetLanguage())
{
DoAccept<IsSameTag<Tag, ObjectSourcesTag>::Result>::Do(this->Data, sf);
}
else if(ext == "def")
{
DoAccept<IsSameTag<Tag, ModuleDefinitionFileTag>::Result>::Do(this->Data,
sf);
if(this->IsObjLib)
{
this->BadObjLibFiles.push_back(sf);
}
}
else if(ext == "idl")
{
DoAccept<IsSameTag<Tag, IDLSourcesTag>::Result>::Do(this->Data, sf);
if(this->IsObjLib)
{
this->BadObjLibFiles.push_back(sf);
}
}
else if(ext == "resx")
{
DoAccept<IsSameTag<Tag, ResxTag>::Result>::Do(this->Data, sf);
}
else if(this->Header.find(sf->GetFullPath().c_str()))
{
DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
}
else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str()))
{
DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
}
else
{
DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
if(this->IsObjLib && ext != "txt")
{
this->BadObjLibFiles.push_back(sf);
}
}
}
};
//----------------------------------------------------------------------------
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t),
SourceFileFlagsConstructed(false)
{
this->Makefile = this->Target->GetMakefile();
this->LocalGenerator = this->Makefile->GetLocalGenerator();
@ -62,19 +251,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<std::string>& result,
bool excludeImported)
{
cmTarget* depTgt = mf->FindTargetToUse(name);
if (!depTgt)
{
return;
}
cmListFileBacktrace lfbt;
if (const char* dirs =
@ -102,11 +284,34 @@ static void handleSystemIncludesDep(cmMakefile *mf, const std::string &name,
}
}
#define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE) \
{ \
std::vector<cmSourceFile*> sourceFiles; \
this->Target->GetSourceFiles(sourceFiles); \
TagVisitor<DATA ## Tag DATATYPE> visitor(this->Target, data); \
for(std::vector<cmSourceFile*>::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<cmSourceFile*> &objs) const
cmGeneratorTarget::GetObjectSources(std::vector<cmSourceFile*> &data) const
{
objs = this->ObjectSources;
IMPLEMENT_VISIT(ObjectSources);
if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
{
this->ObjectSources = data;
}
}
//----------------------------------------------------------------------------
@ -135,49 +340,53 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
}
//----------------------------------------------------------------------------
void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile*>& srcs) const
void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile*>& data) const
{
srcs = this->ResxSources;
}
//----------------------------------------------------------------------------
void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile*>& srcs) const
{
srcs = this->IDLSources;
IMPLEMENT_VISIT(IDLSources);
}
//----------------------------------------------------------------------------
void
cmGeneratorTarget::GetHeaderSources(std::vector<cmSourceFile*>& srcs) const
cmGeneratorTarget::GetHeaderSources(std::vector<cmSourceFile*>& data) const
{
srcs = this->HeaderSources;
IMPLEMENT_VISIT(HeaderSources);
}
//----------------------------------------------------------------------------
void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile*>& srcs) const
void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile*>& data) const
{
srcs = this->ExtraSources;
IMPLEMENT_VISIT(ExtraSources);
}
//----------------------------------------------------------------------------
void
cmGeneratorTarget::GetCustomCommands(std::vector<cmSourceFile*>& srcs) const
cmGeneratorTarget::GetCustomCommands(std::vector<cmSourceFile*>& data) const
{
srcs = this->CustomCommands;
IMPLEMENT_VISIT(CustomCommands);
}
//----------------------------------------------------------------------------
void
cmGeneratorTarget::GetExternalObjects(std::vector<cmSourceFile*>& data) const
{
IMPLEMENT_VISIT(ExternalObjects);
}
//----------------------------------------------------------------------------
void
cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& srcs) const
{
srcs = this->ExpectedResxHeaders;
ResxData data;
IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
srcs = data.ExpectedResxHeaders;
}
//----------------------------------------------------------------------------
void
cmGeneratorTarget::GetExternalObjects(std::vector<cmSourceFile*>& srcs) const
void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile*>& srcs) const
{
srcs = this->ExternalObjects;
ResxData data;
IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
srcs = data.ResxSources;
}
//----------------------------------------------------------------------------
@ -224,26 +433,25 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir,
&dagChecker), result);
}
std::set<cmStdString> uniqueDeps;
std::set<cmTarget*> uniqueDeps;
for(std::vector<std::string>::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);
continue;
}
if (!tgt)
{
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<std::string> deps;
tgt->GetTransitivePropertyLinkLibraries(config, this->Target, deps);
std::vector<cmTarget*> deps;
tgt->GetTransitivePropertyTargets(config, this->Target, deps);
for(std::vector<std::string>::const_iterator di = deps.begin();
for(std::vector<cmTarget*>::const_iterator di = deps.begin();
di != deps.end(); ++di)
{
if (uniqueDeps.insert(*di).second)
@ -289,102 +497,6 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
this->Target->GetSourceFiles(files);
}
//----------------------------------------------------------------------------
void cmGeneratorTarget::ClassifySources()
{
cmsys::RegularExpression header(CM_HEADER_REGEX);
cmTarget::TargetType targetType = this->Target->GetType();
bool isObjLib = targetType == cmTarget::OBJECT_LIBRARY;
std::vector<cmSourceFile*> badObjLib;
std::vector<cmSourceFile*> sources;
this->Target->GetSourceFiles(sources);
for(std::vector<cmSourceFile*>::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<cmSourceFile*>::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()
{
@ -437,6 +549,14 @@ void cmGeneratorTarget::LookupObjectLibraries()
}
}
//----------------------------------------------------------------------------
std::string cmGeneratorTarget::GetModuleDefinitionFile() const
{
std::string data;
IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile, COMMA std::string)
return data;
}
//----------------------------------------------------------------------------
void
cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs) const
@ -876,3 +996,97 @@ 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<cmSourceFile const*, SourceFileFlags>::iterator si =
this->SourceFlagsMap.find(sf);
if(si != this->SourceFlagsMap.end())
{
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;
}
//----------------------------------------------------------------------------
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<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(std::vector<std::string>::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<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(std::vector<std::string>::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<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(std::vector<std::string>::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;
}
}
}
}

View File

@ -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
@ -82,31 +82,56 @@ public:
*/
void TraceDependencies();
void ClassifySources();
void LookupObjectLibraries();
/** Get sources that must be built before the given source. */
std::vector<cmSourceFile*> 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;
struct ResxData {
mutable std::set<std::string> ExpectedResxHeaders;
mutable std::vector<cmSourceFile*> ResxSources;
};
private:
friend class cmTargetTraceDependencies;
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
SourceEntriesType SourceEntries;
std::vector<cmSourceFile*> CustomCommands;
std::vector<cmSourceFile*> ExtraSources;
std::vector<cmSourceFile*> HeaderSources;
std::vector<cmSourceFile*> ExternalObjects;
std::vector<cmSourceFile*> IDLSources;
std::vector<cmSourceFile*> ResxSources;
std::map<cmSourceFile const*, std::string> Objects;
std::set<cmSourceFile const*> ExplicitObjectName;
std::set<std::string> ExpectedResxHeaders;
std::vector<cmSourceFile*> ObjectSources;
mutable std::vector<cmSourceFile*> ObjectSources;
std::vector<cmTarget*> ObjectLibraries;
mutable std::map<std::string, std::vector<std::string> > SystemIncludesCache;
void ConstructSourceFileFlags() const;
mutable bool SourceFileFlagsConstructed;
mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
cmGeneratorTarget(cmGeneratorTarget const&);
void operator=(cmGeneratorTarget const&);
};

View File

@ -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
@ -1305,35 +1299,6 @@ bool cmGlobalGenerator::ComputeTargetDepends()
return true;
}
//----------------------------------------------------------------------------
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)
{
@ -1474,7 +1439,6 @@ void cmGlobalGenerator::ComputeGeneratorTargetObjects()
continue;
}
cmGeneratorTarget* gt = ti->second;
gt->ClassifySources();
gt->LookupObjectLibraries();
this->ComputeTargetObjects(gt);
}

View File

@ -340,7 +340,6 @@ protected:
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
bool CheckTargets();
typedef std::vector<std::pair<cmQtAutoGenerators,
cmTarget const*> > AutogensType;
void CreateQtAutoGeneratorsTargets(AutogensType& autogens);

View File

@ -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<std::string> objs;
this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
gtgt->UseObjectLibraries(objs);
for(std::vector<std::string>::const_iterator
oi = objs.begin(); oi != objs.end(); ++oi)
{
@ -1138,9 +1140,9 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
for(std::vector<cmSourceFile*>::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);
}

View File

@ -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());
}

View File

@ -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());
}
{

View File

@ -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<cmSourceFile*> const& sources,
for(std::vector<cmSourceFile*>::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;

View File

@ -59,7 +59,7 @@ private:
bool MustSkip();
private:
cmTarget* Target;
cmGeneratorTarget* GT;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
const char* ConfigName;

View File

@ -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<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
mutable bool SourceFileFlagsConstructed;
// The backtrace when the target was created.
cmListFileBacktrace Backtrace;
@ -101,9 +96,17 @@ 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,
cmTarget const* head,
const char *explicitLibraries) const;
typedef std::map<TargetConfigPair, OptionalLinkInterface>
LinkInterfaceMapType;
LinkInterfaceMapType LinkInterfaceMap;
@ -527,10 +530,11 @@ bool cmTarget::IsBundleOnApple() const
}
//----------------------------------------------------------------------------
bool cmTarget::FindSourceFiles()
void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
{
assert(this->GetType() != INTERFACE_LIBRARY);
for(std::vector<cmSourceFile*>::const_iterator
si = this->SourceFiles.begin();
si = this->SourceFiles.begin();
si != this->SourceFiles.end(); ++si)
{
std::string e;
@ -542,16 +546,9 @@ bool cmTarget::FindSourceFiles()
cm->IssueMessage(cmake::FATAL_ERROR, e,
this->GetBacktrace());
}
return false;
return;
}
}
return true;
}
//----------------------------------------------------------------------------
void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
{
assert(this->GetType() != INTERFACE_LIBRARY);
files = this->SourceFiles;
}
@ -647,109 +644,6 @@ void cmTarget::ProcessSourceExpression(std::string const& expr)
}
}
//----------------------------------------------------------------------------
struct cmTarget::SourceFileFlags
cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
{
struct SourceFileFlags flags;
this->ConstructSourceFileFlags();
std::map<cmSourceFile const*, SourceFileFlags>::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<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(std::vector<std::string>::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<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(std::vector<std::string>::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<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(std::vector<std::string>::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<cmSourceFile*> sources;
this->GetSourceFiles(sources);
for(std::vector<cmSourceFile*>::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,
@ -4530,12 +4424,13 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
assert((impliedByUse ^ explicitlySet)
|| (!impliedByUse && !explicitlySet));
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
if(!info)
std::vector<cmTarget*> deps;
tgt->GetTransitiveTargetClosure(config, tgt, deps);
if(deps.empty())
{
return propContent;
}
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
bool propInitialized = explicitlySet;
std::string report = " * Target \"";
@ -4555,7 +4450,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
report += "\" property not set.\n";
}
for(cmComputeLinkInformation::ItemVector::const_iterator li =
for(std::vector<cmTarget*>::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
@ -4565,23 +4460,20 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
// target itself has a POSITION_INDEPENDENT_CODE which disagrees
// with a dependency.
if (!li->Target)
{
continue;
}
cmTarget const* theTarget = *li;
const bool ifaceIsSet = li->Target->GetProperties()
const bool ifaceIsSet = theTarget->GetProperties()
.find("INTERFACE_" + p)
!= li->Target->GetProperties().end();
!= theTarget->GetProperties().end();
PropertyType ifacePropContent =
getTypedProperty<PropertyType>(li->Target,
getTypedProperty<PropertyType>(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<PropertyType>(ifacePropContent);
reportEntry += "\" ";
@ -4602,7 +4494,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;
}
@ -4636,7 +4528,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;
}
@ -4667,7 +4559,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());
@ -4748,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<cmTarget*> 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<cmTarget*>::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;
@ -5316,24 +5204,124 @@ 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);
iface.ExplicitLibraries =
this->ComputeLinkInterfaceLibraries(config, iface, head, iface.Exists);
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;
}
//----------------------------------------------------------------------------
void cmTarget::GetTransitivePropertyLinkLibraries(
const char* config,
cmTarget const* headTarget,
std::vector<std::string> &libs) const
void processILibs(const char* config,
cmTarget const* headTarget,
std::string const& name,
std::vector<cmTarget*>& tgts, std::set<cmTarget*>& emitted)
{
cmTarget::LinkInterface const* iface = this->GetLinkInterface(config,
headTarget);
if (cmTarget* tgt = headTarget->GetMakefile()
->FindTargetToUse(name.c_str()))
{
if (emitted.insert(tgt).second)
{
tgts.push_back(tgt);
std::vector<std::string> ilibs;
cmTarget::LinkInterface const* iface =
tgt->GetLinkInterfaceLibraries(config, headTarget);
if (iface)
{
for(std::vector<std::string>::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<cmTarget*> &tgts) const
{
std::set<cmTarget*> emitted;
cmTarget::LinkImplementation const* impl
= this->GetLinkImplementationLibraries(config, headTarget);
for(std::vector<std::string>::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<cmTarget*> &tgts) const
{
cmTarget::LinkInterface const* iface
= this->GetLinkInterfaceLibraries(config, headTarget);
if (!iface)
{
return;
@ -5342,7 +5330,15 @@ void cmTarget::GetTransitivePropertyLinkLibraries(
|| this->GetPolicyStatusCMP0022() == cmPolicies::WARN
|| this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
{
libs = iface->Libraries;
for(std::vector<std::string>::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;
}
@ -5360,17 +5356,30 @@ void cmTarget::GetTransitivePropertyLinkLibraries(
cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
linkIfaceProp, 0, 0);
dagChecker.SetTransitivePropertiesOnly();
std::vector<std::string> libs;
cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate(
this->Makefile,
config,
false,
headTarget,
this, &dagChecker), libs);
for(std::vector<std::string>::const_iterator it = libs.begin();
it != libs.end(); ++it)
{
if (cmTarget* tgt = headTarget->GetMakefile()
->FindTargetToUse(it->c_str()))
{
tgts.push_back(tgt);
}
}
}
//----------------------------------------------------------------------------
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 = "_";
@ -5446,8 +5455,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)
{
@ -5462,52 +5473,6 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
false,
headTarget,
this, &dagChecker), iface.Libraries);
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<cmStdString> emitted;
for(std::vector<std::string>::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<std::string>::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)
@ -5517,17 +5482,9 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// to the link implementation.
{
// The link implementation is the default link interface.
LinkImplementation const* impl = this->GetLinkImplementation(config,
headTarget);
iface.ImplementationIsInterface = true;
LinkImplementation const* impl =
this->GetLinkImplementationLibraries(config, headTarget);
iface.Libraries = impl->Libraries;
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)
{
@ -5592,25 +5549,107 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
}
}
}
return explicitLibraries;
}
if(this->GetType() == cmTarget::STATIC_LIBRARY)
//----------------------------------------------------------------------------
void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget,
const char* config,
OptionalLinkInterface& iface,
cmTarget const* headTarget,
const char* explicitLibraries) const
{
if(explicitLibraries)
{
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.
std::set<cmStdString> emitted;
for(std::vector<std::string>::const_iterator
li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li)
{
emitted.insert(*li);
}
if (thisTarget->GetType() != cmTarget::INTERFACE_LIBRARY)
{
cmTarget::LinkImplementation const* impl =
thisTarget->GetLinkImplementation(config, headTarget);
for(std::vector<std::string>::const_iterator
li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
{
if(emitted.insert(*li).second)
{
if(cmTarget* tgt = thisTarget->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(thisTarget->LinkLanguagePropagatesToDependents())
{
// Targets using this archive need its language runtime libraries.
iface.Languages = impl->Languages;
}
}
}
}
else if (thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN
|| thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD)
{
// The link implementation is the default link interface.
cmTarget::LinkImplementation const*
impl = thisTarget->GetLinkImplementation(config, headTarget);
iface.ImplementationIsInterface = true;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
if(thisTarget->LinkLanguagePropagatesToDependents())
{
// Targets using this archive need its language runtime libraries.
iface.Languages = impl->Languages;
}
}
if(thisTarget->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";
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);
}
}
return true;
iface.Complete = true;
}
//----------------------------------------------------------------------------
@ -5626,6 +5665,41 @@ cmTarget::GetLinkImplementation(const char* config, cmTarget const* head) const
// 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);
this->ComputeLinkImplementationLanguages(impl);
// Store the information for this configuration.
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())
@ -5715,7 +5789,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<cmStdString> languages;
// Get languages used in our source files.

View File

@ -139,34 +139,6 @@ public:
return this->ObjectLibraries;
}
/**
* 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.
*/
@ -292,9 +264,14 @@ public:
if the target cannot be linked. */
LinkInterface const* GetLinkInterface(const char* config,
cmTarget const* headTarget) const;
void GetTransitivePropertyLinkLibraries(const char* config,
LinkInterface const* GetLinkInterfaceLibraries(const char* config,
cmTarget const* headTarget) const;
void GetTransitivePropertyTargets(const char* config,
cmTarget const* headTarget,
std::vector<std::string> &libs) const;
std::vector<cmTarget*> &libs) const;
void GetTransitiveTargetClosure(const char* config,
cmTarget const* headTarget,
std::vector<cmTarget*> &libs) const;
/** The link implementation specifies the direct library
dependencies needed by the object files of the target. */
@ -313,6 +290,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
@ -358,11 +338,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;
@ -723,12 +698,15 @@ private:
void CheckPropertyCompatibility(cmComputeLinkInformation *info,
const char* config) const;
bool ComputeLinkInterface(const char* config, LinkInterface& iface,
cmTarget const* head) const;
const char* ComputeLinkInterfaceLibraries(const char* config,
LinkInterface& iface,
cmTarget const* head,
bool &exists) const;
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;
@ -756,7 +734,6 @@ private:
friend class cmTargetTraceDependencies;
cmTargetInternalPointer Internal;
void ConstructSourceFileFlags() const;
void ComputeVersionedName(std::string& vName,
std::string const& prefix,
std::string const& base,

View File

@ -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();

View File

@ -1,3 +1,10 @@
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"\):
@ -39,13 +46,6 @@ CMake Debug Log:
\* Target "iface1" property value "FALSE" \(Interface set\)
\* 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"\):