From 35936433e11728397dcdb2beab615674bfa79ec7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 18 Jun 2007 11:59:23 -0400 Subject: [PATCH] ENH: Merging changes from branch CMake-SourceFile2-b between tags CMake-SourceFile2-bp and CMake-SourceFile2-b-mp1 to trunk. This commit is surrounded by tags CMake-SourceFile2-b-mp1-pre and CMake-SourceFile2-b-mp1-post on the trunk. The changes re-implement cmSourceFile and the use of it to allow instances to be created much earlier. The use of cmSourceFileLocation allows locating a source file referenced by a user to be much simpler and more robust. The two SetName methods are no longer needed so some duplicate code has been removed. The strange "SourceName" stuff is gone. Code that created cmSourceFile instances on the stack and then sent them to cmMakefile::AddSource has been simplified and converted to getting cmSourceFile instances from cmMakefile. The CPluginAPI has preserved the old API through a compatibility interface. Source lists are gone. Targets now get real instances of cmSourceFile right away instead of storing a list of strings until the final pass. TraceVSDependencies has been re-written to avoid the use of SourceName. It is now called TraceDependencies since it is not just for VS. It is now implemented with a helper object which makes the code simpler. --- Source/CMakeLists.txt | 2 + Source/cmAuxSourceDirectoryCommand.cxx | 21 +- Source/cmCPluginAPI.cxx | 329 +++++++++++-- Source/cmCreateTestSourceList.cxx | 26 +- Source/cmFLTKWrapUICommand.cxx | 21 +- Source/cmGetSourceFilePropertyCommand.cxx | 5 + Source/cmGlobalGenerator.cxx | 40 +- Source/cmGlobalGenerator.h | 6 +- Source/cmGlobalXCodeGenerator.cxx | 18 +- Source/cmLocalGenerator.cxx | 66 +-- Source/cmLocalGenerator.h | 2 - Source/cmLocalVisualStudio6Generator.cxx | 2 +- Source/cmLocalVisualStudio7Generator.cxx | 29 +- Source/cmLocalVisualStudio7Generator.h | 2 - Source/cmLocalVisualStudioGenerator.cxx | 4 +- Source/cmLocalXCodeGenerator.cxx | 13 - Source/cmLocalXCodeGenerator.h | 2 - Source/cmMakefile.cxx | 222 +-------- Source/cmMakefile.h | 9 +- Source/cmMakefileLibraryTargetGenerator.cxx | 21 +- Source/cmMakefileTargetGenerator.cxx | 5 +- Source/cmOutputRequiredFilesCommand.cxx | 7 - Source/cmQTWrapCPPCommand.cxx | 144 +++--- Source/cmQTWrapCPPCommand.h | 20 - Source/cmQTWrapUICommand.cxx | 290 +++++------- Source/cmQTWrapUICommand.h | 23 - Source/cmSourceFile.cxx | 356 ++++++++------ Source/cmSourceFile.h | 89 ++-- Source/cmSourceFileLocation.cxx | 212 +++++++++ Source/cmSourceFileLocation.h | 104 ++++ Source/cmTarget.cxx | 497 ++++++++++---------- Source/cmTarget.h | 33 +- bootstrap | 1 + 33 files changed, 1397 insertions(+), 1224 deletions(-) create mode 100644 Source/cmSourceFileLocation.cxx create mode 100644 Source/cmSourceFileLocation.h 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 \