diff options
author | Brad King <brad.king@kitware.com> | 2007-06-18 15:59:23 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2007-06-18 15:59:23 (GMT) |
commit | 35936433e11728397dcdb2beab615674bfa79ec7 (patch) | |
tree | 8222a4daea955055c852d6db058421a570a8f6b2 /Source/cmSourceFile.cxx | |
parent | ef81ac50e5d6e981088c00e822fde538d9da9e37 (diff) | |
download | CMake-35936433e11728397dcdb2beab615674bfa79ec7.zip CMake-35936433e11728397dcdb2beab615674bfa79ec7.tar.gz CMake-35936433e11728397dcdb2beab615674bfa79ec7.tar.bz2 |
ENH: Merging changes from branch CMake-SourceFile2-b between tags
CMake-SourceFile2-bp and CMake-SourceFile2-b-mp1 to trunk. This
commit is surrounded by tags CMake-SourceFile2-b-mp1-pre and
CMake-SourceFile2-b-mp1-post on the trunk.
The changes re-implement cmSourceFile and the use of it to allow
instances to be created much earlier. The use of cmSourceFileLocation
allows locating a source file referenced by a user to be much simpler
and more robust. The two SetName methods are no longer needed so some
duplicate code has been removed. The strange "SourceName" stuff is
gone. Code that created cmSourceFile instances on the stack and then
sent them to cmMakefile::AddSource has been simplified and converted
to getting cmSourceFile instances from cmMakefile. The CPluginAPI has
preserved the old API through a compatibility interface.
Source lists are gone. Targets now get real instances of cmSourceFile
right away instead of storing a list of strings until the final pass.
TraceVSDependencies has been re-written to avoid the use of
SourceName. It is now called TraceDependencies since it is not just
for VS. It is now implemented with a helper object which makes the
code simpler.
Diffstat (limited to 'Source/cmSourceFile.cxx')
-rw-r--r-- | Source/cmSourceFile.cxx | 350 |
1 files changed, 209 insertions, 141 deletions
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 4fc74e8..c9d0c48 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<std::string>& sourceExts, - const std::vector<std::string>& 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); +//---------------------------------------------------------------------------- +const char* cmSourceFile::GetLanguage() +{ + // Compute the final location of the file if necessary. + if(this->FullPath.empty()) + { + this->GetFullPath(); + } + + // Now try to determine the language. + return static_cast<cmSourceFile const*>(this)->GetLanguage(); +} - // 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() const +{ + // If the language was set explicitly by the user then use it. + if(const char* lang = this->GetProperty("LANGUAGE")) { - 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); - } - } - } + return lang; + } - // 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; + // If the language was determined from the source file extension use it. + if(!this->Language.empty()) + { + return this->Language.c_str(); + } - // 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" ) + // 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 true; } - - // Next, try the various source extensions - for( std::vector<std::string>::const_iterator ext = sourceExts.begin(); - ext != sourceExts.end(); ++ext ) + 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) { - hname = pathname; - hname += "."; - hname += *ext; - if(cmSystemTools::FileExists(hname.c_str())) - { - this->SourceExtension = *ext; - this->SetProperty("HEADER_FILE_ONLY","0"); - this->FullPath = hname; - return true; - } + return false; } - // Finally, try the various header extensions - for( std::vector<std::string>::const_iterator ext = headerExts.begin(); - ext != headerExts.end(); ++ext ) + // 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; + } + + // 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()) + { + tryDirs[0] = mf->GetCurrentDirectory(); + tryDirs[1] = mf->GetCurrentOutputDirectory(); + } + else + { + tryDirs[0] = ""; + } + const std::vector<std::string>& srcExts = mf->GetSourceExtensions(); + const std::vector<std::string>& hdrExts = mf->GetHeaderExtensions(); + for(const char* const* di = tryDirs; *di; ++di) { - hname = pathname; - hname += "."; - hname += *ext; - if(cmSystemTools::FileExists(hname.c_str())) + 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->FullPath = hname; return true; } + for(std::vector<std::string>::const_iterator ei = srcExts.begin(); + ei != srcExts.end(); ++ei) + { + if(this->TryFullPath(tryPath.c_str(), ei->c_str())) + { + return true; + } + } + for(std::vector<std::string>::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<std::string>::const_iterator ext = sourceExts.begin(); - ext != sourceExts.end(); ++ext ) + for(std::vector<std::string>::const_iterator ext = srcExts.begin(); + ext != srcExts.end(); ++ext) { e << " ." << *ext; } - for( std::vector<std::string>::const_iterator ext = headerExts.begin(); - ext != headerExts.end(); ++ext ) + for(std::vector<std::string>::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; - - // 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" ) + if(cmSystemTools::FileExists(tryPath.c_str())) + { + this->FullPath = tryPath; + return true; + } + return false; +} + +//---------------------------------------------------------------------------- +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<std::string>& 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) -{ - if(this->CustomCommand) - { - delete this->CustomCommand; - } - this->CustomCommand = cc; -} - -const std::string& cmSourceFile::GetSourceNameWithoutLastExtension() +//---------------------------------------------------------------------------- +cmCustomCommand* cmSourceFile::GetCustomCommand() { - if ( this->SourceNameWithoutLastExtension.empty() ) - { - this->SourceNameWithoutLastExtension = - cmSystemTools::GetFilenameWithoutLastExtension(this->FullPath); - } - return this->SourceNameWithoutLastExtension; + return this->CustomCommand; } -cmSourceFile::cmSourceFile() +//---------------------------------------------------------------------------- +cmCustomCommand const* cmSourceFile::GetCustomCommand() const { - this->Makefile = 0; - this->CustomCommand = 0; + return this->CustomCommand; } //---------------------------------------------------------------------------- -void cmSourceFile::SetMakefile(cmMakefile* mf) +void cmSourceFile::SetCustomCommand(cmCustomCommand* cc) { - // Set our makefile. - this->Makefile = mf; - - // set the cmake instance of the properties - this->Properties.SetCMakeInstance(mf->GetCMakeInstance()); + cmCustomCommand* old = this->CustomCommand; + this->CustomCommand = cc; + delete old; } -// define properties +//---------------------------------------------------------------------------- void cmSourceFile::DefineProperties(cmake *cm) { // define properties |