summaryrefslogtreecommitdiffstats
path: root/Source/cmGeneratorTarget.cxx
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2014-02-13 20:07:31 (GMT)
committerStephen Kelly <steveire@gmail.com>2014-02-24 15:44:51 (GMT)
commit64d398416ad678c1c57fbd3a7981623e28d69bca (patch)
tree946a012e2e5321e236210bdc4d8835588b777d4a /Source/cmGeneratorTarget.cxx
parentd3682d8647789db759270a2f9c96493167468e61 (diff)
downloadCMake-64d398416ad678c1c57fbd3a7981623e28d69bca.zip
CMake-64d398416ad678c1c57fbd3a7981623e28d69bca.tar.gz
CMake-64d398416ad678c1c57fbd3a7981623e28d69bca.tar.bz2
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.
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r--Source/cmGeneratorTarget.cxx349
1 files changed, 235 insertions, 114 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<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)
{
@@ -96,11 +284,34 @@ static void handleSystemIncludesDep(cmMakefile *mf, cmTarget* depTgt,
}
}
+#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;
+ }
}
//----------------------------------------------------------------------------
@@ -129,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;
+ IMPLEMENT_VISIT(IDLSources);
}
//----------------------------------------------------------------------------
-void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile*>& srcs) const
+void
+cmGeneratorTarget::GetHeaderSources(std::vector<cmSourceFile*>& data) const
{
- srcs = this->IDLSources;
+ IMPLEMENT_VISIT(HeaderSources);
}
//----------------------------------------------------------------------------
-void
-cmGeneratorTarget::GetHeaderSources(std::vector<cmSourceFile*>& srcs) const
+void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile*>& data) const
{
- srcs = this->HeaderSources;
+ IMPLEMENT_VISIT(ExtraSources);
}
//----------------------------------------------------------------------------
-void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile*>& srcs) const
+void
+cmGeneratorTarget::GetCustomCommands(std::vector<cmSourceFile*>& data) const
{
- srcs = this->ExtraSources;
+ IMPLEMENT_VISIT(CustomCommands);
}
//----------------------------------------------------------------------------
void
-cmGeneratorTarget::GetCustomCommands(std::vector<cmSourceFile*>& srcs) const
+cmGeneratorTarget::GetExternalObjects(std::vector<cmSourceFile*>& data) const
{
- srcs = this->CustomCommands;
+ 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;
}
//----------------------------------------------------------------------------
@@ -283,102 +498,6 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &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<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()
{
std::vector<std::string> 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;
}
//----------------------------------------------------------------------------