diff options
Diffstat (limited to 'Source/cmSourceFile.cxx')
-rw-r--r-- | Source/cmSourceFile.cxx | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx new file mode 100644 index 0000000..a9ac549 --- /dev/null +++ b/Source/cmSourceFile.cxx @@ -0,0 +1,403 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmSourceFile.h" + +#include "cmGlobalGenerator.h" +#include "cmMakefile.h" +#include "cmSystemTools.h" +#include "cmake.h" + +//---------------------------------------------------------------------------- +cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name): + Location(mf, name) +{ + this->CustomCommand = 0; + this->FindFullPathFailed = false; + this->IsUiFile = (".ui" == + cmSystemTools::GetFilenameLastExtension(this->Location.GetName())); +} + +//---------------------------------------------------------------------------- +cmSourceFile::~cmSourceFile() +{ + this->SetCustomCommand(0); +} + +//---------------------------------------------------------------------------- +std::string const& cmSourceFile::GetExtension() const +{ + return this->Extension; +} + +const std::string cmSourceFile::propLANGUAGE = "LANGUAGE"; + +//---------------------------------------------------------------------------- +void cmSourceFile::SetObjectLibrary(std::string const& objlib) +{ + this->ObjectLibrary = objlib; +} + +//---------------------------------------------------------------------------- +std::string cmSourceFile::GetObjectLibrary() const +{ + return this->ObjectLibrary; +} + +//---------------------------------------------------------------------------- +std::string cmSourceFile::GetLanguage() +{ + // If the language was set explicitly by the user then use it. + if(const char* lang = this->GetProperty(propLANGUAGE)) + { + return lang; + } + + // Perform computation needed to get the language if necessary. + if(this->FullPath.empty() && this->Language.empty()) + { + // If a known extension is given or a known full path is given + // then trust that the current extension is sufficient to + // determine the language. This will fail only if the user + // specifies a full path to the source but leaves off the + // extension, which is kind of weird. + if(this->Location.ExtensionIsAmbiguous() && + this->Location.DirectoryIsAmbiguous()) + { + // Finalize the file location to get the extension and set the + // language. + this->GetFullPath(); + } + else + { + // Use the known extension to get the language if possible. + std::string ext = + cmSystemTools::GetFilenameLastExtension(this->Location.GetName()); + this->CheckLanguage(ext); + } + } + + // Now try to determine the language. + return static_cast<cmSourceFile const*>(this)->GetLanguage(); +} + +//---------------------------------------------------------------------------- +std::string cmSourceFile::GetLanguage() const +{ + // If the language was set explicitly by the user then use it. + if(const char* lang = this->GetProperty(propLANGUAGE)) + { + return lang; + } + + // If the language was determined from the source file extension use it. + if(!this->Language.empty()) + { + return this->Language; + } + + // The language is not known. + return ""; +} + +//---------------------------------------------------------------------------- +cmSourceFileLocation const& cmSourceFile::GetLocation() const +{ + return this->Location; +} + +//---------------------------------------------------------------------------- +std::string const& cmSourceFile::GetFullPath(std::string* error) +{ + if(this->FullPath.empty()) + { + if(this->FindFullPath(error)) + { + this->CheckExtension(); + } + } + return this->FullPath; +} + +//---------------------------------------------------------------------------- +std::string const& cmSourceFile::GetFullPath() const +{ + return this->FullPath; +} + +//---------------------------------------------------------------------------- +bool cmSourceFile::FindFullPath(std::string* error) +{ + // 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; + } + + // The file is not generated. It must exist on disk. + cmMakefile const* mf = this->Location.GetMakefile(); + const char* tryDirs[3] = {0, 0, 0}; + if(this->Location.DirectoryIsAmbiguous()) + { + tryDirs[0] = mf->GetCurrentSourceDirectory(); + tryDirs[1] = mf->GetCurrentBinaryDirectory(); + } + else + { + tryDirs[0] = ""; + } + const std::vector<std::string>& srcExts = + mf->GetCMakeInstance()->GetSourceExtensions(); + std::vector<std::string> hdrExts = + mf->GetCMakeInstance()->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, *di); + if(this->TryFullPath(tryPath, "")) + { + return true; + } + for(std::vector<std::string>::const_iterator ei = srcExts.begin(); + ei != srcExts.end(); ++ei) + { + if(this->TryFullPath(tryPath, *ei)) + { + return true; + } + } + for(std::vector<std::string>::const_iterator ei = hdrExts.begin(); + ei != hdrExts.end(); ++ei) + { + if(this->TryFullPath(tryPath, *ei)) + { + return true; + } + } + } + + std::ostringstream e; + std::string missing = this->Location.GetDirectory(); + if(!missing.empty()) + { + missing += "/"; + } + missing += this->Location.GetName(); + e << "Cannot find source file:\n " << missing << "\nTried extensions"; + for(std::vector<std::string>::const_iterator ext = srcExts.begin(); + ext != srcExts.end(); ++ext) + { + e << " ." << *ext; + } + for(std::vector<std::string>::const_iterator ext = hdrExts.begin(); + ext != hdrExts.end(); ++ext) + { + e << " ." << *ext; + } + if(error) + { + *error = e.str(); + } + else + { + this->Location.GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); + } + this->FindFullPathFailed = true; + return false; +} + +//---------------------------------------------------------------------------- +bool cmSourceFile::TryFullPath(const std::string& path, + const std::string& ext) +{ + std::string tryPath = path; + if(!ext.empty()) + { + tryPath += "."; + tryPath += ext; + } + 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"); + } + + // Try to identify the source file language from the extension. + if(this->Language.empty()) + { + this->CheckLanguage(this->Extension); + } +} + +//---------------------------------------------------------------------------- +void cmSourceFile::CheckLanguage(std::string const& ext) +{ + // Try to identify the source file language from the extension. + cmMakefile const* mf = this->Location.GetMakefile(); + cmGlobalGenerator* gg = mf->GetGlobalGenerator(); + std::string l = gg->GetLanguageFromExtension(ext.c_str()); + if(!l.empty()) + { + this->Language = l; + } +} + +//---------------------------------------------------------------------------- +bool cmSourceFile::Matches(cmSourceFileLocation const& loc) +{ + return this->Location.Matches(loc); +} + +//---------------------------------------------------------------------------- +void cmSourceFile::SetProperty(const std::string& prop, const char* value) +{ + this->Properties.SetProperty(prop, value); + + if (this->IsUiFile) + { + cmMakefile const* mf = this->Location.GetMakefile(); + if (prop == "AUTOUIC_OPTIONS") + { + const_cast<cmMakefile*>(mf)->AddQtUiFileWithOptions(this); + } + } +} + +//---------------------------------------------------------------------------- +void cmSourceFile::AppendProperty(const std::string& prop, const char* value, + bool asString) +{ + this->Properties.AppendProperty(prop, value, asString); +} + +//---------------------------------------------------------------------------- +const char* cmSourceFile::GetPropertyForUser(const std::string& prop) +{ + // This method is a consequence of design history and backwards + // compatibility. GetProperty is (and should be) a const method. + // Computed properties should not be stored back in the property map + // but instead reference information already known. If they need to + // cache information in a mutable ivar to provide the return string + // safely then so be it. + // + // The LOCATION property is particularly problematic. The CMake + // language has very loose restrictions on the names that will match + // a given source file (for historical reasons). Implementing + // lookups correctly with such loose naming requires the + // cmSourceFileLocation class to commit to a particular full path to + // the source file as late as possible. If the users requests the + // LOCATION property we must commit now. + if(prop == "LOCATION") + { + // Commit to a location. + this->GetFullPath(); + } + + // Perform the normal property lookup. + return this->GetProperty(prop); +} + +//---------------------------------------------------------------------------- +const char* cmSourceFile::GetProperty(const std::string& prop) const +{ + // Check for computed properties. + if(prop == "LOCATION") + { + if(this->FullPath.empty()) + { + return 0; + } + else + { + return this->FullPath.c_str(); + } + } + + const char *retVal = this->Properties.GetPropertyValue(prop); + if (!retVal) + { + cmMakefile const* mf = this->Location.GetMakefile(); + const bool chain = mf->GetState()-> + IsPropertyChained(prop, cmProperty::SOURCE_FILE); + if (chain) + { + return mf->GetProperty(prop, chain); + } + } + + return retVal; +} + +//---------------------------------------------------------------------------- +bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const +{ + return cmSystemTools::IsOn(this->GetProperty(prop)); +} + +//---------------------------------------------------------------------------- +cmCustomCommand* cmSourceFile::GetCustomCommand() +{ + return this->CustomCommand; +} + +//---------------------------------------------------------------------------- +cmCustomCommand const* cmSourceFile::GetCustomCommand() const +{ + return this->CustomCommand; +} + +//---------------------------------------------------------------------------- +void cmSourceFile::SetCustomCommand(cmCustomCommand* cc) +{ + cmCustomCommand* old = this->CustomCommand; + this->CustomCommand = cc; + delete old; +} |