diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index b7969f9b7..800084298 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -148,6 +148,8 @@ SET(SRCS cmPropertyMap.h cmSourceFile.cxx cmSourceFile.h + cmSourceFileLocation.cxx + cmSourceFileLocation.h cmSourceGroup.cxx cmSourceGroup.h cmSystemTools.cxx diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 2cc57892e..705aad7cf 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -56,9 +56,9 @@ bool cmAuxSourceDirectoryCommand::InitialPass if( dotpos != std::string::npos ) { std::string ext = file.substr(dotpos+1); - file = file.substr(0, dotpos); + std::string base = file.substr(0, dotpos); // Process only source files - if( file.size() != 0 + if( base.size() != 0 && std::find( this->Makefile->GetSourceExtensions().begin(), this->Makefile->GetSourceExtensions().end(), ext ) != this->Makefile->GetSourceExtensions().end() ) @@ -68,21 +68,14 @@ bool cmAuxSourceDirectoryCommand::InitialPass fullname += file; // add the file as a class file so // depends can be done - cmSourceFile cmfile; - cmfile.SetMakefile(this->Makefile); - cmfile.SetName(fullname.c_str(), - this->Makefile->GetCurrentDirectory(), - this->Makefile->GetSourceExtensions(), - this->Makefile->GetHeaderExtensions()); - cmfile.SetProperty("ABSTRACT","0"); - this->Makefile->AddSource(cmfile); - if (sourceListValue.size() > 0) + cmSourceFile* sf = + this->Makefile->GetOrCreateSource(fullname.c_str()); + sf->SetProperty("ABSTRACT","0"); + if(!sourceListValue.empty()) { sourceListValue += ";"; } - sourceListValue += cmfile.GetSourceName(); - sourceListValue += "."; - sourceListValue += cmfile.GetSourceExtension(); + sourceListValue += fullname; } } } diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index dff603570..d6ef01b0b 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -488,104 +488,341 @@ int CCONV cmGetTotalArgumentSize(int argc, char **argv) return result; } +// 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 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 +{ +public: + typedef std::map 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 cmCreateSourceFile() +{ + return (void*)new cmCPluginAPISourceFile; +} + +void * CCONV cmCreateNewSourceFile(void *arg) +{ + (void)arg; // no longer needed + return (void*)new cmCPluginAPISourceFile; +} + +void CCONV cmDestroySourceFile(void *arg) +{ + cmCPluginAPISourceFile* sf = static_cast(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 *cmGetSource(void *arg, const char *name) { cmMakefile *mf = static_cast(arg); - return (void *)mf->GetSource(name); + 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 cmAddSource(void *arg, void *arg2) { cmMakefile *mf = static_cast(arg); - cmSourceFile *sf = static_cast(arg2); - return (void *)mf->AddSource(*sf); -} + cmCPluginAPISourceFile* osf = static_cast(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::iterator i = osf->Depends.begin(); + i != osf->Depends.end(); ++i) + { + rsf->AddDepend(i->c_str()); + } -void * CCONV cmCreateSourceFile() -{ - return (void *)(new cmSourceFile); -} + // 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; -void * CCONV cmCreateNewSourceFile(void *arg) -{ - cmMakefile *mf = static_cast(arg); - cmSourceFile *sf = new cmSourceFile; - sf->SetMakefile(mf); + // Store the proxy in the map so it can be re-used and deleted later. + cmCPluginAPISourceFiles[rsf] = sf; return (void *)sf; } -void CCONV cmDestroySourceFile(void *arg) -{ - cmSourceFile *sf = static_cast(arg); - delete sf; -} - const char * CCONV cmSourceFileGetSourceName(void *arg) { - cmSourceFile *sf = static_cast(arg); - return sf->GetSourceName().c_str(); + cmCPluginAPISourceFile* sf = static_cast(arg); + return sf->SourceName.c_str(); } const char * CCONV cmSourceFileGetFullPath(void *arg) { - cmSourceFile *sf = static_cast(arg); - return sf->GetFullPath().c_str(); + cmCPluginAPISourceFile* sf = static_cast(arg); + return sf->FullPath.c_str(); } const char * CCONV cmSourceFileGetProperty(void *arg,const char *prop) { - cmSourceFile *sf = static_cast(arg); - return sf->GetProperty(prop); + cmCPluginAPISourceFile* sf = static_cast(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(arg); - return (sf->GetPropertyAsBool(prop) ? 1: 0); + cmCPluginAPISourceFile* sf = static_cast(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(arg); - sf->SetProperty(prop,val); + cmCPluginAPISourceFile* sf = static_cast(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(arg); - sf->AddDepend(depend); + cmCPluginAPISourceFile* sf = static_cast(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) + int numSourceExtensions, + const char **sourceExtensions, + int numHeaderExtensions, + const char **headerExtensions) { - cmSourceFile *sf = static_cast(arg); - std::vector srcs; - std::vector hdrs; + cmCPluginAPISourceFile* sf = static_cast(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 sourceExts; + std::vector 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::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::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::const_iterator ext = sourceExts.begin(); + ext != sourceExts.end(); ++ext ) + { + e << " ." << *ext; + } + for( std::vector::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(arg); - sf->SetName(name,dir,ext,(headerFileOnly ? true : false)); -} + cmCPluginAPISourceFile* sf = static_cast(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) { diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index ebd7f719c..4d542c9d9 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -170,29 +170,17 @@ bool cmCreateTestSourceList::InitialPass(std::vector const& args) res = false; } - // Create the source list - cmSourceFile cfile; - cfile.SetMakefile(this->Makefile); + // Construct the source list. std::string sourceListValue; - - cfile.SetProperty("ABSTRACT","0"); - cfile.SetName(cmSystemTools::GetFilenameWithoutExtension(args[1]).c_str(), - this->Makefile->GetCurrentOutputDirectory(), - cmSystemTools::GetFilenameExtension(args[1]).c_str()+1, - false); - this->Makefile->AddSource(cfile); + { + cmSourceFile* sf = this->Makefile->GetOrCreateSource(driver.c_str()); + sf->SetProperty("ABSTRACT","0"); sourceListValue = args[1]; - + } for(i = testsBegin; i != tests.end(); ++i) { - cmSourceFile icfile; - icfile.SetMakefile(this->Makefile); - icfile.SetProperty("ABSTRACT","0"); - icfile.SetName(i->c_str(), - this->Makefile->GetCurrentDirectory(), - this->Makefile->GetSourceExtensions(), - this->Makefile->GetHeaderExtensions()); - this->Makefile->AddSource(icfile); + cmSourceFile* sf = this->Makefile->GetOrCreateSource(i->c_str()); + sf->SetProperty("ABSTRACT","0"); sourceListValue += ";"; sourceListValue += *i; } diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 80abd674f..43c4494b2 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -53,20 +53,17 @@ bool cmFLTKWrapUICommand::InitialPass(std::vector const& args) // to generate .cxx and .h files if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) { - cmSourceFile header_file; - header_file.SetMakefile(this->Makefile); - std::string srcName = cmSystemTools::GetFilenameWithoutExtension(*i); - const bool headerFileOnly = true; - header_file.SetName(srcName.c_str(), - outputDirectory.c_str(), "h",headerFileOnly); + std::string outName = outputDirectory; + outName += "/"; + outName += cmSystemTools::GetFilenameWithoutExtension(*i); + std::string hname = outName; + hname += ".h"; std::string origname = cdir + "/" + *i; - std::string hname = header_file.GetFullPath(); // add starting depends std::vector depends; depends.push_back(origname); depends.push_back(fluid_exe); - std::string cxxres = outputDirectory.c_str(); - cxxres += "/" + srcName; + std::string cxxres = outName; cxxres += ".cxx"; cmCustomCommandLine commandLine; @@ -123,12 +120,12 @@ void cmFLTKWrapUICommand::FinalPass() // people should add the srcs to the target themselves, but the old command // didn't support that, so check and see if they added the files in and if // they didn;t then print a warning and add then anyhow - std::vector const& srcs = - this->Makefile->GetTargets()[this->Target].GetSourceLists(); + std::vector const& srcs = + this->Makefile->GetTargets()[this->Target].GetSourceFiles(); bool found = false; for (unsigned int i = 0; i < srcs.size(); ++i) { - if (srcs[i] == + if (srcs[i]->GetFullPath() == this->GeneratedSourcesClasses[0]->GetFullPath()) { found = true; diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index 4d444bcd5..2b01f58c6 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -38,6 +38,11 @@ bool cmGetSourceFilePropertyCommand::InitialPass( } if(sf) { + if(args[2] == "LOCATION") + { + // Make sure the location is known. + sf->GetFullPath(); + } const char *prop = sf->GetProperty(args[2].c_str()); if (prop) { diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 0c8bf4047..189f5e49a 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -19,6 +19,7 @@ #include "cmExternalMakefileProjectGenerator.h" #include "cmake.h" #include "cmMakefile.h" +#include "cmSourceFile.h" #include "cmVersion.h" #include // required for atof @@ -483,39 +484,32 @@ cmGlobalGenerator::EnableLanguage(std::vectorconst& languages, } } -const char* cmGlobalGenerator -::GetLanguageOutputExtensionForLanguage(const char* lang) +//---------------------------------------------------------------------------- +const char* +cmGlobalGenerator::GetLanguageOutputExtension(cmSourceFile const& source) { - if(!lang) + if(const char* lang = source.GetLanguage()) { - return ""; + if(this->LanguageToOutputExtension.count(lang) > 0) + { + return this->LanguageToOutputExtension[lang].c_str(); + } } - if(this->LanguageToOutputExtension.count(lang) > 0) - { - return this->LanguageToOutputExtension[lang].c_str(); - } - return ""; -} - -const char* cmGlobalGenerator -::GetLanguageOutputExtensionFromExtension(const char* ext) -{ - if(!ext) - { - return ""; - } - const char* lang = this->GetLanguageFromExtension(ext); - if(!lang || *lang == 0) + else { // if no language is found then check to see if it is already an // ouput extension for some language. In that case it should be ignored // and in this map, so it will not be compiled but will just be used. - if(this->OutputExtensions.count(ext)) + std::string const& ext = source.GetExtension(); + if(!ext.empty()) { - return ext; + if(this->OutputExtensions.count(ext)) + { + return ext.c_str(); + } } } - return this->GetLanguageOutputExtensionForLanguage(lang); + return ""; } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index aea31fba0..8ed5e3ae3 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -143,10 +143,8 @@ public: bool IgnoreFile(const char* ext); ///! What is the preference for linkers and this language (None or Prefered) const char* GetLinkerPreference(const char* lang); - ///! What is the output extension for a given language. - const char* GetLanguageOutputExtensionForLanguage(const char* lang); - ///! What is the output extension for a given source file extension. - const char* GetLanguageOutputExtensionFromExtension(const char* lang); + ///! What is the object file extension for a given source file? + const char* GetLanguageOutputExtension(cmSourceFile const&); ///! What is the configurations directory variable called? virtual const char* GetCMakeCFGInitDirectory() { return "."; } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 746d645a6..6c6299f7e 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -440,9 +440,7 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, cmXCodeObject* children = group->GetObject("children"); children->AddObject(fileRef); cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); - std::string fname = sf->GetSourceName(); - fname += "."; - fname += sf->GetSourceExtension(); + std::string fname = sf->GetFullPath(); std::string comment = fname; comment += " in "; std::string gname = group->GetObject("name")->GetString(); @@ -458,7 +456,7 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, const char* lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); std::string sourcecode = "sourcecode"; - std::string ext = sf->GetSourceExtension(); + std::string ext = sf->GetExtension(); ext = cmSystemTools::LowerCase(ext); if(ext == "o") { @@ -2046,12 +2044,12 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, // MACOSX_BUNDLE file if(cmtarget.GetPropertyAsBool("MACOSX_BUNDLE")) { - cmSourceFile file; - file.SetName("Info", - this->CurrentMakefile->GetCurrentOutputDirectory(), - "plist", false); - cmtarget.AddSourceFile - (this->CurrentMakefile->AddSource(file)); + std::string plistFile = + this->CurrentMakefile->GetCurrentOutputDirectory(); + plistFile += "/Info.plist"; + cmSourceFile* sf = + this->CurrentMakefile->GetOrCreateSource(plistFile.c_str(), true); + cmtarget.AddSourceFile(sf); } std::vector classes = cmtarget.GetSourceFiles(); // add framework copy headers diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 8f2bcca9b..222e60896 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -147,12 +147,12 @@ void cmLocalGenerator::TraceDependencies() // so don't build a projectfile for it if (strncmp(t->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0) { - std::string projectFilename; + const char* projectFilename = 0; if (this->IsMakefileGenerator == false) // only use of this variable { - projectFilename=t->second.GetName(); + projectFilename = t->second.GetName(); } - t->second.TraceVSDependencies(projectFilename, this->Makefile); + t->second.TraceDependencies(projectFilename); } } } @@ -625,18 +625,21 @@ void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target) std::vector const& classes = target.GetSourceFiles(); for(std::vector::const_iterator i = classes.begin(); i != classes.end(); ++i) - { - if(!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY") && - !(*i)->GetCustomCommand()) + { + cmSourceFile* sf = *i; + if(!sf->GetCustomCommand() && + !sf->GetPropertyAsBool("HEADER_FILE_ONLY") && + !sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { - std::string outExt = - this->GlobalGenerator->GetLanguageOutputExtensionFromExtension( - (*i)->GetSourceExtension().c_str()); - if(outExt.size() && !(*i)->GetPropertyAsBool("EXTERNAL_OBJECT") ) + std::string::size_type dir_len = 0; + dir_len += strlen(this->Makefile->GetCurrentOutputDirectory()); + dir_len += 1; + std::string obj = this->GetObjectFileNameWithoutTarget(*sf, dir_len); + if(!obj.empty()) { std::string ofname = this->Makefile->GetCurrentOutputDirectory(); ofname += "/"; - ofname += (*i)->GetSourceName() + outExt; + ofname += obj; objVector.push_back(ofname); this->AddCustomCommandToCreateObject(ofname.c_str(), llang, *(*i), target); @@ -1358,11 +1361,12 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, for(std::vector::const_iterator i = sources.begin(); i != sources.end(); ++i) { - if((*i)->GetSourceExtension() == "def") + cmSourceFile* sf = *i; + if(sf->GetExtension() == "def") { linkFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); - linkFlags += this->Convert((*i)->GetFullPath().c_str(), + linkFlags += this->Convert(sf->GetFullPath().c_str(), START_OUTPUT, SHELL); linkFlags += " "; } @@ -2672,23 +2676,18 @@ cmLocalGenerator // Replace the original source file extension with the object file // extension. - std::string::size_type dot_pos = objectName.rfind("."); - if(dot_pos != std::string::npos) + if(!source.GetPropertyAsBool("KEEP_EXTENSION")) { - objectName = objectName.substr(0, dot_pos); - } - if ( source.GetPropertyAsBool("KEEP_EXTENSION") ) - { - if ( !source.GetSourceExtension().empty() ) + // Remove the original extension. + std::string::size_type dot_pos = objectName.rfind("."); + if(dot_pos != std::string::npos) { - objectName += "." + source.GetSourceExtension(); + objectName = objectName.substr(0, dot_pos); } - } - else - { + + // Store the new extension. objectName += - this->GlobalGenerator->GetLanguageOutputExtensionFromExtension( - source.GetSourceExtension().c_str()); + this->GlobalGenerator->GetLanguageOutputExtension(source); } // Convert to a safe name. @@ -2700,15 +2699,7 @@ const char* cmLocalGenerator ::GetSourceFileLanguage(const cmSourceFile& source) { - // Check for an explicitly assigned language. - if(const char* lang = source.GetProperty("LANGUAGE")) - { - return lang; - } - - // Infer the language from the source file extension. - return (this->GlobalGenerator - ->GetLanguageFromExtension(source.GetSourceExtension().c_str())); + return source.GetLanguage(); } //---------------------------------------------------------------------------- @@ -2784,8 +2775,3 @@ cmLocalGenerator::GetTargetObjectFileDirectories(cmTarget* , cmSystemTools::Error("GetTargetObjectFileDirectories" " called on cmLocalGenerator"); } - -std::string cmLocalGenerator::GetSourceObjectName(cmSourceFile& sf) -{ - return sf.GetSourceName(); -} diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index cc5a39d60..90779a57f 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -225,8 +225,6 @@ public: GetTargetObjectFileDirectories(cmTarget* target, std::vector& dirs); - // return the source name for the object file - virtual std::string GetSourceObjectName(cmSourceFile& ); /** * Convert the given remote path to a relative path with respect to diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index b7698827b..313bac6aa 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -323,7 +323,7 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout, sourceGroup.AssignSource(*i); // while we are at it, if it is a .rule file then for visual studio 6 we // must generate it - if ((*i)->GetSourceExtension() == "rule") + if ((*i)->GetExtension() == "rule") { if(!cmSystemTools::FileExists(source.c_str())) { diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 9a0ee591e..71fbf1eed 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -883,10 +883,11 @@ void cmLocalVisualStudio7Generator for(std::vector::const_iterator i = classes.begin(); i != classes.end(); i++) { - if(cmSystemTools::UpperCase((*i)->GetSourceExtension()) == "DEF") + cmSourceFile* sf = *i; + if(cmSystemTools::UpperCase(sf->GetExtension()) == "DEF") { fout << "\t\t\t\tModuleDefinitionFile=\"" - << this->ConvertToXMLOutputPath((*i)->GetFullPath().c_str()) + << this->ConvertToXMLOutputPath(sf->GetFullPath().c_str()) << "\"\n"; return; } @@ -969,7 +970,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, { // Add the file to the list of sources. std::string source = (*i)->GetFullPath(); - if(cmSystemTools::UpperCase((*i)->GetSourceExtension()) == "DEF") + if(cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") { this->ModuleDefinitionFile = (*i)->GetFullPath(); } @@ -1070,8 +1071,9 @@ void cmLocalVisualStudio7Generator compileFlags += " "; compileFlags += cflags; } - const char* lang = this->GlobalGenerator->GetLanguageFromExtension - ((*sf)->GetSourceExtension().c_str()); + const char* lang = + this->GlobalGenerator->GetLanguageFromExtension + ((*sf)->GetExtension().c_str()); const char* sourceLang = this->GetSourceFileLanguage(*(*sf)); const char* linkLanguage = target.GetLinkerLanguage (this->GetGlobalGenerator()); @@ -1138,7 +1140,7 @@ void cmLocalVisualStudio7Generator || objectName.size() || excludedFromBuild) { const char* aCompilerTool = "VCCLCompilerTool"; - std::string ext = (*sf)->GetSourceExtension(); + std::string ext = (*sf)->GetExtension(); ext = cmSystemTools::LowerCase(ext); if(ext == "idl") { @@ -1902,18 +1904,3 @@ GetTargetObjectFileDirectories(cmTarget* target, std::cerr << dir << "\n"; dirs.push_back(dir); } - - - // return the source name for the object file -std::string -cmLocalVisualStudio7Generator::GetSourceObjectName(cmSourceFile& sf ) -{ - std::string ret = sf.GetSourceName(); - std::string::size_type pos = ret.find("/"); - if(pos == ret.npos) - { - return ret; - } - return ret.substr(pos+1); -} - diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 2c3c365c6..d6761084c 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -62,8 +62,6 @@ public: void GetTargetObjectFileDirectories(cmTarget* target, std::vector& dirs); - // return the source name for the object file - virtual std::string GetSourceObjectName(cmSourceFile& ); void SetExtraFlagTable(cmVS7FlagTable const* table) { this->ExtraFlagTable = table; } diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 1d494c2ab..b2bacca69 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -73,7 +73,7 @@ void cmLocalVisualStudioGenerator::ComputeObjectNameRequirements std::string objectName = cmSystemTools::LowerCase( cmSystemTools::GetFilenameWithoutLastExtension( - sf->GetFullPath().c_str())); + sf->GetFullPath())); objectName += ".obj"; objectNameCounts[objectName] += 1; } @@ -95,7 +95,7 @@ void cmLocalVisualStudioGenerator::ComputeObjectNameRequirements std::string objectName = cmSystemTools::LowerCase( cmSystemTools::GetFilenameWithoutLastExtension( - sf->GetFullPath().c_str())); + sf->GetFullPath())); objectName += ".obj"; if(objectNameCounts[objectName] > 1) { diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index c55a0edbb..27a91900b 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -24,16 +24,3 @@ GetTargetObjectFileDirectories(cmTarget* target, g->GetTargetObjectFileDirectories(target, dirs); } - - // return the source name for the object file -std::string cmLocalXCodeGenerator::GetSourceObjectName(cmSourceFile& sf ) -{ - std::string ret = sf.GetSourceName(); - std::string::size_type pos = ret.find("/"); - if(pos == ret.npos) - { - return ret; - } - return ret.substr(pos+1); -} - diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h index 8ab946739..b265d6b8b 100644 --- a/Source/cmLocalXCodeGenerator.h +++ b/Source/cmLocalXCodeGenerator.h @@ -35,8 +35,6 @@ public: void GetTargetObjectFileDirectories(cmTarget* target, std::vector& dirs); - // return the source name for the object file - virtual std::string GetSourceObjectName(cmSourceFile& ); private: }; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index d0aced8c0..13422b1e0 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -18,6 +18,7 @@ #include "cmVersion.h" #include "cmCommand.h" #include "cmSourceFile.h" +#include "cmSourceFileLocation.h" #include "cmSystemTools.h" #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" @@ -557,7 +558,6 @@ void cmMakefile::ConfigureFinalPass() for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end(); l++) { - l->second.GenerateSourceFilesFromSourceLists(*this); l->second.AnalyzeLibDependencies(*this); } } @@ -772,7 +772,7 @@ cmMakefile::AddCustomCommandOldStyle(const char* target, { if (this->Targets.find(target) != this->Targets.end()) { - this->Targets[target].AddSourceListEntry(source); + this->Targets[target].AddSource(source); } else { @@ -854,10 +854,10 @@ void cmMakefile::AddUtilityCommand(const char* utilityName, commandLines, comment, workingDirectory, no_replace, escapeOldStyle); - target->AddSourceListEntry(force.c_str()); + cmSourceFile* sf = target->AddSource(force.c_str()); // The output is not actually created so mark it symbolic. - if(cmSourceFile* sf = this->GetSource(force.c_str())) + if(sf) { sf->SetProperty("SYMBOLIC", "1"); } @@ -1364,7 +1364,7 @@ void cmMakefile::AddLibrary(const char* lname, int shared, { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } - target->SetSourceList(srcs); + target->AddSources(srcs); this->AddGlobalLinkInformation(lname, *target); } @@ -1377,7 +1377,7 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName, { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } - target->SetSourceList(srcs); + target->AddSources(srcs); this->AddGlobalLinkInformation(exeName, *target); return target; } @@ -2116,219 +2116,43 @@ cmData* cmMakefile::LookupData(const char* name) const } } -cmSourceFile* cmMakefile::GetSource(const char* sourceName) const +//---------------------------------------------------------------------------- +cmSourceFile* cmMakefile::GetSource(const char* sourceName) { - // if the source is provided with a full path use it, otherwise - // by default it is in the current source dir - std::string path; - if (cmSystemTools::FileIsFullPath(sourceName)) + cmSourceFileLocation sfl(this, sourceName); + for(std::vector::const_iterator + sfi = this->SourceFiles.begin(); + sfi != this->SourceFiles.end(); ++sfi) { - path = cmSystemTools::GetFilenamePath(sourceName); - } - else - { - path = this->GetCurrentDirectory(); - // even though it is not a full path, it may still be relative - std::string subpath = cmSystemTools::GetFilenamePath(sourceName); - if (!subpath.empty()) + cmSourceFile* sf = *sfi; + if(sf->Matches(sfl)) { - path += "/"; - path += cmSystemTools::GetFilenamePath(sourceName); + return sf; } } - path = cmSystemTools::CollapseFullPath(path.c_str()); - - std::string sname = - cmSystemTools::GetFilenameWithoutLastExtension(sourceName); - - // compute the extension - std::string ext - = cmSystemTools::GetFilenameLastExtension(sourceName); - if ( ext.length() && ext[0] == '.' ) - { - ext = ext.substr(1); - } - - for(std::vector::const_iterator i = - this->SourceFiles.begin(); - i != this->SourceFiles.end(); ++i) - { - if ((*i)->GetSourceNameWithoutLastExtension() == sname && - cmSystemTools::GetFilenamePath((*i)->GetFullPath()) == path && - (ext.size() == 0 || (ext == (*i)->GetSourceExtension()))) - { - return *i; - } - } - - // geeze, if it wasn't found maybe it is listed under the output dir - if (!cmSystemTools::GetFilenamePath(sourceName).empty()) - { - return 0; - } - - path = this->GetCurrentOutputDirectory(); - for(std::vector::const_iterator i = - this->SourceFiles.begin(); - i != this->SourceFiles.end(); ++i) - { - if ((*i)->GetSourceName() == sname && - cmSystemTools::GetFilenamePath((*i)->GetFullPath()) == path && - (ext.size() == 0 || (ext == (*i)->GetSourceExtension()))) - { - return *i; - } - } - return 0; } +//---------------------------------------------------------------------------- cmSourceFile* cmMakefile::GetOrCreateSource(const char* sourceName, bool generated) { - // make it a full path first - std::string src = sourceName; - bool relative = !cmSystemTools::FileIsFullPath(sourceName); - std::string srcTreeFile = this->GetCurrentDirectory(); - srcTreeFile += "/"; - srcTreeFile += sourceName; - - if(relative) + if(cmSourceFile* esf = this->GetSource(sourceName)) { - src = srcTreeFile; - } - - // check to see if it exists - cmSourceFile* ret = this->GetSource(src.c_str()); - if (ret) - { - return ret; - } - - // OK a source file object doesn't exist for the source - // maybe we made a bad call on assuming it was in the src tree - std::string buildTreeFile = this->GetCurrentOutputDirectory(); - buildTreeFile += "/"; - buildTreeFile += sourceName; - - if (relative) - { - src = buildTreeFile; - ret = this->GetSource(src.c_str()); - if (ret) - { - return ret; - } - // if it has not been marked generated check to see if it exists in the - // src tree - if(!generated) - { - // see if the file is in the source tree, otherwise assume it - // is in the binary tree - if (cmSystemTools::FileExists(srcTreeFile.c_str()) && - !cmSystemTools::FileIsDirectory(srcTreeFile.c_str())) - { - src = srcTreeFile; - } - else - { - if ( cmSystemTools::GetFilenameLastExtension - (srcTreeFile.c_str()).size() == 0) - { - if (cmSystemTools::DoesFileExistWithExtensions( - srcTreeFile.c_str(), this->GetSourceExtensions())) - { - src = srcTreeFile; - } - else if (cmSystemTools::DoesFileExistWithExtensions( - srcTreeFile.c_str(), this->GetHeaderExtensions())) - { - src = srcTreeFile; - } - } - } - } - } - - // a cmSourceFile instance does not exist yet so we must create one - // go back to looking in the source directory for it - - // we must create one - cmSourceFile file; - file.SetMakefile(this); - std::string path = cmSystemTools::GetFilenamePath(src); - if(generated) - { - std::string ext = cmSystemTools::GetFilenameLastExtension(src); - std::string name_no_ext = cmSystemTools::GetFilenameName(src.c_str()); - name_no_ext = name_no_ext.substr(0, name_no_ext.length()-ext.length()); - if ( ext.length() && ext[0] == '.' ) - { - ext = ext.substr(1); - } - bool headerFile = - !(std::find( this->HeaderFileExtensions.begin(), - this->HeaderFileExtensions.end(), ext ) == - this->HeaderFileExtensions.end()); - file.SetName(name_no_ext.c_str(), path.c_str(), ext.c_str(), headerFile); + return esf; } else { - std::string relPath = cmSystemTools::GetFilenamePath(sourceName); - if (relative && relPath.size()) + cmSourceFile* sf = new cmSourceFile(this, sourceName); + if(generated) { - // we need to keep the relative part of the filename - std::string fullPathLessRel = path; - std::string::size_type pos = fullPathLessRel.rfind(relPath); - if (pos == std::string::npos) - { - cmSystemTools::Error( - "CMake failed to properly look up relative cmSourceFile: ", - sourceName); - } - fullPathLessRel.erase(pos-1); - file.SetName(sourceName, fullPathLessRel.c_str(), - this->GetSourceExtensions(), - this->GetHeaderExtensions()); - } - else - { - file.SetName(cmSystemTools::GetFilenameName(src.c_str()).c_str(), - path.c_str(), - this->GetSourceExtensions(), - this->GetHeaderExtensions()); + sf->SetProperty("GENERATED", "1"); } + this->SourceFiles.push_back(sf); + return sf; } - // add the source file to the makefile - this->AddSource(file); - src = file.GetFullPath(); - ret = this->GetSource(src.c_str()); - if (!ret) - { - cmSystemTools::Error( - "CMake failed to properly look up cmSourceFile: ", sourceName); - } - else - { - ret->SetMakefile(this); - } - return ret; } -cmSourceFile* cmMakefile::AddSource(cmSourceFile const&sf) -{ - // check to see if it exists - cmSourceFile* ret = this->GetSource(sf.GetFullPath().c_str()); - if(ret) - { - return ret; - } - ret = new cmSourceFile(sf); - this->SourceFiles.push_back(ret); - return ret; -} - - void cmMakefile::EnableLanguage(std::vector const & lang) { this->AddDefinition("CMAKE_CFG_INTDIR", diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 502b886a7..753ab81a4 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -463,19 +463,16 @@ public: /** Get a cmSourceFile pointer for a given source name, if the name is * not found, then a null pointer is returned. */ - cmSourceFile* GetSource(const char* sourceName) const; - - ///! Add a new cmSourceFile to the list of sources for this makefile. - cmSourceFile* AddSource(cmSourceFile const&); + cmSourceFile* GetSource(const char* sourceName); /** Get a cmSourceFile pointer for a given source name, if the name is * not found, then create the source file and return it. generated * indicates if it is a generated file, this is used in determining * how to create the source file instance e.g. name */ - cmSourceFile* GetOrCreateSource(const char* sourceName, + cmSourceFile* GetOrCreateSource(const char* sourceName, bool generated = false); - + /** * Obtain a list of auxiliary source directories. */ diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index edef3678d..9ec7f98ba 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -147,13 +147,14 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) for(std::vector::const_iterator i = sources.begin(); i != sources.end(); ++i) { - if((*i)->GetSourceExtension() == "def") + cmSourceFile* sf = *i; + if(sf->GetExtension() == "def") { extraFlags += " "; extraFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); extraFlags += - this->Convert((*i)->GetFullPath().c_str(), + this->Convert(sf->GetFullPath().c_str(), cmLocalGenerator::START_OUTPUT, cmLocalGenerator::SHELL); } @@ -290,13 +291,7 @@ void cmMakefileLibraryTargetGenerator::CopyFrameworkPublicHeaders( cmCustomCommandLine line; cmSourceFile* sf = this->Makefile->GetOrCreateSource(i->c_str()); std::string dest = outpath + "Headers/"; - dest += sf->GetSourceName(); - std::string ext = sf->GetSourceExtension(); - if(ext.size()) - { - dest += "."; - dest += sf->GetSourceExtension(); - } + dest += cmSystemTools::GetFilenameName(sf->GetFullPath()); line.push_back("$(CMAKE_COMMAND)"); line.push_back("-E"); line.push_back("copy_if_different"); @@ -347,13 +342,7 @@ void cmMakefileLibraryTargetGenerator::CopyFrameworkResources( continue; } std::string dest = outpath + "Resources/"; - dest += sf->GetSourceName(); - std::string ext = sf->GetSourceExtension(); - if(ext.size()) - { - dest += "."; - dest += sf->GetSourceExtension(); - } + dest += cmSystemTools::GetFilenameName(sf->GetFullPath()); line.push_back("$(CMAKE_COMMAND)"); line.push_back("-E"); line.push_back("copy_if_different"); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index abef8a828..9476319a4 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -152,7 +152,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY")) { if(!this->GlobalGenerator->IgnoreFile - ((*source)->GetSourceExtension().c_str())) + ((*source)->GetExtension().c_str())) { // Generate this object file's rule file. this->WriteObjectRuleFiles(*(*source)); @@ -307,8 +307,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source) { cmOStringStream err; err << "Warning: Source file \"" - << source.GetSourceName().c_str() << "." - << source.GetSourceExtension().c_str() + << source.GetFullPath() << "\" is listed multiple times for target \"" << this->Target->GetName() << "\"."; diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index 1a922498a..e15fea2df 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -223,13 +223,6 @@ ListDependencies(cmDependInformation const *info, void cmOutputRequiredFilesCommand::FinalPass() { - - cmTargets &tgts = this->Makefile->GetTargets(); - for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) - { - l->second.GenerateSourceFilesFromSourceLists(*this->Makefile); - } - // compute the list of files cmLBDepend md; md.SetMakefile(this->Makefile); diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx index 19033f8a0..03c40608a 100644 --- a/Source/cmQTWrapCPPCommand.cxx +++ b/Source/cmQTWrapCPPCommand.cxx @@ -24,120 +24,96 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector const& argsIn) this->SetError("called with incorrect number of arguments"); return false; } + + // This command supports source list inputs for compatibility. std::vector args; this->Makefile->ExpandSourceListArguments(argsIn, args, 2); - // what is the current source dir - std::string cdir = this->Makefile->GetCurrentDirectory(); + // Get the moc executable to run in the custom command. + const char* moc_exe = + this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE"); - // keep the library name - this->LibraryName = args[0]; - this->SourceList = args[1]; - - std::string sourceListValue; + // Get the variable holding the list of sources. + std::string const& sourceList = args[1]; + std::string sourceListValue = + this->Makefile->GetSafeDefinition(sourceList.c_str()); - // was the list already populated - const char *def = this->Makefile->GetDefinition(this->SourceList.c_str()); - if (def) - { - sourceListValue = def; - } - - // get the list of classes for this library + // Create a rule for all sources listed. for(std::vector::iterator j = (args.begin() + 2); j != args.end(); ++j) - { + { cmSourceFile *curr = this->Makefile->GetSource(j->c_str()); - // if we should wrap the class - if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) + if(!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE"))) { - cmSourceFile file; + // Compute the name of the file to generate. + std::string srcName = + cmSystemTools::GetFilenameWithoutLastExtension(*j); + std::string newName = this->Makefile->GetCurrentOutputDirectory(); + newName += "/moc_"; + newName += srcName; + newName += ".cxx"; + cmSourceFile* sf = + this->Makefile->GetOrCreateSource(newName.c_str(), true); if (curr) { - file.SetProperty("ABSTRACT",curr->GetProperty("ABSTRACT")); + sf->SetProperty("ABSTRACT", curr->GetProperty("ABSTRACT")); } - std::string srcName = - cmSystemTools::GetFilenameWithoutLastExtension(*j); - std::string newName = "moc_" + srcName; - file.SetName(newName.c_str(), - this->Makefile->GetCurrentOutputDirectory(), - "cxx",false); + + // Compute the name of the header from which to generate the file. std::string hname; - if ( (*j)[0] == '/' || (*j)[1] == ':' ) + if(cmSystemTools::FileIsFullPath(j->c_str())) { hname = *j; } else { - if ( curr && curr->GetPropertyAsBool("GENERATED") ) + if(curr && curr->GetPropertyAsBool("GENERATED")) { - hname = std::string(this->Makefile->GetCurrentOutputDirectory()) - + "/" + *j; + hname = this->Makefile->GetCurrentOutputDirectory(); } else { - hname = cdir + "/" + *j; + hname = this->Makefile->GetCurrentDirectory(); } + hname += "/"; + hname += *j; } - this->WrapHeaders.push_back(hname); - // add starting depends - file.AddDepend(hname.c_str()); - this->WrapClasses.push_back(file); - if (sourceListValue.size() > 0) + + // Append the generated source file to the list. + if(!sourceListValue.empty()) { sourceListValue += ";"; } - sourceListValue += newName + ".cxx"; + sourceListValue += newName; + + // Create the custom command to generate the file. + cmCustomCommandLine commandLine; + commandLine.push_back(moc_exe); + commandLine.push_back("-o"); + commandLine.push_back(newName); + commandLine.push_back(hname); + + cmCustomCommandLines commandLines; + commandLines.push_back(commandLine); + + std::vector depends; + depends.push_back(moc_exe); + depends.push_back(hname); + + const char* no_main_dependency = 0; + const char* no_working_dir = 0; + this->Makefile->AddCustomCommandToOutput(newName.c_str(), + depends, + no_main_dependency, + commandLines, + "QT Wrapped File", + no_working_dir); } } - - this->Makefile->AddDefinition(this->SourceList.c_str(), + + // Store the final list of source files. + this->Makefile->AddDefinition(sourceList.c_str(), sourceListValue.c_str()); return true; } - -void cmQTWrapCPPCommand::FinalPass() -{ - - // first we add the rules for all the .h to Moc files - size_t lastClass = this->WrapClasses.size(); - std::vector depends; - const char* moc_exe = - this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE"); - - // wrap all the .h files - depends.push_back(moc_exe); - - for(size_t classNum = 0; classNum < lastClass; classNum++) - { - // Add output to build list - this->Makefile->AddSource(this->WrapClasses[classNum]); - - // set up moc command - std::string res = this->Makefile->GetCurrentOutputDirectory(); - res += "/"; - res += this->WrapClasses[classNum].GetSourceName() + ".cxx"; - - cmCustomCommandLine commandLine; - commandLine.push_back(moc_exe); - commandLine.push_back("-o"); - commandLine.push_back(res); - commandLine.push_back(this->WrapHeaders[classNum]); - - cmCustomCommandLines commandLines; - commandLines.push_back(commandLine); - - std::vector realdepends = depends; - realdepends.push_back(this->WrapHeaders[classNum]); - - const char* no_main_dependency = 0; - const char* no_working_dir = 0; - this->Makefile->AddCustomCommandToOutput(res.c_str(), - realdepends, - no_main_dependency, - commandLines, - "QT Wrapped File", - no_working_dir); - } -} diff --git a/Source/cmQTWrapCPPCommand.h b/Source/cmQTWrapCPPCommand.h index ad5740d8d..79d729b1d 100644 --- a/Source/cmQTWrapCPPCommand.h +++ b/Source/cmQTWrapCPPCommand.h @@ -45,14 +45,6 @@ public: * the CMakeLists.txt file. */ virtual bool InitialPass(std::vector const& args); - - /** - * This is called at the end after all the information - * specified by the command is accumulated. Most commands do - * not implement this method. At this point, reading and - * writing to the cache can be done. - */ - virtual void FinalPass(); /** * The name of the command as specified in CMakeList.txt. @@ -79,18 +71,6 @@ public: "The moc files will be added to the library using the DestName " "source list."; } - -private: - /** - * List of produced files. - */ - std::vector WrapClasses; - /** - * List of header files that pprovide the source for WrapClasses. - */ - std::vector WrapHeaders; - std::string LibraryName; - std::string SourceList; }; diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx index 2f7982d0e..ff86ed937 100644 --- a/Source/cmQTWrapUICommand.cxx +++ b/Source/cmQTWrapUICommand.cxx @@ -24,191 +24,147 @@ bool cmQTWrapUICommand::InitialPass(std::vector const& argsIn) this->SetError("called with incorrect number of arguments"); return false; } + + // This command supports source list inputs for compatibility. std::vector args; this->Makefile->ExpandSourceListArguments(argsIn, args, 3); - // what is the current source dir - std::string cdir = this->Makefile->GetCurrentDirectory(); - - // keep the library name - this->LibraryName = args[0]; - this->HeaderList = args[1]; - this->SourceList = args[2]; - std::string sourceListValue; - std::string headerListValue; - const char *def = this->Makefile->GetDefinition(this->SourceList.c_str()); - if (def) - { - sourceListValue = def; - } - - // get the list of classes for this library - for(std::vector::iterator j = (args.begin() + 3); - j != args.end(); ++j) - { - cmSourceFile *curr = this->Makefile->GetSource(j->c_str()); - - // if we should wrap the class - if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) - { - cmSourceFile header_file; - cmSourceFile source_file; - cmSourceFile moc_file; - std::string srcName = cmSystemTools::GetFilenameWithoutExtension(*j); - header_file.SetName(srcName.c_str(), - this->Makefile->GetCurrentOutputDirectory(), - "h",false); - source_file.SetName(srcName.c_str(), - this->Makefile->GetCurrentOutputDirectory(), - "cxx",false); - std::string moc_source_name("moc_"); - moc_source_name = moc_source_name + srcName; - moc_file.SetName(moc_source_name.c_str(), - this->Makefile->GetCurrentOutputDirectory(), - "cxx",false); - std::string origname; - if ( (*j)[0] == '/' || (*j)[1] == ':' ) - { - origname = *j; - } - else - { - if ( curr && curr->GetPropertyAsBool("GENERATED") ) - { - origname = std::string(this->Makefile->GetCurrentOutputDirectory()) - + "/" + *j; - } - else - { - origname = cdir + "/" + *j; - } - } - std::string hname = header_file.GetFullPath(); - this->WrapUserInterface.push_back(origname); - // add starting depends - moc_file.AddDepend(hname.c_str()); - source_file.AddDepend(hname.c_str()); - source_file.AddDepend(origname.c_str()); - header_file.AddDepend(origname.c_str()); - this->WrapHeadersClasses.push_back(header_file); - this->WrapSourcesClasses.push_back(source_file); - this->WrapMocClasses.push_back(moc_file); - this->Makefile->AddSource(header_file); - this->Makefile->AddSource(source_file); - this->Makefile->AddSource(moc_file); - - // create the list of headers - if (headerListValue.size() > 0) - { - headerListValue += ";"; - } - headerListValue += header_file.GetFullPath(); - - // create the list of sources - if (sourceListValue.size() > 0) - { - sourceListValue += ";"; - } - sourceListValue += source_file.GetFullPath(); - sourceListValue += ";"; - sourceListValue += moc_file.GetFullPath(); - } - } - - this->Makefile->AddDefinition(this->SourceList.c_str(), - sourceListValue.c_str()); - this->Makefile->AddDefinition(this->HeaderList.c_str(), - headerListValue.c_str()); - return true; -} - -void cmQTWrapUICommand::FinalPass() -{ - - // first we add the rules for all the .ui to .h and .cxx files - size_t lastHeadersClass = this->WrapHeadersClasses.size(); - std::vector depends; + // Get the uic and moc executables to run in the custom commands. const char* uic_exe = this->Makefile->GetRequiredDefinition("QT_UIC_EXECUTABLE"); const char* moc_exe = this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE"); - // wrap all the .h files - depends.push_back(uic_exe); + // Get the variable holding the list of sources. + std::string const& headerList = args[1]; + std::string const& sourceList = args[2]; + std::string headerListValue = + this->Makefile->GetSafeDefinition(headerList.c_str()); + std::string sourceListValue = + this->Makefile->GetSafeDefinition(sourceList.c_str()); - for(size_t classNum = 0; classNum < lastHeadersClass; classNum++) + // Create rules for all sources listed. + for(std::vector::iterator j = (args.begin() + 3); + j != args.end(); ++j) { - // set up .ui to .h and .cxx command - std::string hres = this->Makefile->GetCurrentOutputDirectory(); - hres += "/"; - hres += this->WrapHeadersClasses[classNum].GetSourceName() + "." + - this->WrapHeadersClasses[classNum].GetSourceExtension(); + cmSourceFile *curr = this->Makefile->GetSource(j->c_str()); + // if we should wrap the class + if(!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE"))) + { + // Compute the name of the files to generate. + std::string srcName = + cmSystemTools::GetFilenameWithoutLastExtension(*j); + std::string hName = this->Makefile->GetCurrentOutputDirectory(); + hName += "/"; + hName += srcName; + hName += ".h"; + std::string cxxName = this->Makefile->GetCurrentOutputDirectory(); + cxxName += "/"; + cxxName += srcName; + cxxName += ".cxx"; + std::string mocName = this->Makefile->GetCurrentOutputDirectory(); + mocName += "/moc_"; + mocName += srcName; + mocName += ".cxx"; - std::string cxxres = this->Makefile->GetCurrentOutputDirectory(); - cxxres += "/"; - cxxres += this->WrapSourcesClasses[classNum].GetSourceName() + "." + - this->WrapSourcesClasses[classNum].GetSourceExtension(); + // Compute the name of the ui file from which to generate others. + std::string uiName; + if(cmSystemTools::FileIsFullPath(j->c_str())) + { + uiName = *j; + } + else + { + if(curr && curr->GetPropertyAsBool("GENERATED")) + { + uiName = this->Makefile->GetCurrentOutputDirectory(); + } + else + { + uiName = this->Makefile->GetCurrentDirectory(); + } + uiName += "/"; + uiName += *j; + } - std::string mocres = this->Makefile->GetCurrentOutputDirectory(); - mocres += "/"; - mocres += this->WrapMocClasses[classNum].GetSourceName() + "." + - this->WrapMocClasses[classNum].GetSourceExtension(); + // create the list of headers + if(!headerListValue.empty()) + { + headerListValue += ";"; + } + headerListValue += hName; - cmCustomCommandLine hCommand; - hCommand.push_back(uic_exe); - hCommand.push_back("-o"); - hCommand.push_back(hres); - hCommand.push_back(this->WrapUserInterface[classNum]); - cmCustomCommandLines hCommandLines; - hCommandLines.push_back(hCommand); + // create the list of sources + if(!sourceListValue.empty()) + { + sourceListValue += ";"; + } + sourceListValue += cxxName; + sourceListValue += ";"; + sourceListValue += mocName; - cmCustomCommandLine cxxCommand; - cxxCommand.push_back(uic_exe); - cxxCommand.push_back("-impl"); - cxxCommand.push_back(hres); - cxxCommand.push_back("-o"); - cxxCommand.push_back(cxxres); - cxxCommand.push_back(this->WrapUserInterface[classNum]); - cmCustomCommandLines cxxCommandLines; - cxxCommandLines.push_back(cxxCommand); + // set up .ui to .h and .cxx command + cmCustomCommandLine hCommand; + hCommand.push_back(uic_exe); + hCommand.push_back("-o"); + hCommand.push_back(hName); + hCommand.push_back(uiName); + cmCustomCommandLines hCommandLines; + hCommandLines.push_back(hCommand); - cmCustomCommandLine mocCommand; - mocCommand.push_back(moc_exe); - mocCommand.push_back("-o"); - mocCommand.push_back(mocres); - mocCommand.push_back(hres); - cmCustomCommandLines mocCommandLines; - mocCommandLines.push_back(mocCommand); + cmCustomCommandLine cxxCommand; + cxxCommand.push_back(uic_exe); + cxxCommand.push_back("-impl"); + cxxCommand.push_back(hName); + cxxCommand.push_back("-o"); + cxxCommand.push_back(cxxName); + cxxCommand.push_back(uiName); + cmCustomCommandLines cxxCommandLines; + cxxCommandLines.push_back(cxxCommand); - depends.clear(); - depends.push_back(this->WrapUserInterface[classNum]); - const char* no_main_dependency = 0; - const char* no_comment = 0; - const char* no_working_dir = 0; - this->Makefile->AddCustomCommandToOutput(hres.c_str(), - depends, - no_main_dependency, - hCommandLines, - no_comment, - no_working_dir); + cmCustomCommandLine mocCommand; + mocCommand.push_back(moc_exe); + mocCommand.push_back("-o"); + mocCommand.push_back(mocName); + mocCommand.push_back(hName); + cmCustomCommandLines mocCommandLines; + mocCommandLines.push_back(mocCommand); - depends.push_back(hres); + std::vector depends; + depends.push_back(uiName); + const char* no_main_dependency = 0; + const char* no_comment = 0; + const char* no_working_dir = 0; + this->Makefile->AddCustomCommandToOutput(hName.c_str(), + depends, + no_main_dependency, + hCommandLines, + no_comment, + no_working_dir); - this->Makefile->AddCustomCommandToOutput(cxxres.c_str(), - depends, - no_main_dependency, - cxxCommandLines, - no_comment, - no_working_dir); + depends.push_back(hName); + this->Makefile->AddCustomCommandToOutput(cxxName.c_str(), + depends, + no_main_dependency, + cxxCommandLines, + no_comment, + no_working_dir); - depends.clear(); - depends.push_back(hres); - - this->Makefile->AddCustomCommandToOutput(mocres.c_str(), - depends, - no_main_dependency, - mocCommandLines, - no_comment, - no_working_dir); + depends.clear(); + depends.push_back(hName); + this->Makefile->AddCustomCommandToOutput(mocName.c_str(), + depends, + no_main_dependency, + mocCommandLines, + no_comment, + no_working_dir); + } } + + // Store the final list of source files and headers. + this->Makefile->AddDefinition(sourceList.c_str(), + sourceListValue.c_str()); + this->Makefile->AddDefinition(headerList.c_str(), + headerListValue.c_str()); + return true; } diff --git a/Source/cmQTWrapUICommand.h b/Source/cmQTWrapUICommand.h index 2b4b866b9..e9a93542a 100644 --- a/Source/cmQTWrapUICommand.h +++ b/Source/cmQTWrapUICommand.h @@ -43,14 +43,6 @@ public: * the CMakeLists.txt file. */ virtual bool InitialPass(std::vector const& args); - - /** - * This is called at the end after all the information - * specified by the command is accumulated. Most commands do - * not implement this method. At this point, reading and - * writing to the cache can be done. - */ - virtual void FinalPass(); /** * The name of the command as specified in CMakeList.txt. @@ -80,21 +72,6 @@ public: "The .cxx files will be added to the library using the SourcesDestName" "source list."; } - -private: - /** - * List of produced files. - */ - std::vector WrapSourcesClasses; - std::vector WrapHeadersClasses; - std::vector WrapMocClasses; - /** - * List of header files that pprovide the source for WrapClasses. - */ - std::vector WrapUserInterface; - std::string LibraryName; - std::string HeaderList; - std::string SourceList; }; diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 4fc74e879..c9d0c48e9 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -15,161 +15,235 @@ =========================================================================*/ #include "cmSourceFile.h" -#include "cmSystemTools.h" -#include "cmake.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmSystemTools.h" +#include "cmake.h" -// Set the name of the class and the full path to the file. -// The class must be found in dir and end in name.cxx, name.txx, -// name.c or it will be considered a header file only class -// and not included in the build process -bool cmSourceFile::SetName(const char* name, const char* dir, - const std::vector& sourceExts, - const std::vector& headerExts, - const char* target) +//---------------------------------------------------------------------------- +cmSourceFile::cmSourceFile(cmMakefile* mf, const char* name): + Location(mf, name) { + this->CustomCommand = 0; + this->Properties.SetCMakeInstance(mf->GetCMakeInstance()); + this->FindFullPathFailed = false; +} - this->SetProperty("HEADER_FILE_ONLY","1"); - this->SourceNameWithoutLastExtension = ""; +//---------------------------------------------------------------------------- +cmSourceFile::~cmSourceFile() +{ + this->SetCustomCommand(0); +} - // Save the original name given. - this->SourceName = name; +//---------------------------------------------------------------------------- +std::string const& cmSourceFile::GetExtension() const +{ + return this->Extension; +} - // 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())) +//---------------------------------------------------------------------------- +const char* cmSourceFile::GetLanguage() +{ + // Compute the final location of the file if necessary. + if(this->FullPath.empty()) { - this->SourceName = cmSystemTools::GetFilenamePath(name); - if ( this->SourceName.size() > 0 ) - { - this->SourceName += "/"; - } - this->SourceName += cmSystemTools::GetFilenameWithoutLastExtension(name); - std::string::size_type pos = hname.rfind('.'); - if(pos != std::string::npos) - { - this->SourceExtension = hname.substr(pos+1, hname.size()-pos); - if ( cmSystemTools::FileIsFullPath(name) ) - { - std::string::size_type pos2 = hname.rfind('/'); - if(pos2 != std::string::npos) - { - this->SourceName = hname.substr(pos2+1, pos - pos2-1); - } - } - } + this->GetFullPath(); + } - // See if the file is a header file - if(std::find( headerExts.begin(), headerExts.end(), - this->SourceExtension ) == headerExts.end()) - { - this->SetProperty("HEADER_FILE_ONLY","0"); - } - this->FullPath = hname; + // Now try to determine the language. + return static_cast(this)->GetLanguage(); +} - // Mark this as an external object file if it has the proper - // extension. THIS CODE IS DUPLICATED IN THE OTHER SetName METHOD. - // THESE METHODS SHOULD BE MERGED. - if ( this->SourceExtension == "obj" || this->SourceExtension == "o" || - this->SourceExtension == "lo" ) +//---------------------------------------------------------------------------- +const char* cmSourceFile::GetLanguage() const +{ + // If the language was set explicitly by the user then use it. + if(const char* lang = this->GetProperty("LANGUAGE")) + { + return lang; + } + + // If the language was determined from the source file extension use it. + if(!this->Language.empty()) + { + return this->Language.c_str(); + } + + // The language is not known. + return 0; +} + +//---------------------------------------------------------------------------- +std::string const& cmSourceFile::GetFullPath() +{ + if(this->FullPath.empty()) + { + if(this->FindFullPath()) { - this->SetProperty("EXTERNAL_OBJECT", "1"); + this->CheckExtension(); } + } + return this->FullPath; +} + +//---------------------------------------------------------------------------- +std::string const& cmSourceFile::GetFullPath() const +{ + return this->FullPath; +} + +//---------------------------------------------------------------------------- +bool cmSourceFile::FindFullPath() +{ + // If thie method has already failed once do not try again. + if(this->FindFullPathFailed) + { + return false; + } + + // If the file is generated compute the location without checking on + // disk. + if(this->GetPropertyAsBool("GENERATED")) + { + // The file is either already a full path or is relative to the + // build directory for the target. + this->Location.DirectoryUseBinary(); + this->FullPath = this->Location.GetDirectory(); + this->FullPath += "/"; + this->FullPath += this->Location.GetName(); return true; } - - // Next, try the various source extensions - for( std::vector::const_iterator ext = sourceExts.begin(); - ext != sourceExts.end(); ++ext ) + + // The file is not generated. It must exist on disk. + cmMakefile* mf = this->Location.GetMakefile(); + const char* tryDirs[3] = {0, 0, 0}; + if(this->Location.DirectoryIsAmbiguous()) { - hname = pathname; - hname += "."; - hname += *ext; - if(cmSystemTools::FileExists(hname.c_str())) + tryDirs[0] = mf->GetCurrentDirectory(); + tryDirs[1] = mf->GetCurrentOutputDirectory(); + } + else + { + tryDirs[0] = ""; + } + const std::vector& srcExts = mf->GetSourceExtensions(); + const std::vector& hdrExts = mf->GetHeaderExtensions(); + for(const char* const* di = tryDirs; *di; ++di) + { + std::string tryPath = this->Location.GetDirectory(); + if(!tryPath.empty()) + { + tryPath += "/"; + } + tryPath += this->Location.GetName(); + tryPath = cmSystemTools::CollapseFullPath(tryPath.c_str(), *di); + if(this->TryFullPath(tryPath.c_str(), 0)) { - this->SourceExtension = *ext; - this->SetProperty("HEADER_FILE_ONLY","0"); - this->FullPath = hname; return true; } - } - - // Finally, try the various header extensions - for( std::vector::const_iterator ext = headerExts.begin(); - ext != headerExts.end(); ++ext ) - { - hname = pathname; - hname += "."; - hname += *ext; - if(cmSystemTools::FileExists(hname.c_str())) + for(std::vector::const_iterator ei = srcExts.begin(); + ei != srcExts.end(); ++ei) { - this->SourceExtension = *ext; - this->FullPath = hname; - return true; + if(this->TryFullPath(tryPath.c_str(), ei->c_str())) + { + return true; + } + } + for(std::vector::const_iterator ei = hdrExts.begin(); + ei != hdrExts.end(); ++ei) + { + if(this->TryFullPath(tryPath.c_str(), ei->c_str())) + { + return true; + } } } cmOStringStream e; - e << "Cannot find source file \"" << pathname << "\""; - if(target) - { - e << " for target \"" << target << "\""; - } + e << "Cannot find source file \"" << this->Location.GetName() << "\""; e << "\n\nTried extensions"; - for( std::vector::const_iterator ext = sourceExts.begin(); - ext != sourceExts.end(); ++ext ) + for(std::vector::const_iterator ext = srcExts.begin(); + ext != srcExts.end(); ++ext) { e << " ." << *ext; } - for( std::vector::const_iterator ext = headerExts.begin(); - ext != headerExts.end(); ++ext ) + for(std::vector::const_iterator ext = hdrExts.begin(); + ext != hdrExts.end(); ++ext) { e << " ." << *ext; } cmSystemTools::Error(e.str().c_str()); + this->FindFullPathFailed = true; return false; } -void cmSourceFile::SetName(const char* name, const char* dir, const char *ext, - bool hfo) +//---------------------------------------------------------------------------- +bool cmSourceFile::TryFullPath(const char* tp, const char* ext) { - this->SetProperty("HEADER_FILE_ONLY",(hfo ? "1" : "0")); - this->SourceNameWithoutLastExtension = ""; - this->SourceName = name; - std::string fname = this->SourceName; - if(ext && strlen(ext)) + std::string tryPath = tp; + if(ext && *ext) { - fname += "."; - fname += ext; + tryPath += "."; + tryPath += ext; } - this->FullPath = cmSystemTools::CollapseFullPath(fname.c_str(), dir); - cmSystemTools::ConvertToUnixSlashes(this->FullPath); - this->SourceExtension = ext; + if(cmSystemTools::FileExists(tryPath.c_str())) + { + this->FullPath = tryPath; + return true; + } + return false; +} - // Mark this as an external object file if it has the proper - // extension. THIS CODE IS DUPLICATED IN THE OTHER SetName METHOD. - // THESE METHODS SHOULD BE MERGED. - if ( this->SourceExtension == "obj" || this->SourceExtension == "o" || - this->SourceExtension == "lo" ) +//---------------------------------------------------------------------------- +void cmSourceFile::CheckExtension() +{ + // Compute the extension. + std::string realExt = + cmSystemTools::GetFilenameLastExtension(this->FullPath); + if(!realExt.empty()) + { + // Store the extension without the leading '.'. + this->Extension = realExt.substr(1); + } + + // Look for object files. + if(this->Extension == "obj" || + this->Extension == "o" || + this->Extension == "lo") { this->SetProperty("EXTERNAL_OBJECT", "1"); } - return; + + // Look for header files. + cmMakefile* mf = this->Location.GetMakefile(); + const std::vector& hdrExts = mf->GetHeaderExtensions(); + if(std::find(hdrExts.begin(), hdrExts.end(), this->Extension) == + hdrExts.end()) + { + this->SetProperty("HEADER_FILE_ONLY", "0"); + } + else + { + this->SetProperty("HEADER_FILE_ONLY", "1"); + } + + // Try to identify the source file language from the extension. + cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator(); + if(const char* l = gg->GetLanguageFromExtension(this->Extension.c_str())) + { + this->Language = l; + } } -void cmSourceFile::Print() const +//---------------------------------------------------------------------------- +bool cmSourceFile::Matches(cmSourceFileLocation const& loc) { - std::cerr << "this->FullPath: " << this->FullPath << "\n"; - std::cerr << "this->SourceName: " << this->SourceName << std::endl; - std::cerr << "this->SourceExtension: " << this->SourceExtension << "\n"; + return this->Location.Matches(loc); } +//---------------------------------------------------------------------------- void cmSourceFile::SetProperty(const char* prop, const char* value) { if (!prop) @@ -184,13 +258,20 @@ void cmSourceFile::SetProperty(const char* prop, const char* value) this->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE); } -const char *cmSourceFile::GetProperty(const char* prop) const +//---------------------------------------------------------------------------- +const char* cmSourceFile::GetProperty(const char* prop) const { - // watch for special "computed" properties that are dependent on other - // properties or variables, always recompute them - if (!strcmp(prop,"LOCATION")) + // Check for computed properties. + if(strcmp(prop, "LOCATION") == 0) { - return this->FullPath.c_str(); + if(this->FullPath.empty()) + { + return 0; + } + else + { + return this->FullPath.c_str(); + } } bool chain = false; @@ -198,53 +279,40 @@ const char *cmSourceFile::GetProperty(const char* prop) const this->Properties.GetPropertyValue(prop, cmProperty::SOURCE_FILE, chain); if (chain) { - return this->Makefile->GetProperty(prop,cmProperty::SOURCE_FILE); + cmMakefile* mf = this->Location.GetMakefile(); + return mf->GetProperty(prop,cmProperty::SOURCE_FILE); } return retVal; } +//---------------------------------------------------------------------------- bool cmSourceFile::GetPropertyAsBool(const char* prop) const { return cmSystemTools::IsOn(this->GetProperty(prop)); } -void cmSourceFile::SetCustomCommand(cmCustomCommand* cc) +//---------------------------------------------------------------------------- +cmCustomCommand* cmSourceFile::GetCustomCommand() { - if(this->CustomCommand) - { - delete this->CustomCommand; - } - this->CustomCommand = cc; -} - -const std::string& cmSourceFile::GetSourceNameWithoutLastExtension() -{ - if ( this->SourceNameWithoutLastExtension.empty() ) - { - this->SourceNameWithoutLastExtension = - cmSystemTools::GetFilenameWithoutLastExtension(this->FullPath); - } - return this->SourceNameWithoutLastExtension; -} - -cmSourceFile::cmSourceFile() -{ - this->Makefile = 0; - this->CustomCommand = 0; + return this->CustomCommand; } //---------------------------------------------------------------------------- -void cmSourceFile::SetMakefile(cmMakefile* mf) +cmCustomCommand const* cmSourceFile::GetCustomCommand() const { - // Set our makefile. - this->Makefile = mf; - - // set the cmake instance of the properties - this->Properties.SetCMakeInstance(mf->GetCMakeInstance()); + return this->CustomCommand; } -// define properties +//---------------------------------------------------------------------------- +void cmSourceFile::SetCustomCommand(cmCustomCommand* cc) +{ + cmCustomCommand* old = this->CustomCommand; + this->CustomCommand = cc; + delete old; +} + +//---------------------------------------------------------------------------- void cmSourceFile::DefineProperties(cmake *cm) { // define properties diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 5a3da7081..47f31ebd4 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -17,11 +17,11 @@ #ifndef cmSourceFile_h #define cmSourceFile_h +#include "cmSourceFileLocation.h" #include "cmCustomCommand.h" #include "cmPropertyMap.h" class cmake; -class cmMakefile; /** \class cmSourceFile * \brief Represent a class loaded from a makefile. @@ -33,67 +33,41 @@ class cmSourceFile { public: /** - * Construct instance as a concrete class with both a - * .h and .cxx file. + * Construct with the makefile storing the source and the initial + * name referencing it. */ - cmSourceFile(); - ~cmSourceFile() - { - this->SetCustomCommand(0); - } - - /** - * Set the name of the file, given the directory the file should be - * in. The various extensions provided are tried on the name - * (e.g., cxx, cpp) in the directory to find the actual file. - */ - bool SetName(const char* name, const char* dir, - const std::vector& sourceExts, - const std::vector& headerExts, - const char* target = 0); + cmSourceFile(cmMakefile* mf, const char* name); + + ~cmSourceFile(); /** * Get the list of the custom commands for this source file */ - const cmCustomCommand *GetCustomCommand() const - {return this->CustomCommand;} - cmCustomCommand *GetCustomCommand() {return this->CustomCommand;} + cmCustomCommand* GetCustomCommand(); + cmCustomCommand const* GetCustomCommand() const; void SetCustomCommand(cmCustomCommand *cc); - - /** - * Set the name of the file, given the directory the file should be in. IN - * this version the extension is provided in the call. This is useful for - * generated files that do not exist prior to the build. - */ - void SetName(const char* name, const char* dir, const char *ext, - bool headerFileOnly); - - /** - * Print the structure to std::cout. - */ - void Print() const; ///! Set/Get a property of this source file void SetProperty(const char *prop, const char *value); const char *GetProperty(const char *prop) const; bool GetPropertyAsBool(const char *prop) const; - + /** * The full path to the file. */ - const std::string &GetFullPath() const {return this->FullPath;} + std::string const& GetFullPath(); + std::string const& GetFullPath() const; /** - * The file name associated with stripped off directory and extension. - * (In most cases this is the name of the class.) + * Get the file extension of this source file. */ - const std::string &GetSourceName() const {return this->SourceName;} + std::string const& GetExtension() const; /** - * The file extension associated with source file + * Get the language of the compiler to use for this source file. */ - const std::string &GetSourceExtension() const { - return this->SourceExtension;} + const char* GetLanguage(); + const char* GetLanguage() const; /** * Return the vector that holds the list of dependencies @@ -101,33 +75,32 @@ public: const std::vector &GetDepends() const {return this->Depends;} void AddDepend(const char* d) { this->Depends.push_back(d); } - /** - * Get the source name without last extension - */ - const std::string& GetSourceNameWithoutLastExtension(); - // Get the properties cmPropertyMap &GetProperties() { return this->Properties; }; // Define the properties static void DefineProperties(cmake *cm); - ///! Set the cmMakefile that owns this target - void SetMakefile(cmMakefile *mf); - cmMakefile *GetMakefile() { return this->Makefile;}; + /** + * Check whether the given source file location could refer to this + * source. + */ + bool Matches(cmSourceFileLocation const&); private: + cmSourceFileLocation Location; cmPropertyMap Properties; - cmCustomCommand *CustomCommand; + cmCustomCommand* CustomCommand; + std::string Extension; + std::string Language; std::string FullPath; - std::string SourceName; - std::string SourceExtension; - std::vector Depends; - std::string SourceNameWithoutLastExtension; + bool FindFullPathFailed; - // The cmMakefile instance that owns this source file. This should - // always be set. - cmMakefile* Makefile; + bool FindFullPath(); + bool TryFullPath(const char* tryPath, const char* ext); + void CheckExtension(); + + std::vector Depends; }; #endif diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx new file mode 100644 index 000000000..159f22f6b --- /dev/null +++ b/Source/cmSourceFileLocation.cxx @@ -0,0 +1,212 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "cmSourceFileLocation.h" + +#include "cmMakefile.h" +#include "cmSystemTools.h" + +//---------------------------------------------------------------------------- +cmSourceFileLocation +::cmSourceFileLocation(cmMakefile* mf, const char* name): Makefile(mf) +{ + this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name); + this->AmbiguousExtension = true; + this->Directory = cmSystemTools::GetFilenamePath(name); + this->Name = cmSystemTools::GetFilenameName(name); + this->UpdateExtension(name); +} + +//---------------------------------------------------------------------------- +void cmSourceFileLocation::Update(const char* name) +{ + if(this->AmbiguousDirectory) + { + this->UpdateDirectory(name); + } + if(this->AmbiguousExtension) + { + this->UpdateExtension(name); + } +} + +//---------------------------------------------------------------------------- +void cmSourceFileLocation::Update(cmSourceFileLocation const& loc) +{ + if(this->AmbiguousDirectory && !loc.AmbiguousDirectory) + { + this->Directory = loc.Directory; + this->AmbiguousDirectory = false; + } + if(this->AmbiguousExtension && !loc.AmbiguousExtension) + { + this->Name = loc.Name; + this->AmbiguousExtension = false; + } +} + +//---------------------------------------------------------------------------- +void cmSourceFileLocation::DirectoryUseSource() +{ + if(this->AmbiguousDirectory) + { + this->Directory = + cmSystemTools::CollapseFullPath( + this->Directory.c_str(), this->Makefile->GetCurrentDirectory()); + this->AmbiguousDirectory = false; + } +} + +//---------------------------------------------------------------------------- +void cmSourceFileLocation::DirectoryUseBinary() +{ + if(this->AmbiguousDirectory) + { + this->Directory = + cmSystemTools::CollapseFullPath( + this->Directory.c_str(), this->Makefile->GetCurrentOutputDirectory()); + this->AmbiguousDirectory = false; + } +} + +//---------------------------------------------------------------------------- +void cmSourceFileLocation::UpdateExtension(const char* name) +{ + // Check the extension. + std::string ext = cmSystemTools::GetFilenameLastExtension(name); + if(!ext.empty()) { ext = ext.substr(1); } + + // TODO: Let enable-language specify extensions for each language. + cmMakefile const* mf = this->Makefile; + const std::vector& srcExts = mf->GetSourceExtensions(); + const std::vector& hdrExts = mf->GetHeaderExtensions(); + if(std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end() || + std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end()) + { + // This is a known extension. Use the given filename with extension. + this->Name = cmSystemTools::GetFilenameName(name); + this->AmbiguousExtension = false; + } +} + +//---------------------------------------------------------------------------- +void cmSourceFileLocation::UpdateDirectory(const char* name) +{ + // If a full path was given we know the directory. + if(cmSystemTools::FileIsFullPath(name)) + { + this->Directory = cmSystemTools::GetFilenamePath(name); + this->AmbiguousDirectory = false; + } +} + +//---------------------------------------------------------------------------- +bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc) +{ + if(this->AmbiguousExtension || loc.AmbiguousExtension) + { + // Need to compare without the file extension. + std::string thisName; + if(this->AmbiguousExtension) + { + thisName = this->Name; + } + else + { + thisName = cmSystemTools::GetFilenameWithoutLastExtension(this->Name); + } + std::string locName; + if(loc.AmbiguousExtension) + { + locName = loc.Name; + } + else + { + locName = cmSystemTools::GetFilenameWithoutLastExtension(loc.Name); + } + if(thisName != locName) + { + return false; + } + } + else + { + // Compare with extension. + if(this->Name != loc.Name) + { + return false; + } + } + + if(!this->AmbiguousDirectory && !loc.AmbiguousDirectory) + { + // Both sides have absolute directories. + if(this->Directory != loc.Directory) + { + return false; + } + } + else if(this->AmbiguousDirectory && loc.AmbiguousDirectory && + this->Makefile == loc.Makefile) + { + // Both sides have directories relative to the same location. + if(this->Directory != loc.Directory) + { + return false; + } + } + else if(this->AmbiguousDirectory && loc.AmbiguousDirectory) + { + // Each side has a directory relative to a different location. + // This can occur when referencing a source file from a different + // directory. This is not yet allowed. + abort(); + } + else if(this->AmbiguousDirectory) + { + // Compare possible directory combinations. + std::string srcDir = + cmSystemTools::CollapseFullPath( + this->Directory.c_str(), this->Makefile->GetCurrentDirectory()); + std::string binDir = + cmSystemTools::CollapseFullPath( + this->Directory.c_str(), this->Makefile->GetCurrentOutputDirectory()); + if(srcDir != loc.Directory && + binDir != loc.Directory) + { + return false; + } + } + else if(loc.AmbiguousDirectory) + { + // Compare possible directory combinations. + std::string srcDir = + cmSystemTools::CollapseFullPath( + loc.Directory.c_str(), loc.Makefile->GetCurrentDirectory()); + std::string binDir = + cmSystemTools::CollapseFullPath( + loc.Directory.c_str(), loc.Makefile->GetCurrentOutputDirectory()); + if(srcDir != this->Directory && + binDir != this->Directory) + { + return false; + } + } + + // File locations match. + this->Update(loc); + return true; +} diff --git a/Source/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h new file mode 100644 index 000000000..c14b2fa84 --- /dev/null +++ b/Source/cmSourceFileLocation.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef cmSourceFileLocation_h +#define cmSourceFileLocation_h + +#include "cmStandardIncludes.h" + +class cmMakefile; + +/** \class cmSourceFileLocation + * \brief cmSourceFileLocation tracks knowledge about a source file location + * + * Source files can be referenced by a variety of names. The + * directory and/or extension may be omitted leading to a certain + * level of ambiguity about the source file location. This class is + * used by cmSourceFile to keep track of what is known about the + * source file location. Each reference may add some information + * about the directory or extension of the file. + */ +class cmSourceFileLocation +{ +public: + /** + * Construct for a source file created in a given cmMakefile + * instance with an initial name. + */ + cmSourceFileLocation(cmMakefile* mf, const char* name); + + /** + * Return whether the givne source file location could refers to the + * same source file as this location given the level of ambiguity in + * each location. + */ + bool Matches(cmSourceFileLocation const& loc); + + /** + * Explicity state that the source file is located in the source tree. + */ + void DirectoryUseSource(); + + /** + * Explicity state that the source file is located in the build tree. + */ + void DirectoryUseBinary(); + + /** + * Return whether the directory containing the source is ambiguous. + */ + bool DirectoryIsAmbiguous() const { return this->AmbiguousDirectory; } + + /** + * Return whether the extension of the source name is ambiguous. + */ + bool ExtensionIsAmbiguous() const { return this->AmbiguousExtension; } + + /** + * Get the directory containing the file as best is currently known. + * If DirectoryIsAmbiguous() returns false this will be a full path. + * Otherwise it will be a relative path (possibly empty) that is + * either with respect to the source or build tree. + */ + const char* GetDirectory() const { return this->Directory.c_str(); } + + /** + * Get the file name as best is currently known. If + * ExtensionIsAmbiguous() returns true this name may not be the + * final name (but could be). Otherwise the returned name is the + * final name. + */ + const char* GetName() const { return this->Name.c_str(); } + + /** + * Get the cmMakefile instance for which the source file was created. + */ + cmMakefile* GetMakefile() const { return this->Makefile; } +private: + cmMakefile* Makefile; + bool AmbiguousDirectory; + bool AmbiguousExtension; + std::string Directory; + std::string Name; + + // Update the location with additional knowledge. + void Update(cmSourceFileLocation const& loc); + void Update(const char* name); + void UpdateExtension(const char* name); + void UpdateDirectory(const char* name); +}; + +#endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e8b6fdb87..46d4273c5 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -281,6 +281,7 @@ void cmTarget::DefineProperties(cmake *cm) "An internal property used by some generators to record the name of " "project or dsp file associated with this target."); +#if 0 cm->DefineProperty ("OBJECT_FILES", cmProperty::TARGET, "Used to get the resulting list of object files that make up a " @@ -289,6 +290,7 @@ void cmTarget::DefineProperties(cmake *cm) "into another library. It is a read only property. It " "converts the source list for the target into a list of full " "paths to object names that will be produced by the target."); +#endif #define CM_TARGET_FILE_TYPES_DOC \ "There are three kinds of target files that may be built: " \ @@ -414,16 +416,199 @@ void cmTarget::SetMakefile(cmMakefile* mf) } } - -void cmTarget::CheckForTargetsAsCommand(const cmCustomCommand& cc) +//---------------------------------------------------------------------------- +class cmTargetTraceDependencies { +public: + cmTargetTraceDependencies(cmTarget* target, const char* vsProjectFile); + void Trace(); +private: + cmTarget* Target; + cmMakefile* Makefile; + cmGlobalGenerator* GlobalGenerator; + std::queue DependencyQueue; + std::set DependenciesQueued; + std::set TargetSources; + + void QueueOnce(std::string const& name); + void QueueOnce(std::vector const& names); + void QueueDependencies(cmSourceFile* sf); + bool IsUtility(std::string const& dep); + void CheckCustomCommand(cmCustomCommand const& cc); + void CheckCustomCommands(const std::vector& commands); +}; + +//---------------------------------------------------------------------------- +cmTargetTraceDependencies +::cmTargetTraceDependencies(cmTarget* target, const char* vsProjectFile): + Target(target) +{ + // Convenience. + this->Makefile = this->Target->GetMakefile(); + this->GlobalGenerator = + this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + + // Queue all the source files already specified for the target. + std::vector const& sources = this->Target->GetSourceFiles(); + for(std::vector::const_iterator si = sources.begin(); + si != sources.end(); ++si) + { + // Queue the source file itself in case it is generated. + this->QueueOnce((*si)->GetFullPath()); + + // Queue the dependencies of the source file in case they are + // generated. + this->QueueDependencies(*si); + + // Track the sources already known to the target. + this->TargetSources.insert(*si); + } + + // Queue the VS project file to check dependencies on the rule to + // generate it. + if(vsProjectFile) + { + this->QueueOnce(vsProjectFile); + } + + // Queue pre-build, pre-link, and post-build rule dependencies. + this->CheckCustomCommands(this->Target->GetPreBuildCommands()); + this->CheckCustomCommands(this->Target->GetPreLinkCommands()); + this->CheckCustomCommands(this->Target->GetPostBuildCommands()); +} + +//---------------------------------------------------------------------------- +void cmTargetTraceDependencies::Trace() +{ + // Process one dependency at a time until the queue is empty. + while(!this->DependencyQueue.empty()) + { + // Get the next dependency in from queue. + std::string dep = this->DependencyQueue.front(); + this->DependencyQueue.pop(); + + // Check if we know how to generate this dependency. + if(cmSourceFile* sf = + this->Makefile->GetSourceFileWithOutput(dep.c_str())) + { + // Queue dependencies needed to generate this file. + this->QueueDependencies(sf); + + // Make sure this file is in the target. + if(this->TargetSources.insert(sf).second) + { + this->Target->AddSourceFile(sf); + } + } + } +} + +//---------------------------------------------------------------------------- +void cmTargetTraceDependencies::QueueOnce(std::string const& name) +{ + if(this->DependenciesQueued.insert(name).second) + { + this->DependencyQueue.push(name); + } +} + +//---------------------------------------------------------------------------- +void +cmTargetTraceDependencies::QueueOnce(std::vector const& names) +{ + for(std::vector::const_iterator i = names.begin(); + i != names.end(); ++i) + { + this->QueueOnce(*i); + } +} + +//---------------------------------------------------------------------------- +bool cmTargetTraceDependencies::IsUtility(std::string const& dep) +{ + // Dependencies on targets (utilities) are supposed to be named by + // just the target name. However for compatibility we support + // naming the output file generated by the target (assuming there is + // no output-name property which old code would not have set). In + // that case the target name will be the file basename of the + // dependency. + std::string util = cmSystemTools::GetFilenameName(dep); + if(cmSystemTools::GetFilenameLastExtension(util) == ".exe") + { + util = cmSystemTools::GetFilenameWithoutLastExtension(util); + } + + // Check for a non-imported target with this name. + if(cmTarget* t = + this->GlobalGenerator->FindTarget(0, util.c_str(), false)) + { + // If we find the target and the dep was given as a full path, + // then make sure it was not a full path to something else, and + // the fact that the name matched a target was just a coincidence. + if(cmSystemTools::FileIsFullPath(dep.c_str())) + { + // This is really only for compatibility so we do not need to + // worry about configuration names and output names. + std::string tLocation = t->GetLocation(0); + tLocation = cmSystemTools::GetFilenamePath(tLocation); + std::string depLocation = cmSystemTools::GetFilenamePath(dep); + depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str()); + tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str()); + if(depLocation == tLocation) + { + this->Target->AddUtility(util.c_str()); + return true; + } + } + else + { + // The original name of the dependency was not a full path. It + // must name a target, so add the target-level dependency. + this->Target->AddUtility(util.c_str()); + return true; + } + } + + // The dependency does not name a target built in this project. + return false; +} + +//---------------------------------------------------------------------------- +void cmTargetTraceDependencies::QueueDependencies(cmSourceFile* sf) +{ + // Queue dependency added explicitly by the user. + if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) + { + std::vector objDeps; + cmSystemTools::ExpandListArgument(additionalDeps, objDeps); + this->QueueOnce(objDeps); + } + + // Queue dependencies added programatically by commands. + this->QueueOnce(sf->GetDepends()); + + // Queue custom command dependencies. + if(cmCustomCommand const* cc = sf->GetCustomCommand()) + { + this->CheckCustomCommand(*cc); + } + +} + +//---------------------------------------------------------------------------- +void +cmTargetTraceDependencies +::CheckCustomCommand(cmCustomCommand const& cc) +{ + // Transform command names that reference targets built in this + // project to corresponding target-level dependencies. for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin(); - cit != cc.GetCommandLines().end(); ++cit ) + cit != cc.GetCommandLines().end(); ++cit) { std::string const& command = *cit->begin(); // Look for a non-imported target with this name. - if(cmTarget* t = this->Makefile->GetLocalGenerator()-> - GetGlobalGenerator()->FindTarget(0, command.c_str(), false)) + if(cmTarget* t = + this->GlobalGenerator->FindTarget(0, command.c_str(), false)) { if(t->GetType() == cmTarget::EXECUTABLE) { @@ -431,269 +616,67 @@ void cmTarget::CheckForTargetsAsCommand(const cmCustomCommand& cc) // this project. Add the target-level dependency to make // sure the executable is up to date before this custom // command possibly runs. - this->AddUtility(command.c_str()); + this->Target->AddUtility(command.c_str()); } } } + + // Queue the custom command dependencies. + std::vector const& depends = cc.GetDepends(); + for(std::vector::const_iterator di = depends.begin(); + di != depends.end(); ++di) + { + std::string const& dep = *di; + if(!this->IsUtility(dep)) + { + // The dependency does not name a target and may be a file we + // know how to generate. Queue it. + this->QueueOnce(dep); + } + } } +//---------------------------------------------------------------------------- void -cmTarget -::CheckForTargetsAsCommand(const std::vector& commands) +cmTargetTraceDependencies +::CheckCustomCommands(const std::vector& commands) { - for ( std::vector::const_iterator cli = commands.begin(); - cli != commands.end(); - ++cli ) + for(std::vector::const_iterator cli = commands.begin(); + cli != commands.end(); ++cli) { - this->CheckForTargetsAsCommand(*cli); + this->CheckCustomCommand(*cli); } } +//---------------------------------------------------------------------------- +void cmTarget::TraceDependencies(const char* vsProjectFile) +{ + // Use a helper object to trace the dependencies. + cmTargetTraceDependencies tracer(this, vsProjectFile); + tracer.Trace(); +} -void cmTarget::TraceVSDependencies(std::string projFile, - cmMakefile *makefile) -{ - // get the classes from the source lists then add them to the groups - std::vector & classes = this->SourceFiles; - // use a deck to keep track of processed source files - std::queue srcFilesToProcess; - std::set srcFilesQueued; - std::string name; - std::vector newClasses; - for(std::vector::const_iterator i = classes.begin(); - i != classes.end(); ++i) +//---------------------------------------------------------------------------- +void cmTarget::AddSources(std::vector const& srcs) +{ + for(std::vector::const_iterator i = srcs.begin(); + i != srcs.end(); ++i) { - name = (*i)->GetSourceName(); - if ((*i)->GetSourceExtension() != "rule") - { - name += "."; - name += (*i)->GetSourceExtension(); - } - srcFilesToProcess.push(name); - srcFilesQueued.insert(name); - // does this sourcefile have object depends on it? - // If so then add them as well - const char* additionalDeps = (*i)->GetProperty("OBJECT_DEPENDS"); - std::vector depends = (*i)->GetDepends(); - if (additionalDeps || depends.size()) - { - if(additionalDeps) - { - cmSystemTools::ExpandListArgument(additionalDeps, depends); - } - for(std::vector::iterator id = depends.begin(); - id != depends.end(); ++id) - { - // if there is a custom rule to generate that dependency - // then add it to the list - cmSourceFile* outsf = - makefile->GetSourceFileWithOutput(id->c_str()); - // if a source file was found then add it - if (outsf && - (std::find(classes.begin(),classes.end(),outsf) == classes.end()) - && - (std::find(newClasses.begin(),newClasses.end(),outsf) - == newClasses.end())) - { - // then add the source to this target and add it to the queue - newClasses.push_back(outsf); - name = outsf->GetSourceName(); - if (outsf->GetSourceExtension() != "rule") - { - name += "."; - name += outsf->GetSourceExtension(); - } - std::string temp = - cmSystemTools::GetFilenamePath(outsf->GetFullPath()); - temp += "/"; - temp += name; - // if it hasn't been processed - if (srcFilesQueued.find(temp) == srcFilesQueued.end()) - { - srcFilesToProcess.push(temp); - srcFilesQueued.insert(temp); - } - } - } - } - } - for(std::vector::const_iterator i = newClasses.begin(); - i != newClasses.end(); ++i) - { - classes.push_back(*i); - } - - // add in the project file itself - if (projFile.size()) - { - srcFilesToProcess.push(projFile); - srcFilesQueued.insert(projFile); - } - // add in the library depends for custom targets - if (this->GetType() == cmTarget::UTILITY || - this->GetType() == cmTarget::GLOBAL_TARGET) - { - for (std::vector::iterator ic = - this->GetPostBuildCommands().begin(); - ic != this->GetPostBuildCommands().end(); ++ic) - { - cmCustomCommand &c = *ic; - for (std::vector::const_iterator i - = c.GetDepends().begin(); i != c.GetDepends().end(); ++i) - { - srcFilesToProcess.push(*i); - srcFilesQueued.insert(*i); - } - } - } - - this->CheckForTargetsAsCommand(this->GetPreBuildCommands()); - this->CheckForTargetsAsCommand(this->GetPreLinkCommands()); - this->CheckForTargetsAsCommand(this->GetPostBuildCommands()); - - while (!srcFilesToProcess.empty()) - { - // is this source the output of a custom command - cmSourceFile* outsf = - makefile->GetSourceFileWithOutput(srcFilesToProcess.front().c_str()); - if (outsf) - { - // is it not already in the target? - if (std::find(classes.begin(),classes.end(),outsf) == classes.end()) - { - // then add the source to this target and add it to the queue - classes.push_back(outsf); - name = outsf->GetSourceName(); - if (outsf->GetSourceExtension() != "rule") - { - name += "."; - name += outsf->GetSourceExtension(); - } - std::string temp = - cmSystemTools::GetFilenamePath(outsf->GetFullPath()); - temp += "/"; - temp += name; - // if it hasn't been processed - if (srcFilesQueued.find(temp) == srcFilesQueued.end()) - { - srcFilesToProcess.push(temp); - srcFilesQueued.insert(temp); - } - } - - // Add target-level dependencies for the commands. - this->CheckForTargetsAsCommand(*outsf->GetCustomCommand()); - - // add its dependencies to the list to check - for (unsigned int i = 0; - i < outsf->GetCustomCommand()->GetDepends().size(); - ++i) - { - const std::string& fullName - = outsf->GetCustomCommand()->GetDepends()[i]; - std::string dep = cmSystemTools::GetFilenameName(fullName); - if (cmSystemTools::GetFilenameLastExtension(dep) == ".exe") - { - dep = cmSystemTools::GetFilenameWithoutLastExtension(dep); - } - bool isUtility = false; - // Check for a non-imported target with this name. - if(cmTarget* t = this->Makefile->GetLocalGenerator()-> - GetGlobalGenerator()->FindTarget(0, dep.c_str(), false)) - { - // if we find the target and the dep was given as a full - // path, then make sure it was not a full path to something - // else, and the fact that the name matched a target was - // just a coincident - if(cmSystemTools::FileIsFullPath(fullName.c_str())) - { - std::string tLocation = t->GetLocation(0); - tLocation = cmSystemTools::GetFilenamePath(tLocation); - std::string depLocation = cmSystemTools::GetFilenamePath( - std::string(fullName)); - depLocation = - cmSystemTools::CollapseFullPath(depLocation.c_str()); - tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str()); - if(depLocation == tLocation) - { - isUtility = true; - } - } - // if it was not a full path then it must be a target - else - { - isUtility = true; - } - } - if(isUtility) - { - // The dependency refers to a target built in this project. - // Add the target-level dependency to make sure the target - // is up to date before this custom command possibly runs. - this->AddUtility(dep.c_str()); - } - else - { - if (srcFilesQueued.find(outsf->GetCustomCommand()->GetDepends()[i]) - == srcFilesQueued.end()) - { - srcFilesToProcess.push - (outsf->GetCustomCommand()->GetDepends()[i]); - srcFilesQueued.insert(outsf->GetCustomCommand()->GetDepends()[i]); - } - } - } - - } - // finished with this SF move to the next - srcFilesToProcess.pop(); + this->AddSource(i->c_str()); } } -void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf) +cmSourceFile* cmTarget::AddSource(const char* s) { - // only allow this to be called once - // there is a lazy evaluation of this in ComputeObjectFiles, - // that could break backwards compatibility with projects that - // use old style source lists. - if(this->SourceFiles.size() != 0) - { - return; - } - // for each src lists add the classes - for (std::vector::const_iterator s = this->SourceLists.begin(); - s != this->SourceLists.end(); ++s) - { - int done = 0; - // replace any variables - std::string temps = *s; - mf.ExpandVariablesInString(temps); + std::string src = s; - // Next if one wasn't found then assume it is a single class - // check to see if it is an existing source file - if (!done) - { - cmSourceFile* sourceFile = mf.GetSource(temps.c_str()); - if ( sourceFile ) - { - this->SourceFiles.push_back(sourceFile); - done = 1; - } - } - - // if we still are not done, try to create the SourceFile structure - if (!done) - { - cmSourceFile file; - file.GetProperties(). - SetCMakeInstance(this->Makefile->GetCMakeInstance()); - file.SetProperty("ABSTRACT","0"); - file.SetName(temps.c_str(), mf.GetCurrentDirectory(), - mf.GetSourceExtensions(), - mf.GetHeaderExtensions(), this->Name.c_str()); - this->SourceFiles.push_back(mf.AddSource(file)); - } - } + // For backwards compatibility replace varibles in source names. + // This should eventually be removed. + this->Makefile->ExpandVariablesInString(src); + + cmSourceFile* sf = this->Makefile->GetOrCreateSource(src.c_str()); + this->AddSourceFile(sf); + return sf; } void cmTarget::MergeLinkLibraries( cmMakefile& mf, @@ -1328,9 +1311,7 @@ void cmTarget::ComputeObjectFiles() { return; } - - // Force the SourceFiles vector to be populated - this->GenerateSourceFilesFromSourceLists(*this->Makefile); +#if 0 std::vector dirs; this->Makefile->GetLocalGenerator()-> GetTargetObjectFileDirectories(this, @@ -1346,10 +1327,7 @@ void cmTarget::ComputeObjectFiles() s != this->SourceFiles.end(); ++s) { cmSourceFile* sf = *s; - const char* lang = this->Makefile->GetLocalGenerator()-> - GetGlobalGenerator()-> - GetLanguageFromExtension(sf->GetSourceExtension().c_str()); - if (lang) + if(const char* lang = sf->GetLanguage()) { std::string lookupObj = objExtensionLookup1 + lang; lookupObj += objExtensionLookup2; @@ -1371,6 +1349,7 @@ void cmTarget::ComputeObjectFiles() } } this->SetProperty("OBJECT_FILES", objectFiles.c_str()); +#endif } @@ -1487,9 +1466,7 @@ const char* cmTarget::GetLinkerLanguage(cmGlobalGenerator* gg) = this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i) { - const char* lang = - gg->GetLanguageFromExtension((*i)->GetSourceExtension().c_str()); - if(lang) + if(const char* lang = (*i)->GetLanguage()) { languages.insert(lang); } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index e8b17eef5..c87f56dc9 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -73,16 +73,6 @@ public: std::vector &GetPostBuildCommands() {return this->PostBuildCommands;} - /** - * Get the list of the source lists used by this target - */ - std::vector const& GetSourceLists() {return this->SourceLists;} - - void AddSourceListEntry(const char* src) - { this->SourceLists.push_back(src); } - void SetSourceList(std::vector const& srcs) - { this->SourceLists = srcs; } - ///! Return the list of frameworks being linked to this target std::vector &GetFrameworks() {return this->Frameworks;} @@ -93,6 +83,12 @@ public: {return this->SourceFiles;} void AddSourceFile(cmSourceFile* sf) { this->SourceFiles.push_back(sf); } + /** + * Add sources to the target. + */ + void AddSources(std::vector const& srcs); + cmSourceFile* AddSource(const char* src); + /** * Get the list of the source files used by this target */ @@ -149,12 +145,6 @@ public: bool GetHaveInstallRule() { return this->HaveInstallRule; } void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; } - /** - * Generate the SourceFilesList from the SourceLists. This should only be - * done once to be safe. - */ - void GenerateSourceFilesFromSourceLists(cmMakefile &mf); - /** Add a utility on which this project depends. A utility is an executable * name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE * commands. It is not a full path nor does it have an extension. @@ -193,7 +183,7 @@ public: * Trace through the source files in this target and add al source files * that they depend on, used by all generators */ - void TraceVSDependencies(std::string projName, cmMakefile *mf); + void TraceDependencies(const char* vsProjectFile); ///! Return the prefered linker language for this target const char* GetLinkerLanguage(cmGlobalGenerator*); @@ -302,14 +292,6 @@ private: const LibraryID& lib, const LibraryID& dep); - /* - * Check custom commands for known targets and add a target-level - * dependency. - */ - void CheckForTargetsAsCommand(const cmCustomCommand& cc); - void CheckForTargetsAsCommand(const std::vector& commands); - - /** * Emits the library \a lib and all its dependencies into link_line. * \a emitted keeps track of the libraries that have been emitted to @@ -379,7 +361,6 @@ private: std::vector PreBuildCommands; std::vector PreLinkCommands; std::vector PostBuildCommands; - std::vector SourceLists; TargetType TargetTypeValue; std::vector SourceFiles; LinkLibraryVectorType LinkLibraries; diff --git a/bootstrap b/bootstrap index 0e3748c70..6d4d08d51 100755 --- a/bootstrap +++ b/bootstrap @@ -137,6 +137,7 @@ CMAKE_CXX_SOURCES="\ cmInstallScriptGenerator \ cmInstallTargetGenerator \ cmSourceFile \ + cmSourceFileLocation \ cmSystemTools \ cmVersion \ cmFileTimeComparison \