diff options
Diffstat (limited to 'Source/cmCPluginAPI.cxx')
-rw-r--r-- | Source/cmCPluginAPI.cxx | 327 |
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) { |