summaryrefslogtreecommitdiffstats
path: root/Source/cmCPluginAPI.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2007-06-18 15:59:23 (GMT)
committerBrad King <brad.king@kitware.com>2007-06-18 15:59:23 (GMT)
commit35936433e11728397dcdb2beab615674bfa79ec7 (patch)
tree8222a4daea955055c852d6db058421a570a8f6b2 /Source/cmCPluginAPI.cxx
parentef81ac50e5d6e981088c00e822fde538d9da9e37 (diff)
downloadCMake-35936433e11728397dcdb2beab615674bfa79ec7.zip
CMake-35936433e11728397dcdb2beab615674bfa79ec7.tar.gz
CMake-35936433e11728397dcdb2beab615674bfa79ec7.tar.bz2
ENH: Merging changes from branch CMake-SourceFile2-b between tags
CMake-SourceFile2-bp and CMake-SourceFile2-b-mp1 to trunk. This commit is surrounded by tags CMake-SourceFile2-b-mp1-pre and CMake-SourceFile2-b-mp1-post on the trunk. The changes re-implement cmSourceFile and the use of it to allow instances to be created much earlier. The use of cmSourceFileLocation allows locating a source file referenced by a user to be much simpler and more robust. The two SetName methods are no longer needed so some duplicate code has been removed. The strange "SourceName" stuff is gone. Code that created cmSourceFile instances on the stack and then sent them to cmMakefile::AddSource has been simplified and converted to getting cmSourceFile instances from cmMakefile. The CPluginAPI has preserved the old API through a compatibility interface. Source lists are gone. Targets now get real instances of cmSourceFile right away instead of storing a list of strings until the final pass. TraceVSDependencies has been re-written to avoid the use of SourceName. It is now called TraceDependencies since it is not just for VS. It is now implemented with a helper object which makes the code simpler.
Diffstat (limited to 'Source/cmCPluginAPI.cxx')
-rw-r--r--Source/cmCPluginAPI.cxx327
1 files changed, 282 insertions, 45 deletions
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index dff6035..d6ef01b 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -488,104 +488,341 @@ int CCONV cmGetTotalArgumentSize(int argc, char **argv)
return result;
}
-void CCONV *cmGetSource(void *arg, const char *name)
+// Source file proxy object to support the old cmSourceFile/cmMakefile
+// API for source files.
+struct cmCPluginAPISourceFile
+{
+ cmCPluginAPISourceFile(): RealSourceFile(0) {}
+ cmSourceFile* RealSourceFile;
+ std::string SourceName;
+ std::string SourceExtension;
+ std::string FullPath;
+ std::vector<std::string> Depends;
+ cmPropertyMap Properties;
+};
+
+// Keep a map from real cmSourceFile instances stored in a makefile to
+// the CPluginAPI proxy source file.
+class cmCPluginAPISourceFileMap:
+ public std::map<cmSourceFile*, cmCPluginAPISourceFile*>
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return (void *)mf->GetSource(name);
-}
+public:
+ typedef std::map<cmSourceFile*, cmCPluginAPISourceFile*> derived;
+ typedef derived::iterator iterator;
+ typedef derived::value_type value_type;
+ ~cmCPluginAPISourceFileMap()
+ {
+ for(iterator i=this->begin(); i != this->end(); ++i)
+ {
+ delete i->second;
+ }
+ }
+};
+static cmCPluginAPISourceFileMap cmCPluginAPISourceFiles;
-void * CCONV cmAddSource(void *arg, void *arg2)
+void * CCONV cmCreateSourceFile()
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg2);
- return (void *)mf->AddSource(*sf);
+ return (void*)new cmCPluginAPISourceFile;
}
+void * CCONV cmCreateNewSourceFile(void *arg)
+{
+ (void)arg; // no longer needed
+ return (void*)new cmCPluginAPISourceFile;
+}
-void * CCONV cmCreateSourceFile()
+void CCONV cmDestroySourceFile(void *arg)
{
- return (void *)(new cmSourceFile);
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ // Only delete if it was created by cmCreateSourceFile or
+ // cmCreateNewSourceFile and is therefore not in the map.
+ if(!sf->RealSourceFile)
+ {
+ delete sf;
+ }
}
-void * CCONV cmCreateNewSourceFile(void *arg)
+void CCONV *cmGetSource(void *arg, const char *name)
{
cmMakefile *mf = static_cast<cmMakefile *>(arg);
- cmSourceFile *sf = new cmSourceFile;
- sf->SetMakefile(mf);
- return (void *)sf;
+ if(cmSourceFile* rsf = mf->GetSource(name))
+ {
+ // Lookup the proxy source file object for this source.
+ cmCPluginAPISourceFileMap::iterator i = cmCPluginAPISourceFiles.find(rsf);
+ if(i == cmCPluginAPISourceFiles.end())
+ {
+ // Create a proxy source file object for this source.
+ cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile;
+ sf->RealSourceFile = rsf;
+ sf->FullPath = rsf->GetFullPath();
+ sf->SourceName =
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->FullPath.c_str());
+ sf->SourceExtension =
+ cmSystemTools::GetFilenameLastExtension(sf->FullPath.c_str());
+
+ // Store the proxy in the map so it can be re-used and deleted later.
+ cmCPluginAPISourceFileMap::value_type entry(rsf, sf);
+ i = cmCPluginAPISourceFiles.insert(entry).first;
+ }
+ return (void *)i->second;
+ }
+ else
+ {
+ return 0;
+ }
}
-void CCONV cmDestroySourceFile(void *arg)
+void * CCONV cmAddSource(void *arg, void *arg2)
{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- delete sf;
+ cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmCPluginAPISourceFile* osf = static_cast<cmCPluginAPISourceFile*>(arg2);
+ if(osf->FullPath.empty())
+ {
+ return 0;
+ }
+
+ // Create the real cmSourceFile instance and copy over saved information.
+ cmSourceFile* rsf = mf->GetOrCreateSource(osf->FullPath.c_str());
+ rsf->GetProperties() = osf->Properties;
+ for(std::vector<std::string>::iterator i = osf->Depends.begin();
+ i != osf->Depends.end(); ++i)
+ {
+ rsf->AddDepend(i->c_str());
+ }
+
+ // Create the proxy for the real source file.
+ cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile;
+ sf->RealSourceFile = rsf;
+ sf->FullPath = osf->FullPath;
+ sf->SourceName = osf->SourceName;
+ sf->SourceExtension = osf->SourceExtension;
+
+ // Store the proxy in the map so it can be re-used and deleted later.
+ cmCPluginAPISourceFiles[rsf] = sf;
+ return (void *)sf;
}
const char * CCONV cmSourceFileGetSourceName(void *arg)
{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- return sf->GetSourceName().c_str();
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ return sf->SourceName.c_str();
}
const char * CCONV cmSourceFileGetFullPath(void *arg)
{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- return sf->GetFullPath().c_str();
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ return sf->FullPath.c_str();
}
const char * CCONV cmSourceFileGetProperty(void *arg,const char *prop)
{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- return sf->GetProperty(prop);
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ if(cmSourceFile* rsf = sf->RealSourceFile)
+ {
+ return rsf->GetProperty(prop);
+ }
+ else
+ {
+ if(!strcmp(prop,"LOCATION"))
+ {
+ return sf->FullPath.c_str();
+ }
+ bool chain = false;
+ // Ignore chain because old code will not expect it and it is a
+ // pain to implement here anyway.
+ return sf->Properties.GetPropertyValue(prop, cmProperty::SOURCE_FILE,
+ chain);
+ }
}
int CCONV cmSourceFileGetPropertyAsBool(void *arg,const char *prop)
{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- return (sf->GetPropertyAsBool(prop) ? 1: 0);
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ if(cmSourceFile* rsf = sf->RealSourceFile)
+ {
+ return rsf->GetPropertyAsBool(prop) ? 1:0;
+ }
+ else
+ {
+ return cmSystemTools::IsOn(cmSourceFileGetProperty(arg, prop))? 1:0;
+ }
}
void CCONV cmSourceFileSetProperty(void *arg,const char *prop,
- const char *val)
+ const char *value)
{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- sf->SetProperty(prop,val);
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ if(cmSourceFile* rsf = sf->RealSourceFile)
+ {
+ rsf->SetProperty(prop, value);
+ }
+ else if(prop)
+ {
+ if(!value) { value = "NOTFOUND"; }
+ sf->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE);
+ }
}
void CCONV cmSourceFileAddDepend(void *arg, const char *depend)
{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- sf->AddDepend(depend);
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ if(cmSourceFile* rsf = sf->RealSourceFile)
+ {
+ rsf->AddDepend(depend);
+ }
+ else
+ {
+ sf->Depends.push_back(depend);
+ }
}
void CCONV cmSourceFileSetName(void *arg, const char* name, const char* dir,
- int numSourceExtensions,
- const char **sourceExtensions,
- int numHeaderExtensions,
- const char **headerExtensions)
-{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- std::vector<std::string> srcs;
- std::vector<std::string> hdrs;
+ int numSourceExtensions,
+ const char **sourceExtensions,
+ int numHeaderExtensions,
+ const char **headerExtensions)
+{
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ if(sf->RealSourceFile)
+ {
+ // SetName is allowed only on temporary source files created by
+ // the command for building and passing to AddSource.
+ return;
+ }
+ std::vector<std::string> sourceExts;
+ std::vector<std::string> headerExts;
int i;
for (i = 0; i < numSourceExtensions; ++i)
{
- srcs.push_back(sourceExtensions[i]);
+ sourceExts.push_back(sourceExtensions[i]);
}
for (i = 0; i < numHeaderExtensions; ++i)
{
- hdrs.push_back(headerExtensions[i]);
+ headerExts.push_back(headerExtensions[i]);
}
- sf->SetName(name,dir, srcs, hdrs);
+
+ // Implement the old SetName method code here.
+ sf->Properties.SetProperty("HEADER_FILE_ONLY", "1",
+ cmProperty::SOURCE_FILE);
+
+ // Save the original name given.
+ sf->SourceName = name;
+
+ // Convert the name to a full path in case the given name is a
+ // relative path.
+ std::string pathname = cmSystemTools::CollapseFullPath(name, dir);
+
+ // First try and see whether the listed file can be found
+ // as is without extensions added on.
+ std::string hname = pathname;
+ if(cmSystemTools::FileExists(hname.c_str()))
+ {
+ sf->SourceName = cmSystemTools::GetFilenamePath(name);
+ if ( sf->SourceName.size() > 0 )
+ {
+ sf->SourceName += "/";
+ }
+ sf->SourceName += cmSystemTools::GetFilenameWithoutLastExtension(name);
+ std::string::size_type pos = hname.rfind('.');
+ if(pos != std::string::npos)
+ {
+ sf->SourceExtension = hname.substr(pos+1, hname.size()-pos);
+ if ( cmSystemTools::FileIsFullPath(name) )
+ {
+ std::string::size_type pos2 = hname.rfind('/');
+ if(pos2 != std::string::npos)
+ {
+ sf->SourceName = hname.substr(pos2+1, pos - pos2-1);
+ }
+ }
+ }
+
+ // See if the file is a header file
+ if(std::find( headerExts.begin(), headerExts.end(),
+ sf->SourceExtension ) == headerExts.end())
+ {
+ sf->Properties.SetProperty("HEADER_FILE_ONLY", "0",
+ cmProperty::SOURCE_FILE);
+ }
+ sf->FullPath = hname;
+ return;
+ }
+
+ // Next, try the various source extensions
+ for( std::vector<std::string>::const_iterator ext = sourceExts.begin();
+ ext != sourceExts.end(); ++ext )
+ {
+ hname = pathname;
+ hname += ".";
+ hname += *ext;
+ if(cmSystemTools::FileExists(hname.c_str()))
+ {
+ sf->SourceExtension = *ext;
+ sf->Properties.SetProperty("HEADER_FILE_ONLY", "0",
+ cmProperty::SOURCE_FILE);
+ sf->FullPath = hname;
+ return;
+ }
+ }
+
+ // Finally, try the various header extensions
+ for( std::vector<std::string>::const_iterator ext = headerExts.begin();
+ ext != headerExts.end(); ++ext )
+ {
+ hname = pathname;
+ hname += ".";
+ hname += *ext;
+ if(cmSystemTools::FileExists(hname.c_str()))
+ {
+ sf->SourceExtension = *ext;
+ sf->FullPath = hname;
+ return;
+ }
+ }
+
+ cmOStringStream e;
+ e << "Cannot find source file \"" << pathname << "\"";
+ e << "\n\nTried extensions";
+ for( std::vector<std::string>::const_iterator ext = sourceExts.begin();
+ ext != sourceExts.end(); ++ext )
+ {
+ e << " ." << *ext;
+ }
+ for( std::vector<std::string>::const_iterator ext = headerExts.begin();
+ ext != headerExts.end(); ++ext )
+ {
+ e << " ." << *ext;
+ }
+ cmSystemTools::Error(e.str().c_str());
+ return;
}
void CCONV cmSourceFileSetName2(void *arg, const char* name, const char* dir,
- const char *ext, int headerFileOnly)
+ const char *ext, int headerFileOnly)
{
- cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
- sf->SetName(name,dir,ext,(headerFileOnly ? true : false));
-}
+ cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
+ if(sf->RealSourceFile)
+ {
+ // SetName is allowed only on temporary source files created by
+ // the command for building and passing to AddSource.
+ return;
+ }
+ // Implement the old SetName method code here.
+ sf->Properties.SetProperty("HEADER_FILE_ONLY",
+ headerFileOnly? "1" : "0",
+ cmProperty::SOURCE_FILE);
+ sf->SourceName = name;
+ std::string fname = sf->SourceName;
+ if(ext && strlen(ext))
+ {
+ fname += ".";
+ fname += ext;
+ }
+ sf->FullPath = cmSystemTools::CollapseFullPath(fname.c_str(), dir);
+ cmSystemTools::ConvertToUnixSlashes(sf->FullPath);
+ sf->SourceExtension = ext;
+}
char * CCONV cmGetFilenameWithoutExtension(const char *name)
{