diff options
Diffstat (limited to 'Source')
39 files changed, 1106 insertions, 757 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a7adb51..6d012fd 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -281,6 +281,7 @@ set(SRCS cmInstallTargetGenerator.cxx cmInstallDirectoryGenerator.h cmInstallDirectoryGenerator.cxx + cmLinkedTree.h cmListFileCache.cxx cmListFileCache.h cmListFileLexer.c @@ -299,6 +300,8 @@ set(SRCS cmMakefileUtilityTargetGenerator.cxx cmOSXBundleGenerator.cxx cmOSXBundleGenerator.h + cmOutputConverter.cxx + cmOutputConverter.h cmNewLineStyle.h cmNewLineStyle.cxx cmOrderDirectories.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a4c877e..c9aec51 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 3) -set(CMake_VERSION_PATCH 20150604) +set(CMake_VERSION_PATCH 20150608) #set(CMake_VERSION_RC 1) diff --git a/Source/cmCPackPropertiesGenerator.cxx b/Source/cmCPackPropertiesGenerator.cxx index cf24c13..368a0e6 100644 --- a/Source/cmCPackPropertiesGenerator.cxx +++ b/Source/cmCPackPropertiesGenerator.cxx @@ -1,6 +1,6 @@ #include "cmCPackPropertiesGenerator.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" cmCPackPropertiesGenerator::cmCPackPropertiesGenerator( cmMakefile* mf, @@ -29,15 +29,15 @@ void cmCPackPropertiesGenerator::GenerateScriptForConfig(std::ostream& os, cmInstalledFile::Property const& property = i->second; os << indent << "set_property(INSTALL " << - cmLocalGenerator::EscapeForCMake(expandedFileName) << " PROPERTY " << - cmLocalGenerator::EscapeForCMake(name); + cmOutputConverter::EscapeForCMake(expandedFileName) << " PROPERTY " << + cmOutputConverter::EscapeForCMake(name); for(cmInstalledFile::ExpressionVectorType::const_iterator j = property.ValueExpressions.begin(); j != property.ValueExpressions.end(); ++j) { std::string value = (*j)->Evaluate(this->Makefile, config); - os << " " << cmLocalGenerator::EscapeForCMake(value); + os << " " << cmOutputConverter::EscapeForCMake(value); } os << ")\n"; diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index bd098a5..14e9e56 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -14,7 +14,7 @@ #include "cmSystemTools.h" #include "cmMakefile.h" #include "cmState.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmCommandArgumentLexer.h" @@ -141,8 +141,9 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) { std::ostringstream msg; cmListFileContext lfc; - lfc.FilePath = this->Makefile->GetLocalGenerator() - ->Convert(this->FileName, cmLocalGenerator::HOME); + cmOutputConverter converter(this->Makefile->GetStateSnapshot()); + lfc.FilePath = converter.Convert(this->FileName, + cmOutputConverter::HOME); lfc.Line = this->FileLine; msg << "uninitialized variable \'" << var << "\'"; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index e6cbe60..1f3046a 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -16,7 +16,7 @@ #include "cmGlobalGenerator.h" #include "cmState.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmMakefile.h" #include "cmTarget.h" #include "cmake.h" @@ -246,7 +246,6 @@ cmComputeLinkInformation // Store context information. this->Target = target; this->Makefile = this->Target->GetMakefile(); - this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance(); @@ -1395,7 +1394,8 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) // Add the item using the -framework option. this->Items.push_back(Item("-framework", false)); - fw = this->LocalGenerator->EscapeForShell(fw); + cmOutputConverter converter(this->Makefile->GetStateSnapshot()); + fw = converter.EscapeForShell(fw); this->Items.push_back(Item(fw, false)); } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index ccf520b..3afbb92 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -18,7 +18,6 @@ class cmake; class cmGlobalGenerator; -class cmLocalGenerator; class cmMakefile; class cmTarget; class cmOrderDirectories; @@ -75,7 +74,6 @@ private: // Context information. cmTarget const* Target; cmMakefile* Makefile; - cmLocalGenerator* LocalGenerator; cmGlobalGenerator* GlobalGenerator; cmake* CMakeInstance; diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index dd276a8..e1e1a5c 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -11,7 +11,7 @@ ============================================================================*/ #include "cmCoreTryCompile.h" #include "cmake.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmGlobalGenerator.h" #include "cmAlgorithms.h" #include "cmExportTryCompileFileGenerator.h" @@ -322,7 +322,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) std::string langFlags = "CMAKE_" + *li + "_FLAGS"; const char* flags = this->Makefile->GetDefinition(langFlags); fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li->c_str(), - cmLocalGenerator::EscapeForCMake(flags?flags:"").c_str()); + cmOutputConverter::EscapeForCMake(flags?flags:"").c_str()); fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}" " ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str()); } @@ -355,7 +355,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) const char* exeLinkFlags = this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS"); fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n", - cmLocalGenerator::EscapeForCMake( + cmOutputConverter::EscapeForCMake( exeLinkFlags ? exeLinkFlags : "").c_str()); } break; } diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index d23f815..11308c6 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -13,13 +13,13 @@ #include "cmMakefile.h" #include "cmCustomCommand.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmGeneratorExpression.h" //---------------------------------------------------------------------------- cmCustomCommandGenerator::cmCustomCommandGenerator( cmCustomCommand const& cc, const std::string& config, cmMakefile* mf): - CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()), + CC(cc), Config(config), Makefile(mf), OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()), GE(new cmGeneratorExpression(&cc.GetBacktrace())), DependsDone(false) { @@ -96,7 +96,8 @@ cmCustomCommandGenerator } else { - cmd += this->LG->EscapeForShell(arg, this->MakeVars); + cmOutputConverter converter(this->Makefile->GetStateSnapshot()); + cmd += converter.EscapeForShell(arg, this->MakeVars); } } } diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index b4ae014..7ad95d1 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -16,7 +16,6 @@ class cmCustomCommand; class cmMakefile; -class cmLocalGenerator; class cmGeneratorExpression; class cmCustomCommandGenerator @@ -24,7 +23,6 @@ class cmCustomCommandGenerator cmCustomCommand const& CC; std::string Config; cmMakefile* Makefile; - cmLocalGenerator* LG; bool OldStyle; bool MakeVars; cmGeneratorExpression* GE; diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 8854c36..b6c5fde 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -13,7 +13,6 @@ #define _cmDocumentation_h #include "cmStandardIncludes.h" -#include "cmProperty.h" #include "cmDocumentationFormatter.h" #include "cmDocumentationSection.h" #include "cmake.h" diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index eb8d193..dfb991b 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -99,8 +99,6 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget const* target, || i->first.find("IMPORTED_LINK_DEPENDENT_LIBRARIES") == 0 || i->first.find("INTERFACE_LINK_LIBRARIES") == 0) { - const std::string libs = i->second.GetValue(); - std::string evalResult = this->FindTargets(i->first, target, emitted); @@ -118,6 +116,7 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget const* target, } } } + std::string cmExportTryCompileFileGenerator::InstallNameDir(cmTarget* target, const std::string& config) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index e2b8c45..67d0d54 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -353,6 +353,34 @@ void cmGeneratorTarget::ComputeObjectMapping() } //---------------------------------------------------------------------------- +const char* cmGeneratorTarget::GetFeature(const std::string& feature, + const std::string& config) const +{ + if(!config.empty()) + { + std::string featureConfig = feature; + featureConfig += "_"; + featureConfig += cmSystemTools::UpperCase(config); + if(const char* value = this->Target->GetProperty(featureConfig)) + { + return value; + } + } + if(const char* value = this->Target->GetProperty(feature)) + { + return value; + } + return this->LocalGenerator->GetFeature(feature, config); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature, + const std::string& config) const +{ + return cmSystemTools::IsOn(this->GetFeature(feature, config)); +} + +//---------------------------------------------------------------------------- const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) { this->ComputeObjectMapping(); @@ -983,7 +1011,7 @@ cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang, case cmTarget::STATIC_LIBRARY: { std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY"; - if(this->Target->GetFeatureAsBool( + if(this->GetFeatureAsBool( "INTERPROCEDURAL_OPTIMIZATION", config)) { std::string varIPO = var + "_IPO"; diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index c79aa72..a8edcb8 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -67,6 +67,11 @@ public: void ComputeObjectMapping(); + const char* GetFeature(const std::string& feature, + const std::string& config) const; + bool GetFeatureAsBool(const std::string& feature, + const std::string& config) const; + cmTarget* Target; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx index 6717035..a460ca6 100644 --- a/Source/cmGetCMakePropertyCommand.cxx +++ b/Source/cmGetCMakePropertyCommand.cxx @@ -32,8 +32,7 @@ bool cmGetCMakePropertyCommand if ( args[1] == "VARIABLES" ) { - int cacheonly = 0; - std::vector<std::string> vars = this->Makefile->GetDefinitions(cacheonly); + std::vector<std::string> vars = this->Makefile->GetDefinitions(); if (!vars.empty()) { output = cmJoin(vars, ";"); diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index a242046..f453da1 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -15,6 +15,7 @@ #include "cmGeneratedFileStream.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmUuid.h" #include "cmake.h" #include <cmsys/Encoding.hxx> @@ -953,14 +954,15 @@ std::string cmGlobalVisualStudio7Generator::GetGUID(std::string const& name) std::string input = this->CMakeInstance->GetState()->GetBinaryDirectory(); input += "|"; input += name; - std::string md5 = cmSystemTools::ComputeStringMD5(input); - assert(md5.length() == 32); - std::string const& guid = - (md5.substr( 0,8)+"-"+ - md5.substr( 8,4)+"-"+ - md5.substr(12,4)+"-"+ - md5.substr(16,4)+"-"+ - md5.substr(20,12)); + + cmUuid uuidGenerator; + + std::vector<unsigned char> uuidNamespace; + uuidGenerator.StringToBinary( + "ee30c4be-5192-4fb0-b335-722a2dffe760", uuidNamespace); + + std::string guid = uuidGenerator.FromMd5(uuidNamespace, input); + return cmSystemTools::UpperCase(guid); } @@ -1023,12 +1025,13 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( { return activeConfigs; } + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); // inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties for(std::vector<std::string>::const_iterator i = configs.begin(); i != configs.end(); ++i) { const char* propertyValue = - target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str()); + gt->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str()); if(cmSystemTools::IsOff(propertyValue)) { activeConfigs.insert(*i); diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 7c4792c..20448c1 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -27,7 +27,7 @@ static std::string cmIfCommandError( i != args.end(); ++i) { err += " "; - err += cmLocalGenerator::EscapeForCMake(i->GetValue()); + err += cmOutputConverter::EscapeForCMake(i->GetValue()); } err += "\n"; return err; diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h new file mode 100644 index 0000000..d2339c4 --- /dev/null +++ b/Source/cmLinkedTree.h @@ -0,0 +1,164 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Stephen Kelly <steveire@gmail.com> + + 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. +============================================================================*/ +#ifndef cmLinkedTree_h +#define cmLinkedTree_h + +#include "cmStandardIncludes.h" + +#include <assert.h> + +/** + @brief A adaptor for traversing a tree structure in a vector + + This class is not intended to be wholly generic like a standard library + container adaptor. Mostly it exists to facilitate code sharing for the + needs of the cmState. For example, the Truncate() method is a specific + requirement of the cmState. + + An empty cmLinkedTree provides a Root() method, and an Extend() method, + each of which return iterators. A Tree can be built up by extending + from the root, and then extending from any other iterator. + + An iterator resulting from this tree construction can be + forward-only-iterated toward the root. Extending the tree never + invalidates existing iterators. + */ +template<typename T> +class cmLinkedTree +{ + typedef typename std::vector<T>::size_type PositionType; + typedef T* PointerType; + typedef T& ReferenceType; +public: + class iterator : public std::iterator<std::forward_iterator_tag, T> + { + friend class cmLinkedTree; + cmLinkedTree* Tree; + + // The Position is always 'one past the end'. + PositionType Position; + + iterator(cmLinkedTree* tree, PositionType pos) + : Tree(tree), Position(pos) + { + + } + + public: + iterator() + : Tree(0), Position(0) + { + + } + + void operator++() + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + this->Position = this->Tree->UpPositions[this->Position - 1]; + } + + PointerType operator->() const + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + return this->Tree->GetPointer(this->Position - 1); + } + + PointerType operator->() + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + return this->Tree->GetPointer(this->Position - 1); + } + + bool operator==(iterator other) const + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Tree == other.Tree); + return this->Position == other.Position; + } + + bool operator!=(iterator other) const + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + return !(*this == other); + } + + bool IsValid() const + { + if (!this->Tree) + { + return false; + } + return this->Position <= this->Tree->Data.size(); + } + }; + + iterator Root() const + { + return iterator(const_cast<cmLinkedTree*>(this), 0); + } + + iterator Extend(iterator it) + { + return Extend_impl(it, T()); + } + + iterator Extend(iterator it, T t) + { + return Extend_impl(it, t); + } + + iterator Truncate() + { + assert(this->UpPositions.size() > 0); + this->UpPositions.erase(this->UpPositions.begin() + 1, + this->UpPositions.end()); + assert(this->Data.size() > 0); + this->Data.erase(this->Data.begin() + 1, this->Data.end()); + return iterator(this, 1); + } + +private: + T& GetReference(PositionType pos) + { + return this->Data[pos]; + } + + T* GetPointer(PositionType pos) + { + return &this->Data[pos]; + } + + iterator Extend_impl(iterator it, T t) + { + assert(this->UpPositions.size() == this->Data.size()); + assert(it.Position <= this->UpPositions.size()); + this->UpPositions.push_back(it.Position); + this->Data.push_back(t); + return iterator(this, this->UpPositions.size()); + } + + std::vector<T> Data; + std::vector<PositionType> UpPositions; +}; + +#endif diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index ffe1a1f..ca58314 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -412,9 +412,9 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) return; } + cmOutputConverter converter(this->Snapshot); cmListFileContext lfc = this->front(); - lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath, - cmLocalGenerator::HOME); + lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); out << (lfc.Line ? " at " : " in ") << lfc; } @@ -425,13 +425,13 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) return; } + cmOutputConverter converter(this->Snapshot); const_iterator i = this->begin() + 1; out << "Call Stack (most recent call first):\n"; while(i != this->end()) { cmListFileContext lfc = *i; - lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath, - cmLocalGenerator::HOME); + lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); out << " " << lfc << "\n"; ++i; } diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 1971862a..4002d94 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -14,7 +14,7 @@ #include "cmStandardIncludes.h" -class cmLocalGenerator; +#include "cmState.h" /** \class cmListFileCache * \brief A class to cache list file contents. @@ -74,8 +74,8 @@ struct cmListFileFunction: public cmListFileContext class cmListFileBacktrace: private std::vector<cmListFileContext> { public: - cmListFileBacktrace(cmLocalGenerator* localGen = 0) - : LocalGenerator(localGen) + cmListFileBacktrace(cmState::Snapshot snapshot = cmState::Snapshot()) + : Snapshot(snapshot) { } @@ -84,7 +84,7 @@ class cmListFileBacktrace: private std::vector<cmListFileContext> void PrintTitle(std::ostream& out); void PrintCallStack(std::ostream& out); private: - cmLocalGenerator* LocalGenerator; + cmState::Snapshot Snapshot; }; struct cmListFile diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index da95a4d..5ed53d0 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -46,7 +46,7 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, cmState::Snapshot snapshot) - : StateSnapshot(snapshot) + : cmOutputConverter(snapshot), StateSnapshot(snapshot) { assert(snapshot.IsValid()); this->GlobalGenerator = gg; @@ -58,7 +58,6 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, this->Makefile = new cmMakefile(this); - this->LinkScriptShell = false; this->EmitUniversalBinaryFlags = true; this->BackwardsCompatibility = 0; this->BackwardsCompatibilityFinal = false; @@ -1097,58 +1096,6 @@ void cmLocalGenerator::InsertRuleLauncher(std::string& s, cmTarget* target, //---------------------------------------------------------------------------- std::string -cmLocalGenerator::ConvertToOutputForExistingCommon(const std::string& remote, - std::string const& result, - OutputFormat format) -{ - // If this is a windows shell, the result has a space, and the path - // already exists, we can use a short-path to reference it without a - // space. - if(this->GetState()->UseWindowsShell() && result.find(' ') != result.npos && - cmSystemTools::FileExists(remote.c_str())) - { - std::string tmp; - if(cmSystemTools::GetShortPath(remote, tmp)) - { - return this->ConvertToOutputFormat(tmp, format); - } - } - - // Otherwise, leave it unchanged. - return result; -} - -//---------------------------------------------------------------------------- -std::string -cmLocalGenerator::ConvertToOutputForExisting(const std::string& remote, - RelativeRoot local, - OutputFormat format) -{ - static_cast<void>(local); - - // Perform standard conversion. - std::string result = this->ConvertToOutputFormat(remote, format); - - // Consider short-path. - return this->ConvertToOutputForExistingCommon(remote, result, format); -} - -//---------------------------------------------------------------------------- -std::string -cmLocalGenerator::ConvertToOutputForExisting(RelativeRoot remote, - const std::string& local, - OutputFormat format) -{ - // Perform standard conversion. - std::string result = this->Convert(remote, local, format, true); - - // Consider short-path. - const char* remotePath = this->GetRelativeRootPath(remote); - return this->ConvertToOutputForExistingCommon(remotePath, result, format); -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::ConvertToIncludeReference(std::string const& path, OutputFormat format, bool forceFullPaths) @@ -2573,6 +2520,33 @@ void cmLocalGenerator::AppendFeatureOptions( } //---------------------------------------------------------------------------- +const char* cmLocalGenerator::GetFeature(const std::string& feature, + const std::string& config) +{ + // TODO: Define accumulation policy for features (prepend, append, replace). + // Currently we always replace. + if(!config.empty()) + { + std::string featureConfig = feature; + featureConfig += "_"; + featureConfig += cmSystemTools::UpperCase(config); + if(const char* value = this->Makefile->GetProperty(featureConfig)) + { + return value; + } + } + if(const char* value = this->Makefile->GetProperty(feature)) + { + return value; + } + if(cmLocalGenerator* parent = this->GetParent()) + { + return parent->GetFeature(feature, config); + } + return 0; +} + +//---------------------------------------------------------------------------- std::string cmLocalGenerator::ConstructComment(cmCustomCommandGenerator const& ccg, const char* default_comment) @@ -2604,230 +2578,6 @@ cmLocalGenerator::ConstructComment(cmCustomCommandGenerator const& ccg, } //---------------------------------------------------------------------------- -const char* cmLocalGenerator::GetRelativeRootPath(RelativeRoot relroot) -{ - switch (relroot) - { - case HOME: return this->GetState()->GetSourceDirectory(); - case START: return this->StateSnapshot.GetCurrentSourceDirectory(); - case HOME_OUTPUT: return this->GetState()->GetBinaryDirectory(); - case START_OUTPUT: return this->StateSnapshot.GetCurrentBinaryDirectory(); - default: break; - } - return 0; -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::Convert(const std::string& source, - RelativeRoot relative, - OutputFormat output) -{ - // Convert the path to a relative path. - std::string result = source; - - switch (relative) - { - case HOME: - //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath( - this->GetState()->GetSourceDirectoryComponents(), result); - break; - case START: - //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath( - this->StateSnapshot.GetCurrentSourceDirectoryComponents(), result); - break; - case HOME_OUTPUT: - //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath( - this->GetState()->GetBinaryDirectoryComponents(), result); - break; - case START_OUTPUT: - //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath( - this->StateSnapshot.GetCurrentBinaryDirectoryComponents(), result); - break; - case FULL: - result = cmSystemTools::CollapseFullPath(result); - break; - case NONE: - break; - - } - return this->ConvertToOutputFormat(result, output); -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source, - OutputFormat output) -{ - std::string result = source; - // Convert it to an output path. - if (output == MAKERULE) - { - result = cmSystemTools::ConvertToOutputPath(result.c_str()); - } - else if(output == SHELL || output == WATCOMQUOTE) - { - // For the MSYS shell convert drive letters to posix paths, so - // that c:/some/path becomes /c/some/path. This is needed to - // avoid problems with the shell path translation. - if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell) - { - if(result.size() > 2 && result[1] == ':') - { - result[1] = result[0]; - result[0] = '/'; - } - } - if(this->GetState()->UseWindowsShell()) - { - std::replace(result.begin(), result.end(), '/', '\\'); - } - result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE); - } - else if(output == RESPONSE) - { - result = this->EscapeForShell(result, false, false, false); - } - return result; -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::Convert(RelativeRoot remote, - const std::string& local, - OutputFormat output, bool optional) -{ - const char* remotePath = this->GetRelativeRootPath(remote); - - // The relative root must have a path (i.e. not FULL or NONE) - assert(remotePath != 0); - - if(!local.empty() && !optional) - { - std::vector<std::string> components; - cmSystemTools::SplitPath(local, components); - std::string result = this->ConvertToRelativePath(components, remotePath); - return this->ConvertToOutputFormat(result, output); - } - else - { - return this->ConvertToOutputFormat(remotePath, output); - } -} - -//---------------------------------------------------------------------------- -static bool cmLocalGeneratorNotAbove(const char* a, const char* b) -{ - return (cmSystemTools::ComparePath(a, b) || - cmSystemTools::IsSubDirectory(a, b)); -} - -//---------------------------------------------------------------------------- -std::string -cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local, - const std::string& in_remote, - bool force) -{ - // The path should never be quoted. - assert(in_remote[0] != '\"'); - - // The local path should never have a trailing slash. - assert(!local.empty() && !(local[local.size()-1] == "")); - - // If the path is already relative then just return the path. - if(!cmSystemTools::FileIsFullPath(in_remote.c_str())) - { - return in_remote; - } - - if(!force) - { - // Skip conversion if the path and local are not both in the source - // or both in the binary tree. - std::string local_path = cmSystemTools::JoinPath(local); - if(!((cmLocalGeneratorNotAbove(local_path.c_str(), - this->StateSnapshot.GetRelativePathTopBinary()) && - cmLocalGeneratorNotAbove(in_remote.c_str(), - this->StateSnapshot.GetRelativePathTopBinary())) || - (cmLocalGeneratorNotAbove(local_path.c_str(), - this->StateSnapshot.GetRelativePathTopSource()) && - cmLocalGeneratorNotAbove(in_remote.c_str(), - this->StateSnapshot.GetRelativePathTopSource())))) - { - return in_remote; - } - } - - // Identify the longest shared path component between the remote - // path and the local path. - std::vector<std::string> remote; - cmSystemTools::SplitPath(in_remote, remote); - unsigned int common=0; - while(common < remote.size() && - common < local.size() && - cmSystemTools::ComparePath(remote[common], - local[common])) - { - ++common; - } - - // If no part of the path is in common then return the full path. - if(common == 0) - { - return in_remote; - } - - // If the entire path is in common then just return a ".". - if(common == remote.size() && - common == local.size()) - { - return "."; - } - - // If the entire path is in common except for a trailing slash then - // just return a "./". - if(common+1 == remote.size() && - remote[common].empty() && - common == local.size()) - { - return "./"; - } - - // Construct the relative path. - std::string relative; - - // First add enough ../ to get up to the level of the shared portion - // of the path. Leave off the trailing slash. Note that the last - // component of local will never be empty because local should never - // have a trailing slash. - for(unsigned int i=common; i < local.size(); ++i) - { - relative += ".."; - if(i < local.size()-1) - { - relative += "/"; - } - } - - // Now add the portion of the destination path that is not included - // in the shared portion of the path. Add a slash the first time - // only if there was already something in the path. If there was a - // trailing slash in the input then the last iteration of the loop - // will add a slash followed by an empty string which will preserve - // the trailing slash in the output. - - if(!relative.empty() && !remote.empty()) - { - relative += "/"; - } - relative += cmJoin(cmRange(remote).advance(common), "/"); - - // Finally return the path. - return relative; -} - -//---------------------------------------------------------------------------- class cmInstallTargetGeneratorLocal: public cmInstallTargetGenerator { public: @@ -3220,150 +2970,6 @@ cmLocalGenerator } //---------------------------------------------------------------------------- -static bool cmLocalGeneratorIsShellOperator(const std::string& str) -{ - static std::set<std::string> shellOperators; - if(shellOperators.empty()) - { - shellOperators.insert("<"); - shellOperators.insert(">"); - shellOperators.insert("<<"); - shellOperators.insert(">>"); - shellOperators.insert("|"); - shellOperators.insert("||"); - shellOperators.insert("&&"); - shellOperators.insert("&>"); - shellOperators.insert("1>"); - shellOperators.insert("2>"); - shellOperators.insert("2>&1"); - shellOperators.insert("1>&2"); - } - return shellOperators.count(str) > 0; -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::EscapeForShell(const std::string& str, - bool makeVars, - bool forEcho, - bool useWatcomQuote) -{ - // Do not escape shell operators. - if(cmLocalGeneratorIsShellOperator(str)) - { - return str; - } - - // Compute the flags for the target shell environment. - int flags = 0; - if(this->GetState()->UseWindowsVSIDE()) - { - flags |= cmsysSystem_Shell_Flag_VSIDE; - } - else if(!this->LinkScriptShell) - { - flags |= cmsysSystem_Shell_Flag_Make; - } - if(makeVars) - { - flags |= cmsysSystem_Shell_Flag_AllowMakeVariables; - } - if(forEcho) - { - flags |= cmsysSystem_Shell_Flag_EchoWindows; - } - if(useWatcomQuote) - { - flags |= cmsysSystem_Shell_Flag_WatcomQuote; - } - if(this->GetState()->UseWatcomWMake()) - { - flags |= cmsysSystem_Shell_Flag_WatcomWMake; - } - if(this->GetState()->UseMinGWMake()) - { - flags |= cmsysSystem_Shell_Flag_MinGWMake; - } - if(this->GetState()->UseNMake()) - { - flags |= cmsysSystem_Shell_Flag_NMake; - } - - // Compute the buffer size needed. - int size = (this->GetState()->UseWindowsShell() ? - cmsysSystem_Shell_GetArgumentSizeForWindows(str.c_str(), flags) : - cmsysSystem_Shell_GetArgumentSizeForUnix(str.c_str(), flags)); - - // Compute the shell argument itself. - std::vector<char> arg(size); - if(this->GetState()->UseWindowsShell()) - { - cmsysSystem_Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags); - } - else - { - cmsysSystem_Shell_GetArgumentForUnix(str.c_str(), &arg[0], flags); - } - return std::string(&arg[0]); -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::EscapeForCMake(const std::string& str) -{ - // Always double-quote the argument to take care of most escapes. - std::string result = "\""; - for(const char* c = str.c_str(); *c; ++c) - { - if(*c == '"') - { - // Escape the double quote to avoid ending the argument. - result += "\\\""; - } - else if(*c == '$') - { - // Escape the dollar to avoid expanding variables. - result += "\\$"; - } - else if(*c == '\\') - { - // Escape the backslash to avoid other escapes. - result += "\\\\"; - } - else - { - // Other characters will be parsed correctly. - result += *c; - } - } - result += "\""; - return result; -} - -//---------------------------------------------------------------------------- -cmLocalGenerator::FortranFormat -cmLocalGenerator::GetFortranFormat(const char* value) -{ - FortranFormat format = FortranFormatNone; - if(value && *value) - { - std::vector<std::string> fmt; - cmSystemTools::ExpandListArgument(value, fmt); - for(std::vector<std::string>::iterator fi = fmt.begin(); - fi != fmt.end(); ++fi) - { - if(*fi == "FIXED") - { - format = FortranFormatFixed; - } - if(*fi == "FREE") - { - format = FortranFormatFree; - } - } - } - return format; -} - -//---------------------------------------------------------------------------- std::string cmLocalGenerator::GetTargetDirectory(cmTarget const&) const { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 1359dd6..efdd487 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -14,6 +14,7 @@ #include "cmStandardIncludes.h" #include "cmState.h" +#include "cmOutputConverter.h" class cmMakefile; class cmGlobalGenerator; @@ -31,7 +32,7 @@ class cmCustomCommandGenerator; * platforms. This class should never be constructed directly. A * GlobalGenerator will create it and invoke the appropriate commands on it. */ -class cmLocalGenerator +class cmLocalGenerator : public cmOutputConverter { public: cmLocalGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, @@ -90,35 +91,6 @@ public: cmState* GetState() const; cmState::Snapshot GetStateSnapshot() const; - /** - * Convert something to something else. This is a centralized conversion - * routine used by the generators to handle relative paths and the like. - * The flags determine what is actually done. - * - * relative: treat the argument as a directory and convert it to make it - * relative or full or unchanged. If relative (HOME, START etc) then that - * specifies what it should be relative to. - * - * output: make the result suitable for output to a... - * - * optional: should any relative path operation be controlled by the rel - * path setting - */ - enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT }; - enum OutputFormat { UNCHANGED, MAKERULE, SHELL, WATCOMQUOTE, RESPONSE }; - std::string ConvertToOutputFormat(const std::string& source, - OutputFormat output); - std::string Convert(const std::string& remote, RelativeRoot local, - OutputFormat output = UNCHANGED); - std::string Convert(RelativeRoot remote, const std::string& local, - OutputFormat output = UNCHANGED, - bool optional = false); - - /** - * Get path for the specified relative root. - */ - const char* GetRelativeRootPath(RelativeRoot relroot); - ///! set/get the parent generator cmLocalGenerator* GetParent() const {return this->Parent;} @@ -179,6 +151,9 @@ public: void AppendFeatureOptions(std::string& flags, const std::string& lang, const char* feature); + const char* GetFeature(const std::string& feature, + const std::string& config); + /** \brief Get absolute path to dependency \a name * * Translate a dependency as given in CMake code to the name to @@ -194,17 +169,6 @@ public: bool GetRealDependency(const std::string& name, const std::string& config, std::string& dep); - ///! for existing files convert to output path and short path if spaces - std::string ConvertToOutputForExisting(const std::string& remote, - RelativeRoot local = START_OUTPUT, - OutputFormat format = SHELL); - - /** For existing path identified by RelativeRoot convert to output - path and short path if spaces. */ - std::string ConvertToOutputForExisting(RelativeRoot remote, - const std::string& local = "", - OutputFormat format = SHELL); - virtual std::string ConvertToIncludeReference(std::string const& path, OutputFormat format = SHELL, bool forceFullPaths = false); @@ -276,40 +240,6 @@ public: const char* FilterPrefix; }; - /** Set whether to treat conversions to SHELL as a link script shell. */ - void SetLinkScriptShell(bool b) { this->LinkScriptShell = b; } - - /** Escape the given string to be used as a command line argument in - the native build system shell. Optionally allow the build - system to replace make variable references. Optionally adjust - escapes for the special case of passing to the native echo - command. */ - std::string EscapeForShell(const std::string& str, bool makeVars = false, - bool forEcho = false, - bool useWatcomQuote = false); - - /** Escape the given string as an argument in a CMake script. */ - static std::string EscapeForCMake(const std::string& str); - - enum FortranFormat - { - FortranFormatNone, - FortranFormatFixed, - FortranFormatFree - }; - FortranFormat GetFortranFormat(const char* value); - - /** - * Convert the given remote path to a relative path with respect to - * the given local path. The local path must be given in component - * form (see SystemTools::SplitPath) without a trailing slash. The - * remote path must use forward slashes and not already be escaped - * or quoted. - */ - std::string ConvertToRelativePath(const std::vector<std::string>& local, - const std::string& remote, - bool force=false); - /** * Get the relative path from the generator output directory to a * per-target support directory. @@ -442,7 +372,6 @@ protected: std::set<cmTarget const*> WarnCMP0063; - bool LinkScriptShell; bool EmitUniversalBinaryFlags; // Hack for ExpandRuleVariable until object-oriented version is @@ -452,10 +381,6 @@ protected: cmIML_INT_uint64_t BackwardsCompatibility; bool BackwardsCompatibilityFinal; private: - std::string ConvertToOutputForExistingCommon(const std::string& remote, - std::string const& result, - OutputFormat format); - void AddSharedFlags(std::string& flags, const std::string& lang, bool shared); bool GetShouldUseOldFlags(bool shared, const std::string &lang) const; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index c9eea56..f1fd806 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1254,7 +1254,7 @@ cmLocalUnixMakefileGenerator3 f != files.end(); ++f) { std::string fc = this->Convert(*f,START_OUTPUT,UNCHANGED); - fout << " " << cmLocalGenerator::EscapeForCMake(fc) << "\n"; + fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n"; } fout << ")\n"; } @@ -2052,7 +2052,7 @@ void cmLocalUnixMakefileGenerator3 di != defines.end(); ++di) { cmakefileStream - << " " << cmLocalGenerator::EscapeForCMake(*di) << "\n"; + << " " << cmOutputConverter::EscapeForCMake(*di) << "\n"; } cmakefileStream << " )\n"; @@ -2106,7 +2106,7 @@ void cmLocalUnixMakefileGenerator3 tri != transformRules.end(); ++tri) { cmakefileStream << " " - << cmLocalGenerator::EscapeForCMake(*tri) << "\n"; + << cmOutputConverter::EscapeForCMake(*tri) << "\n"; } cmakefileStream << " )\n"; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index bc308f1..a8b163a 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -275,7 +275,7 @@ void cmMakefile::IssueMessage(cmake::MessageType t, //---------------------------------------------------------------------------- cmListFileBacktrace cmMakefile::GetBacktrace() const { - cmListFileBacktrace backtrace(this->GetLocalGenerator()); + cmListFileBacktrace backtrace(this->StateSnapshot); for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin(); i != this->CallStack.rend(); ++i) { @@ -288,7 +288,7 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const cmListFileBacktrace cmMakefile::GetBacktrace(cmListFileContext const& lfc) const { - cmListFileBacktrace backtrace(this->GetLocalGenerator()); + cmListFileBacktrace backtrace(this->StateSnapshot); backtrace.Append(lfc); for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin(); i != this->CallStack.rend(); ++i) @@ -2495,18 +2495,11 @@ const char* cmMakefile::GetSafeDefinition(const std::string& def) const return ret; } -std::vector<std::string> cmMakefile -::GetDefinitions(int cacheonly /* = 0 */) const +std::vector<std::string> cmMakefile::GetDefinitions() const { - std::vector<std::string> res; - if ( !cacheonly ) - { - res = this->Internal->ClosureKeys(); - } - std::vector<std::string> cacheKeys = - this->GetState()->GetCacheEntryKeys(); + std::vector<std::string> res = this->Internal->ClosureKeys(); + std::vector<std::string> cacheKeys = this->GetState()->GetCacheEntryKeys(); res.insert(res.end(), cacheKeys.begin(), cacheKeys.end()); - std::sort(res.begin(), res.end()); return res; } @@ -4163,14 +4156,14 @@ const char *cmMakefile::GetProperty(const std::string& prop, output = cmJoin(this->ListFileStack, ";"); return output.c_str(); } - else if (prop == "VARIABLES" || prop == "CACHE_VARIABLES") + else if ( prop == "CACHE_VARIABLES" ) { - int cacheonly = 0; - if ( prop == "CACHE_VARIABLES" ) - { - cacheonly = 1; - } - output = cmJoin(this->GetDefinitions(cacheonly), ";"); + output = cmJoin(this->GetState()->GetCacheEntryKeys(), ";"); + return output.c_str(); + } + else if (prop == "VARIABLES") + { + output = cmJoin(this->GetDefinitions(), ";"); return output.c_str(); } else if (prop == "MACROS") @@ -4261,33 +4254,6 @@ bool cmMakefile::GetPropertyAsBool(const std::string& prop) const return cmSystemTools::IsOn(this->GetProperty(prop)); } -//---------------------------------------------------------------------------- -const char* cmMakefile::GetFeature(const std::string& feature, - const std::string& config) -{ - // TODO: Define accumulation policy for features (prepend, append, replace). - // Currently we always replace. - if(!config.empty()) - { - std::string featureConfig = feature; - featureConfig += "_"; - featureConfig += cmSystemTools::UpperCase(config); - if(const char* value = this->GetProperty(featureConfig)) - { - return value; - } - } - if(const char* value = this->GetProperty(feature)) - { - return value; - } - if(cmLocalGenerator* parent = this->LocalGenerator->GetParent()) - { - return parent->GetMakefile()->GetFeature(feature, config); - } - return 0; -} - cmTarget* cmMakefile::FindTarget(const std::string& name, bool excludeAliases) const { @@ -4703,6 +4669,11 @@ void cmMakefile::StoreMatches(cmsys::RegularExpression& re) this->MarkVariableAsUsed(nMatchesVariable); } +cmState::Snapshot cmMakefile::GetStateSnapshot() const +{ + return this->StateSnapshot; +} + //---------------------------------------------------------------------------- cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id) const diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 32223b4..6f6ed27 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -509,7 +509,7 @@ public: * cacheonly is specified and is greater than 0, then only cache * variables will be listed. */ - std::vector<std::string> GetDefinitions(int cacheonly=0) const; + std::vector<std::string> GetDefinitions() const; /** * Test a boolean variable to see if it is true or false. @@ -718,9 +718,6 @@ public: const char *GetProperty(const std::string& prop, bool chain) const; bool GetPropertyAsBool(const std::string& prop) const; - const char* GetFeature(const std::string& feature, - const std::string& config); - // Get the properties cmPropertyMap &GetProperties() { return this->Properties; } @@ -839,6 +836,8 @@ public: void ClearMatches(); void StoreMatches(cmsys::RegularExpression& re); + cmState::Snapshot GetStateSnapshot() const; + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const std::string& name, cmTarget& target); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 9ac9ddb..923aa7b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1126,8 +1126,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() pi != this->MultipleOutputPairs.end(); ++pi) { *this->InfoFileStream - << " " << cmLocalGenerator::EscapeForCMake(pi->first) - << " " << cmLocalGenerator::EscapeForCMake(pi->second) + << " " << cmOutputConverter::EscapeForCMake(pi->first) + << " " << cmOutputConverter::EscapeForCMake(pi->second) << "\n"; } *this->InfoFileStream << " )\n\n"; @@ -2086,13 +2086,13 @@ void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) //---------------------------------------------------------------------------- const char* cmMakefileTargetGenerator::GetFeature(const std::string& feature) { - return this->Target->GetFeature(feature, this->ConfigName); + return this->GeneratorTarget->GetFeature(feature, this->ConfigName); } //---------------------------------------------------------------------------- bool cmMakefileTargetGenerator::GetFeatureAsBool(const std::string& feature) { - return this->Target->GetFeatureAsBool(feature, this->ConfigName); + return this->GeneratorTarget->GetFeatureAsBool(feature, this->ConfigName); } //---------------------------------------------------------------------------- diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 879d6b7..b2aef68 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -107,13 +107,14 @@ std::string cmNinjaTargetGenerator::LanguageCompilerRule( // TODO: Picked up from cmMakefileTargetGenerator. Refactor it. const char* cmNinjaTargetGenerator::GetFeature(const std::string& feature) { - return this->Target->GetFeature(feature, this->GetConfigName()); + return this->GeneratorTarget->GetFeature(feature, this->GetConfigName()); } // TODO: Picked up from cmMakefileTargetGenerator. Refactor it. bool cmNinjaTargetGenerator::GetFeatureAsBool(const std::string& feature) { - return this->Target->GetFeatureAsBool(feature, this->GetConfigName()); + return this->GeneratorTarget->GetFeatureAsBool(feature, + this->GetConfigName()); } // TODO: Picked up from cmMakefileTargetGenerator. Refactor it. diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx new file mode 100644 index 0000000..db73a34 --- /dev/null +++ b/Source/cmOutputConverter.cxx @@ -0,0 +1,447 @@ +/*============================================================================ + 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 "cmOutputConverter.h" + +#include "cmAlgorithms.h" +#include "cmake.h" + +#include <cmsys/System.h> + +#include <assert.h> + +cmOutputConverter::cmOutputConverter(cmState::Snapshot snapshot) + : StateSnapshot(snapshot), LinkScriptShell(false) +{ +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::ConvertToOutputForExistingCommon(const std::string& remote, + std::string const& result, + OutputFormat format) +{ + // If this is a windows shell, the result has a space, and the path + // already exists, we can use a short-path to reference it without a + // space. + if(this->GetState()->UseWindowsShell() && result.find(' ') != result.npos && + cmSystemTools::FileExists(remote.c_str())) + { + std::string tmp; + if(cmSystemTools::GetShortPath(remote, tmp)) + { + return this->ConvertToOutputFormat(tmp, format); + } + } + + // Otherwise, leave it unchanged. + return result; +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::ConvertToOutputForExisting(const std::string& remote, + RelativeRoot local, + OutputFormat format) +{ + static_cast<void>(local); + + // Perform standard conversion. + std::string result = this->ConvertToOutputFormat(remote, format); + + // Consider short-path. + return this->ConvertToOutputForExistingCommon(remote, result, format); +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::ConvertToOutputForExisting(RelativeRoot remote, + const std::string& local, + OutputFormat format) +{ + // Perform standard conversion. + std::string result = this->Convert(remote, local, format, true); + + // Consider short-path. + const char* remotePath = this->GetRelativeRootPath(remote); + return this->ConvertToOutputForExistingCommon(remotePath, result, format); +} + +//---------------------------------------------------------------------------- +const char* cmOutputConverter::GetRelativeRootPath(RelativeRoot relroot) +{ + switch (relroot) + { + case HOME: return this->GetState()->GetSourceDirectory(); + case START: return this->StateSnapshot.GetCurrentSourceDirectory(); + case HOME_OUTPUT: return this->GetState()->GetBinaryDirectory(); + case START_OUTPUT: return this->StateSnapshot.GetCurrentBinaryDirectory(); + default: break; + } + return 0; +} + +std::string cmOutputConverter::Convert(const std::string& source, + RelativeRoot relative, + OutputFormat output) +{ + // Convert the path to a relative path. + std::string result = source; + + switch (relative) + { + case HOME: + result = this->ConvertToRelativePath( + this->GetState()->GetSourceDirectoryComponents(), result); + break; + case START: + result = this->ConvertToRelativePath( + this->StateSnapshot.GetCurrentSourceDirectoryComponents(), result); + break; + case HOME_OUTPUT: + result = this->ConvertToRelativePath( + this->GetState()->GetBinaryDirectoryComponents(), result); + break; + case START_OUTPUT: + result = this->ConvertToRelativePath( + this->StateSnapshot.GetCurrentBinaryDirectoryComponents(), result); + break; + case FULL: + result = cmSystemTools::CollapseFullPath(result); + break; + case NONE: + break; + } + return this->ConvertToOutputFormat(result, output); +} + +//---------------------------------------------------------------------------- +std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source, + OutputFormat output) +{ + std::string result = source; + // Convert it to an output path. + if (output == MAKERULE) + { + result = cmSystemTools::ConvertToOutputPath(result.c_str()); + } + else if(output == SHELL || output == WATCOMQUOTE) + { + // For the MSYS shell convert drive letters to posix paths, so + // that c:/some/path becomes /c/some/path. This is needed to + // avoid problems with the shell path translation. + if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell) + { + if(result.size() > 2 && result[1] == ':') + { + result[1] = result[0]; + result[0] = '/'; + } + } + if(this->GetState()->UseWindowsShell()) + { + std::replace(result.begin(), result.end(), '/', '\\'); + } + result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE); + } + else if(output == RESPONSE) + { + result = this->EscapeForShell(result, false, false, false); + } + return result; +} + +//---------------------------------------------------------------------------- +std::string cmOutputConverter::Convert(RelativeRoot remote, + const std::string& local, + OutputFormat output, + bool optional) +{ + const char* remotePath = this->GetRelativeRootPath(remote); + + // The relative root must have a path (i.e. not FULL or NONE) + assert(remotePath != 0); + + if(!local.empty() && !optional) + { + std::vector<std::string> components; + cmSystemTools::SplitPath(local, components); + std::string result = this->ConvertToRelativePath(components, remotePath); + return this->ConvertToOutputFormat(result, output); + } + + return this->ConvertToOutputFormat(remotePath, output); +} + +//---------------------------------------------------------------------------- +static bool cmOutputConverterNotAbove(const char* a, const char* b) +{ + return (cmSystemTools::ComparePath(a, b) || + cmSystemTools::IsSubDirectory(a, b)); +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::ConvertToRelativePath(const std::vector<std::string>& local, + const std::string& in_remote, + bool force) +{ + // The path should never be quoted. + assert(in_remote[0] != '\"'); + + // The local path should never have a trailing slash. + assert(!local.empty() && !(local[local.size()-1] == "")); + + // If the path is already relative then just return the path. + if(!cmSystemTools::FileIsFullPath(in_remote.c_str())) + { + return in_remote; + } + + if(!force) + { + // Skip conversion if the path and local are not both in the source + // or both in the binary tree. + std::string local_path = cmSystemTools::JoinPath(local); + if(!((cmOutputConverterNotAbove(local_path.c_str(), + this->StateSnapshot.GetRelativePathTopBinary()) && + cmOutputConverterNotAbove(in_remote.c_str(), + this->StateSnapshot.GetRelativePathTopBinary())) || + (cmOutputConverterNotAbove(local_path.c_str(), + this->StateSnapshot.GetRelativePathTopSource()) && + cmOutputConverterNotAbove(in_remote.c_str(), + this->StateSnapshot.GetRelativePathTopSource())))) + { + return in_remote; + } + } + + // Identify the longest shared path component between the remote + // path and the local path. + std::vector<std::string> remote; + cmSystemTools::SplitPath(in_remote, remote); + unsigned int common=0; + while(common < remote.size() && + common < local.size() && + cmSystemTools::ComparePath(remote[common], + local[common])) + { + ++common; + } + + // If no part of the path is in common then return the full path. + if(common == 0) + { + return in_remote; + } + + // If the entire path is in common then just return a ".". + if(common == remote.size() && + common == local.size()) + { + return "."; + } + + // If the entire path is in common except for a trailing slash then + // just return a "./". + if(common+1 == remote.size() && + remote[common].empty() && + common == local.size()) + { + return "./"; + } + + // Construct the relative path. + std::string relative; + + // First add enough ../ to get up to the level of the shared portion + // of the path. Leave off the trailing slash. Note that the last + // component of local will never be empty because local should never + // have a trailing slash. + for(unsigned int i=common; i < local.size(); ++i) + { + relative += ".."; + if(i < local.size()-1) + { + relative += "/"; + } + } + + // Now add the portion of the destination path that is not included + // in the shared portion of the path. Add a slash the first time + // only if there was already something in the path. If there was a + // trailing slash in the input then the last iteration of the loop + // will add a slash followed by an empty string which will preserve + // the trailing slash in the output. + + if(!relative.empty() && !remote.empty()) + { + relative += "/"; + } + relative += cmJoin(cmRange(remote).advance(common), "/"); + + // Finally return the path. + return relative; +} + +//---------------------------------------------------------------------------- +static bool cmOutputConverterIsShellOperator(const std::string& str) +{ + static std::set<std::string> shellOperators; + if(shellOperators.empty()) + { + shellOperators.insert("<"); + shellOperators.insert(">"); + shellOperators.insert("<<"); + shellOperators.insert(">>"); + shellOperators.insert("|"); + shellOperators.insert("||"); + shellOperators.insert("&&"); + shellOperators.insert("&>"); + shellOperators.insert("1>"); + shellOperators.insert("2>"); + shellOperators.insert("2>&1"); + shellOperators.insert("1>&2"); + } + return shellOperators.count(str) > 0; +} + +//---------------------------------------------------------------------------- +std::string cmOutputConverter::EscapeForShell(const std::string& str, + bool makeVars, + bool forEcho, + bool useWatcomQuote) +{ + // Do not escape shell operators. + if(cmOutputConverterIsShellOperator(str)) + { + return str; + } + + // Compute the flags for the target shell environment. + int flags = 0; + if(this->GetState()->UseWindowsVSIDE()) + { + flags |= cmsysSystem_Shell_Flag_VSIDE; + } + else if(!this->LinkScriptShell) + { + flags |= cmsysSystem_Shell_Flag_Make; + } + if(makeVars) + { + flags |= cmsysSystem_Shell_Flag_AllowMakeVariables; + } + if(forEcho) + { + flags |= cmsysSystem_Shell_Flag_EchoWindows; + } + if(useWatcomQuote) + { + flags |= cmsysSystem_Shell_Flag_WatcomQuote; + } + if(this->GetState()->UseWatcomWMake()) + { + flags |= cmsysSystem_Shell_Flag_WatcomWMake; + } + if(this->GetState()->UseMinGWMake()) + { + flags |= cmsysSystem_Shell_Flag_MinGWMake; + } + if(this->GetState()->UseNMake()) + { + flags |= cmsysSystem_Shell_Flag_NMake; + } + + // Compute the buffer size needed. + int size = (this->GetState()->UseWindowsShell() ? + cmsysSystem_Shell_GetArgumentSizeForWindows(str.c_str(), flags) : + cmsysSystem_Shell_GetArgumentSizeForUnix(str.c_str(), flags)); + + // Compute the shell argument itself. + std::vector<char> arg(size); + if(this->GetState()->UseWindowsShell()) + { + cmsysSystem_Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags); + } + else + { + cmsysSystem_Shell_GetArgumentForUnix(str.c_str(), &arg[0], flags); + } + return std::string(&arg[0]); +} + +//---------------------------------------------------------------------------- +std::string cmOutputConverter::EscapeForCMake(const std::string& str) +{ + // Always double-quote the argument to take care of most escapes. + std::string result = "\""; + for(const char* c = str.c_str(); *c; ++c) + { + if(*c == '"') + { + // Escape the double quote to avoid ending the argument. + result += "\\\""; + } + else if(*c == '$') + { + // Escape the dollar to avoid expanding variables. + result += "\\$"; + } + else if(*c == '\\') + { + // Escape the backslash to avoid other escapes. + result += "\\\\"; + } + else + { + // Other characters will be parsed correctly. + result += *c; + } + } + result += "\""; + return result; +} + +//---------------------------------------------------------------------------- +cmOutputConverter::FortranFormat +cmOutputConverter::GetFortranFormat(const char* value) +{ + FortranFormat format = FortranFormatNone; + if(value && *value) + { + std::vector<std::string> fmt; + cmSystemTools::ExpandListArgument(value, fmt); + for(std::vector<std::string>::iterator fi = fmt.begin(); + fi != fmt.end(); ++fi) + { + if(*fi == "FIXED") + { + format = FortranFormatFixed; + } + if(*fi == "FREE") + { + format = FortranFormatFree; + } + } + } + return format; +} + +void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell) +{ + this->LinkScriptShell = linkScriptShell; +} + +cmState* cmOutputConverter::GetState() const +{ + return this->StateSnapshot.GetState(); +} diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h new file mode 100644 index 0000000..1d3f8c7 --- /dev/null +++ b/Source/cmOutputConverter.h @@ -0,0 +1,106 @@ +/*============================================================================ + 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. +============================================================================*/ +#ifndef cmOutputConverter_h +#define cmOutputConverter_h + +#include "cmStandardIncludes.h" + +#include "cmGlobalGenerator.h" +#include "cmState.h" + +class cmOutputConverter +{ +public: + cmOutputConverter(cmState::Snapshot snapshot); + + /** + * Convert something to something else. This is a centralized conversion + * routine used by the generators to handle relative paths and the like. + * The flags determine what is actually done. + * + * relative: treat the argument as a directory and convert it to make it + * relative or full or unchanged. If relative (HOME, START etc) then that + * specifies what it should be relative to. + * + * output: make the result suitable for output to a... + * + * optional: should any relative path operation be controlled by the rel + * path setting + */ + enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT }; + enum OutputFormat { UNCHANGED, MAKERULE, SHELL, WATCOMQUOTE, RESPONSE }; + std::string ConvertToOutputFormat(const std::string& source, + OutputFormat output); + std::string Convert(const std::string& remote, RelativeRoot local, + OutputFormat output = UNCHANGED); + std::string Convert(RelativeRoot remote, const std::string& local, + OutputFormat output = UNCHANGED, + bool optional = false); + + /** + * Get path for the specified relative root. + */ + const char* GetRelativeRootPath(RelativeRoot relroot); + + ///! for existing files convert to output path and short path if spaces + std::string ConvertToOutputForExisting(const std::string& remote, + RelativeRoot local = START_OUTPUT, + OutputFormat format = SHELL); + + /** For existing path identified by RelativeRoot convert to output + path and short path if spaces. */ + std::string ConvertToOutputForExisting(RelativeRoot remote, + const std::string& local = "", + OutputFormat format = SHELL); + + void SetLinkScriptShell(bool linkScriptShell); + + std::string EscapeForShell(const std::string& str, + bool makeVars = false, + bool forEcho = false, + bool useWatcomQuote = false); + + static std::string EscapeForCMake(const std::string& str); + + enum FortranFormat + { + FortranFormatNone, + FortranFormatFixed, + FortranFormatFree + }; + static FortranFormat GetFortranFormat(const char* value); + + /** + * Convert the given remote path to a relative path with respect to + * the given local path. The local path must be given in component + * form (see SystemTools::SplitPath) without a trailing slash. The + * remote path must use forward slashes and not already be escaped + * or quoted. + */ + std::string ConvertToRelativePath(const std::vector<std::string>& local, + const std::string& in_remote, + bool force = false); + +private: + cmState* GetState() const; + + std::string ConvertToOutputForExistingCommon(const std::string& remote, + std::string const& result, + OutputFormat format); + +private: + cmState::Snapshot StateSnapshot; + + bool LinkScriptShell; +}; + +#endif diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index fbd2946..ef32c75 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -550,9 +550,9 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) std::string autogenTargetName = getAutogenTargetName(target); makefile->AddDefinition("_moc_target_name", - cmLocalGenerator::EscapeForCMake(autogenTargetName).c_str()); + cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); makefile->AddDefinition("_origin_target_name", - cmLocalGenerator::EscapeForCMake(target->GetName()).c_str()); + cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); std::string targetDir = getAutogenTargetDir(target); @@ -582,7 +582,7 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) this->SetupSourceFiles(target); } makefile->AddDefinition("_cpp_files", - cmLocalGenerator::EscapeForCMake(this->Sources).c_str()); + cmOutputConverter::EscapeForCMake(this->Sources).c_str()); if (target->GetPropertyAsBool("AUTOMOC")) { this->SetupAutoMocTarget(target, autogenTargetName, @@ -764,11 +764,11 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); std::string _moc_options = (tmp!=0 ? tmp : ""); makefile->AddDefinition("_moc_options", - cmLocalGenerator::EscapeForCMake(_moc_options).c_str()); + cmOutputConverter::EscapeForCMake(_moc_options).c_str()); makefile->AddDefinition("_skip_moc", - cmLocalGenerator::EscapeForCMake(this->SkipMoc).c_str()); + cmOutputConverter::EscapeForCMake(this->SkipMoc).c_str()); makefile->AddDefinition("_moc_headers", - cmLocalGenerator::EscapeForCMake(this->Headers).c_str()); + cmOutputConverter::EscapeForCMake(this->Headers).c_str()); bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); @@ -780,9 +780,9 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, _moc_incs, _moc_compile_defs); makefile->AddDefinition("_moc_incs", - cmLocalGenerator::EscapeForCMake(_moc_incs).c_str()); + cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); makefile->AddDefinition("_moc_compile_defs", - cmLocalGenerator::EscapeForCMake(_moc_compile_defs).c_str()); + cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); for (std::vector<std::string>::const_iterator li = configs.begin(); li != configs.end(); ++li) @@ -795,7 +795,7 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, if (config_moc_incs != _moc_incs) { configIncludes[*li] = - cmLocalGenerator::EscapeForCMake(config_moc_incs); + cmOutputConverter::EscapeForCMake(config_moc_incs); if(_moc_incs.empty()) { _moc_incs = config_moc_incs; @@ -804,7 +804,7 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, if (config_moc_compile_defs != _moc_compile_defs) { configDefines[*li] = - cmLocalGenerator::EscapeForCMake(config_moc_compile_defs); + cmOutputConverter::EscapeForCMake(config_moc_compile_defs); if(_moc_compile_defs.empty()) { _moc_compile_defs = config_moc_compile_defs; @@ -906,7 +906,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, skipped.insert(skipVec.begin(), skipVec.end()); makefile->AddDefinition("_skip_uic", - cmLocalGenerator::EscapeForCMake(this->SkipUic).c_str()); + cmOutputConverter::EscapeForCMake(this->SkipUic).c_str()); std::vector<cmSourceFile*> uiFilesWithOptions = makefile->GetQtUiFilesWithOptions(); @@ -920,7 +920,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, if (!_uic_opts.empty()) { - _uic_opts = cmLocalGenerator::EscapeForCMake(_uic_opts); + _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); } for (std::vector<std::string>::const_iterator li = configs.begin(); @@ -931,7 +931,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, if (config_uic_opts != _uic_opts) { configUicOptions[*li] = - cmLocalGenerator::EscapeForCMake(config_uic_opts); + cmOutputConverter::EscapeForCMake(config_uic_opts); if(_uic_opts.empty()) { _uic_opts = config_uic_opts; @@ -966,9 +966,9 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, } makefile->AddDefinition("_qt_uic_options_files", - cmLocalGenerator::EscapeForCMake(uiFileFiles).c_str()); + cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); makefile->AddDefinition("_qt_uic_options_options", - cmLocalGenerator::EscapeForCMake(uiFileOptions).c_str()); + cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); std::string targetName = target->GetName(); if (strcmp(qtVersion, "5") == 0) @@ -1141,15 +1141,15 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target) } } makefile->AddDefinition("_qt_rcc_inputs_" + target->GetName(), - cmLocalGenerator::EscapeForCMake(qrcInputs).c_str()); + cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); makefile->AddDefinition("_rcc_files", - cmLocalGenerator::EscapeForCMake(_rcc_files).c_str()); + cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); makefile->AddDefinition("_qt_rcc_options_files", - cmLocalGenerator::EscapeForCMake(rccFileFiles).c_str()); + cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); makefile->AddDefinition("_qt_rcc_options_options", - cmLocalGenerator::EscapeForCMake(rccFileOptions).c_str()); + cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); makefile->AddDefinition("_qt_rcc_executable", this->GetRccExecutable(target).c_str()); @@ -1434,7 +1434,7 @@ cmQtAutoGenerators::WriteOldMocDefinitionsFile( outfile.open(filename.c_str(), std::ios::trunc); outfile << "set(AM_OLD_COMPILE_SETTINGS " - << cmLocalGenerator::EscapeForCMake( + << cmOutputConverter::EscapeForCMake( this->CurrentCompileSettingsStr) << ")\n"; outfile.close(); diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 25b4966..a13c13f 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -18,6 +18,30 @@ #include <assert.h> +struct cmState::SnapshotDataType +{ + cmState::PositionType DirectoryParent; + cmState::SnapshotType SnapshotType; + cmLinkedTree<cmState::BuildsystemDirectoryStateType>::iterator + BuildSystemDirectory; +}; + +struct cmState::BuildsystemDirectoryStateType +{ + std::string Location; + std::string OutputLocation; + + std::vector<std::string> CurrentSourceDirectoryComponents; + std::vector<std::string> CurrentBinaryDirectoryComponents; + // The top-most directories for relative path conversion. Both the + // source and destination location of a relative path conversion + // must be underneath one of these directories (both under source or + // both under binary) in order for the relative path to be evaluated + // safely by the build tools. + std::string RelativePathTopSource; + std::string RelativePathTopBinary; +}; + cmState::cmState(cmake* cm) : CMakeInstance(cm), IsInTryCompile(false), @@ -200,29 +224,8 @@ void cmState::Reset() this->GlobalProperties.clear(); this->PropertyDefinitions.clear(); - assert(this->Locations.size() > 0); - assert(this->OutputLocations.size() > 0); - assert(this->ParentPositions.size() > 0); - assert(this->CurrentSourceDirectoryComponents.size() > 0); - assert(this->CurrentBinaryDirectoryComponents.size() > 0); - assert(this->RelativePathTopSource.size() > 0); - assert(this->RelativePathTopBinary.size() > 0); - - this->Locations.erase(this->Locations.begin() + 1, this->Locations.end()); - this->OutputLocations.erase(this->OutputLocations.begin() + 1, - this->OutputLocations.end()); - this->ParentPositions.erase(this->ParentPositions.begin() + 1, - this->ParentPositions.end()); - this->CurrentSourceDirectoryComponents.erase( - this->CurrentSourceDirectoryComponents.begin() + 1, - this->CurrentSourceDirectoryComponents.end()); - this->CurrentBinaryDirectoryComponents.erase( - this->CurrentBinaryDirectoryComponents.begin() + 1, - this->CurrentBinaryDirectoryComponents.end()); - this->RelativePathTopSource.erase(this->RelativePathTopSource.begin() + 1, - this->RelativePathTopSource.end()); - this->RelativePathTopBinary.erase(this->RelativePathTopBinary.begin() + 1, - this->RelativePathTopBinary.end()); + this->BuildsystemDirectory.Truncate(); + this->SnapshotData.Truncate(); this->DefineProperty ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, @@ -623,7 +626,7 @@ void cmState::Snapshot::ComputeRelativePathTopSource() result = currentSource; } } - this->State->RelativePathTopSource[this->Position] = result; + this->Position->BuildSystemDirectory->RelativePathTopSource = result; } void cmState::Snapshot::ComputeRelativePathTopBinary() @@ -662,24 +665,21 @@ void cmState::Snapshot::ComputeRelativePathTopBinary() // is a network path. if(result.size() < 2 || result.substr(0, 2) != "//") { - this->State->RelativePathTopBinary[this->Position] = result; + this->Position->BuildSystemDirectory->RelativePathTopBinary = result; } else { - this->State->RelativePathTopBinary[this->Position] = ""; + this->Position->BuildSystemDirectory->RelativePathTopBinary = ""; } } cmState::Snapshot cmState::CreateBaseSnapshot() { - PositionType pos = 0; - this->ParentPositions.push_back(pos); - this->Locations.resize(1); - this->OutputLocations.resize(1); - this->CurrentSourceDirectoryComponents.resize(1); - this->CurrentBinaryDirectoryComponents.resize(1); - this->RelativePathTopSource.resize(1); - this->RelativePathTopBinary.resize(1); + PositionType pos = this->SnapshotData.Extend(this->SnapshotData.Root()); + pos->DirectoryParent = this->SnapshotData.Root(); + pos->SnapshotType = BuildsystemDirectoryType; + pos->BuildSystemDirectory = + this->BuildsystemDirectory.Extend(this->BuildsystemDirectory.Root()); return cmState::Snapshot(this, pos); } @@ -687,16 +687,12 @@ cmState::Snapshot cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot) { assert(originSnapshot.IsValid()); - PositionType pos = this->ParentPositions.size(); - this->ParentPositions.push_back(originSnapshot.Position); - this->Locations.resize(this->Locations.size() + 1); - this->OutputLocations.resize(this->OutputLocations.size() + 1); - this->CurrentSourceDirectoryComponents.resize( - this->CurrentSourceDirectoryComponents.size() + 1); - this->CurrentBinaryDirectoryComponents.resize( - this->CurrentBinaryDirectoryComponents.size() + 1); - this->RelativePathTopSource.resize(this->RelativePathTopSource.size() + 1); - this->RelativePathTopBinary.resize(this->RelativePathTopBinary.size() + 1); + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position); + pos->DirectoryParent = originSnapshot.Position; + pos->SnapshotType = BuildsystemDirectoryType; + pos->BuildSystemDirectory = + this->BuildsystemDirectory.Extend( + originSnapshot.Position->BuildSystemDirectory); return cmState::Snapshot(this, pos); } @@ -709,92 +705,99 @@ cmState::Snapshot::Snapshot(cmState* state, PositionType position) const char* cmState::Snapshot::GetCurrentSourceDirectory() const { - return this->State->Locations[this->Position].c_str(); + return this->Position->BuildSystemDirectory->Location.c_str(); } void cmState::Snapshot::SetCurrentSourceDirectory(std::string const& dir) { assert(this->State); - assert(this->State->Locations.size() > this->Position); - this->State->Locations[this->Position] = dir; - cmSystemTools::ConvertToUnixSlashes( - this->State->Locations[this->Position]); - this->State->Locations[this->Position] = - cmSystemTools::CollapseFullPath(this->State->Locations[this->Position]); + std::string& loc = this->Position->BuildSystemDirectory->Location; + loc = dir; + cmSystemTools::ConvertToUnixSlashes(loc); + loc = cmSystemTools::CollapseFullPath(loc); cmSystemTools::SplitPath( - this->State->Locations[this->Position], - this->State->CurrentSourceDirectoryComponents[this->Position]); + loc, + this->Position->BuildSystemDirectory->CurrentSourceDirectoryComponents); this->ComputeRelativePathTopSource(); } const char* cmState::Snapshot::GetCurrentBinaryDirectory() const { - return this->State->OutputLocations[this->Position].c_str(); + return this->Position->BuildSystemDirectory->OutputLocation.c_str(); } void cmState::Snapshot::SetCurrentBinaryDirectory(std::string const& dir) { - assert(this->State->OutputLocations.size() > this->Position); - this->State->OutputLocations[this->Position] = dir; - cmSystemTools::ConvertToUnixSlashes( - this->State->OutputLocations[this->Position]); - this->State->OutputLocations[this->Position] = - cmSystemTools::CollapseFullPath( - this->State->OutputLocations[this->Position]); + std::string& loc = this->Position->BuildSystemDirectory->OutputLocation; + loc = dir; + cmSystemTools::ConvertToUnixSlashes(loc); + loc = cmSystemTools::CollapseFullPath(loc); cmSystemTools::SplitPath( - this->State->OutputLocations[this->Position], - this->State->CurrentBinaryDirectoryComponents[this->Position]); + loc, + this->Position->BuildSystemDirectory->CurrentBinaryDirectoryComponents); this->ComputeRelativePathTopBinary(); } std::vector<std::string> const& cmState::Snapshot::GetCurrentSourceDirectoryComponents() { - return this->State->CurrentSourceDirectoryComponents[this->Position]; + return this->Position->BuildSystemDirectory + ->CurrentSourceDirectoryComponents; } std::vector<std::string> const& cmState::Snapshot::GetCurrentBinaryDirectoryComponents() { - return this->State->CurrentBinaryDirectoryComponents[this->Position]; + return this->Position->BuildSystemDirectory + ->CurrentBinaryDirectoryComponents; } const char* cmState::Snapshot::GetRelativePathTopSource() const { - return this->State->RelativePathTopSource[this->Position].c_str(); + return this->Position->BuildSystemDirectory->RelativePathTopSource.c_str(); } const char* cmState::Snapshot::GetRelativePathTopBinary() const { - return this->State->RelativePathTopBinary[this->Position].c_str(); + return this->Position->BuildSystemDirectory->RelativePathTopBinary.c_str(); } void cmState::Snapshot::SetRelativePathTopSource(const char* dir) { - this->State->RelativePathTopSource[this->Position] = dir; + this->Position->BuildSystemDirectory->RelativePathTopSource = dir; } void cmState::Snapshot::SetRelativePathTopBinary(const char* dir) { - this->State->RelativePathTopBinary[this->Position] = dir; + this->Position->BuildSystemDirectory->RelativePathTopBinary = dir; } bool cmState::Snapshot::IsValid() const { - return this->State ? true : false; + return this->State && this->Position.IsValid() + ? this->Position != this->State->SnapshotData.Root() + : false; } cmState::Snapshot cmState::Snapshot::GetBuildsystemDirectoryParent() const { Snapshot snapshot; - if (!this->State || this->Position == 0) + if (!this->State || this->Position == this->State->SnapshotData.Root()) { return snapshot; } - PositionType parentPos = this->State->ParentPositions[this->Position]; - snapshot = Snapshot(this->State, parentPos); + PositionType parentPos = this->Position->DirectoryParent; + if (parentPos != this->State->SnapshotData.Root()) + { + snapshot = Snapshot(this->State, parentPos); + } return snapshot; } + +cmState* cmState::Snapshot::GetState() const +{ + return this->State; +} diff --git a/Source/cmState.h b/Source/cmState.h index b06f77c..353a6c6 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -15,21 +15,28 @@ #include "cmStandardIncludes.h" #include "cmPropertyDefinitionMap.h" #include "cmPropertyMap.h" +#include "cmLinkedTree.h" class cmake; class cmCommand; class cmState { - typedef std::vector<std::string>::size_type PositionType; + struct SnapshotDataType; + typedef cmLinkedTree<SnapshotDataType>::iterator PositionType; friend class Snapshot; public: cmState(cmake* cm); ~cmState(); + enum SnapshotType + { + BuildsystemDirectoryType + }; + class Snapshot { public: - Snapshot(cmState* state = 0, PositionType position = 0); + Snapshot(cmState* state = 0, PositionType position = PositionType()); const char* GetCurrentSourceDirectory() const; void SetCurrentSourceDirectory(std::string const& dir); @@ -47,6 +54,8 @@ public: bool IsValid() const; Snapshot GetBuildsystemDirectoryParent() const; + cmState* GetState() const; + private: void ComputeRelativePathTopSource(); void ComputeRelativePathTopBinary(); @@ -160,19 +169,11 @@ private: std::map<std::string, cmCommand*> Commands; cmPropertyMap GlobalProperties; cmake* CMakeInstance; - std::vector<std::string> Locations; - std::vector<std::string> OutputLocations; - std::vector<PositionType> ParentPositions; - - std::vector<std::vector<std::string> > CurrentSourceDirectoryComponents; - std::vector<std::vector<std::string> > CurrentBinaryDirectoryComponents; - // The top-most directories for relative path conversion. Both the - // source and destination location of a relative path conversion - // must be underneath one of these directories (both under source or - // both under binary) in order for the relative path to be evaluated - // safely by the build tools. - std::vector<std::string> RelativePathTopSource; - std::vector<std::string> RelativePathTopBinary; + + struct BuildsystemDirectoryStateType; + cmLinkedTree<BuildsystemDirectoryStateType> BuildsystemDirectory; + + cmLinkedTree<SnapshotDataType> SnapshotData; std::vector<std::string> SourceDirectoryComponents; std::vector<std::string> BinaryDirectoryComponents; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index daf5282..398d5c9 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -13,7 +13,7 @@ #include "cmake.h" #include "cmMakefile.h" #include "cmSourceFile.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmGlobalGenerator.h" #include "cmComputeLinkInformation.h" #include "cmListFileCache.h" @@ -1241,14 +1241,14 @@ void cmTarget::GetTllSignatureTraces(std::ostringstream &s, : "plain"); s << "The uses of the " << sigString << " signature are here:\n"; typedef std::vector<std::pair<TLLSignature, cmListFileContext> > Container; - cmLocalGenerator* lg = this->GetMakefile()->GetLocalGenerator(); + cmOutputConverter converter(this->GetMakefile()->GetStateSnapshot()); for(Container::const_iterator it = this->TLLCommands.begin(); it != this->TLLCommands.end(); ++it) { if (it->first == sig) { cmListFileContext lfc = it->second; - lfc.FilePath = lg->Convert(lfc.FilePath, cmLocalGenerator::HOME); + lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); s << " * " << lfc << std::endl; } } @@ -2798,34 +2798,6 @@ void cmTarget::GetTargetVersion(bool soversion, } //---------------------------------------------------------------------------- -const char* cmTarget::GetFeature(const std::string& feature, - const std::string& config) const -{ - if(!config.empty()) - { - std::string featureConfig = feature; - featureConfig += "_"; - featureConfig += cmSystemTools::UpperCase(config); - if(const char* value = this->GetProperty(featureConfig)) - { - return value; - } - } - if(const char* value = this->GetProperty(feature)) - { - return value; - } - return this->Makefile->GetFeature(feature, config); -} - -//---------------------------------------------------------------------------- -bool cmTarget::GetFeatureAsBool(const std::string& feature, - const std::string& config) const -{ - return cmSystemTools::IsOn(this->GetFeature(feature, config)); -} - -//---------------------------------------------------------------------------- bool cmTarget::HandleLocationPropertyPolicy(cmMakefile* context) const { if (this->IsImported()) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index ddc8d35..6916bd3 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -260,11 +260,6 @@ public: bool GetPropertyAsBool(const std::string& prop) const; void CheckProperty(const std::string& prop, cmMakefile* context) const; - const char* GetFeature(const std::string& feature, - const std::string& config) const; - bool GetFeatureAsBool(const std::string& feature, - const std::string& config) const; - bool IsImported() const {return this->IsImportedTarget;} void GetObjectLibrariesCMP0026(std::vector<cmTarget*>& objlibs) const; diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 7e11d8c..546ad71 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -12,7 +12,7 @@ #include "cmTestGenerator.h" #include "cmGeneratorExpression.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmMakefile.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -97,13 +97,13 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs); std::string emulatorExe(emulatorWithArgs[0]); cmSystemTools::ConvertToUnixSlashes(emulatorExe); - os << cmLocalGenerator::EscapeForCMake(emulatorExe) << " "; + os << cmOutputConverter::EscapeForCMake(emulatorExe) << " "; for(std::vector<std::string>::const_iterator ei = emulatorWithArgs.begin()+1; ei != emulatorWithArgs.end(); ++ei) { - os << cmLocalGenerator::EscapeForCMake(*ei) << " "; + os << cmOutputConverter::EscapeForCMake(*ei) << " "; } } } @@ -115,11 +115,11 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, } // Generate the command line with full escapes. - os << cmLocalGenerator::EscapeForCMake(exe); + os << cmOutputConverter::EscapeForCMake(exe); for(std::vector<std::string>::const_iterator ci = command.begin()+1; ci != command.end(); ++ci) { - os << " " << cmLocalGenerator::EscapeForCMake( + os << " " << cmOutputConverter::EscapeForCMake( ge.Parse(*ci)->Evaluate(mf, config)); } @@ -136,7 +136,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, i != pm.end(); ++i) { os << " " << i->first - << " " << cmLocalGenerator::EscapeForCMake( + << " " << cmOutputConverter::EscapeForCMake( ge.Parse(i->second.GetValue())->Evaluate(mf, config)); } os << ")" << std::endl; @@ -206,7 +206,7 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, i != pm.end(); ++i) { fout << " " << i->first - << " " << cmLocalGenerator::EscapeForCMake(i->second.GetValue()); + << " " << cmOutputConverter::EscapeForCMake(i->second.GetValue()); } fout << ")" << std::endl; } diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index c88e888..7eb678b 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -786,6 +786,15 @@ IF(KWSYS_USE_SystemInformation) SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1) ENDIF() + + IF(UNIX AND NOT CYGWIN) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_GETLOADAVG + "Checking whether CXX compiler has getloadavg" DIRECT) + IF(KWSYS_CXX_HAS_GETLOADAVG) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_CXX_HAS_GETLOADAVG=1) + ENDIF() + ENDIF() ENDIF() #----------------------------------------------------------------------------- diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index b0434f4..6e81b0b 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -81,6 +81,11 @@ typedef int siginfo_t; # include <errno.h> // extern int errno; #endif +#if defined (__CYGWIN__) && !defined(_WIN32) +# include <windows.h> +# undef _WIN32 +#endif + #ifdef __FreeBSD__ # include <sys/sysctl.h> # include <fenv.h> @@ -366,6 +371,8 @@ public: const char *procLimitEnvVarName); LongLong GetProcMemoryUsed(); + double GetLoadAverage(); + // enable/disable stack trace signal handler. static void SetStackTraceOnError(int enable); @@ -820,6 +827,11 @@ SystemInformation::LongLong SystemInformation::GetProcMemoryUsed() return this->Implementation->GetProcMemoryUsed(); } +double SystemInformation::GetLoadAverage() +{ + return this->Implementation->GetLoadAverage(); +} + SystemInformation::LongLong SystemInformation::GetProcessId() { return this->Implementation->GetProcessId(); @@ -1490,6 +1502,60 @@ void SymbolProperties::Initialize(void *address) } #endif // don't define this class if we're not using it +// -------------------------------------------------------------------------- +#if defined(_WIN32) || defined(__CYGWIN__) +# define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes +#endif +#if defined(_MSC_VER) && _MSC_VER < 1310 +# undef KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes +#endif +#if defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes) +double calculateCPULoad(unsigned __int64 idleTicks, + unsigned __int64 totalTicks) +{ + static double previousLoad = -0.0; + static unsigned __int64 previousIdleTicks = 0; + static unsigned __int64 previousTotalTicks = 0; + + unsigned __int64 const idleTicksSinceLastTime = + idleTicks - previousIdleTicks; + unsigned __int64 const totalTicksSinceLastTime = + totalTicks - previousTotalTicks; + + double load; + if (previousTotalTicks == 0 || totalTicksSinceLastTime == 0) + { + // No new information. Use previous result. + load = previousLoad; + } + else + { + // Calculate load since last time. + load = 1.0 - double(idleTicksSinceLastTime) / totalTicksSinceLastTime; + + // Smooth if possible. + if (previousLoad > 0) + { + load = 0.25 * load + 0.75 * previousLoad; + } + } + + previousLoad = load; + previousIdleTicks = idleTicks; + previousTotalTicks = totalTicks; + + return load; +} + +unsigned __int64 fileTimeToUInt64(FILETIME const& ft) +{ + LARGE_INTEGER out; + out.HighPart = ft.dwHighDateTime; + out.LowPart = ft.dwLowDateTime; + return out.QuadPart; +} +#endif + } // anonymous namespace @@ -3612,6 +3678,38 @@ SystemInformationImplementation::GetProcMemoryUsed() #endif } +double SystemInformationImplementation::GetLoadAverage() +{ +#if defined(KWSYS_CXX_HAS_GETLOADAVG) + double loadavg[3] = { 0.0, 0.0, 0.0 }; + if (getloadavg(loadavg, 3) > 0) + { + return loadavg[0]; + } + return -0.0; +#elif defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes) + // Old windows.h headers do not provide GetSystemTimes. + typedef BOOL (WINAPI *GetSystemTimesType)(LPFILETIME, LPFILETIME, + LPFILETIME); + static GetSystemTimesType pGetSystemTimes = + (GetSystemTimesType)GetProcAddress(GetModuleHandleW(L"kernel32"), + "GetSystemTimes"); + FILETIME idleTime, kernelTime, userTime; + if (pGetSystemTimes && pGetSystemTimes(&idleTime, &kernelTime, &userTime)) + { + unsigned __int64 const idleTicks = + fileTimeToUInt64(idleTime); + unsigned __int64 const totalTicks = + fileTimeToUInt64(kernelTime) + fileTimeToUInt64(userTime); + return calculateCPULoad(idleTicks, totalTicks) * GetNumberOfPhysicalCPU(); + } + return -0.0; +#else + // Not implemented on this platform. + return -0.0; +#endif +} + /** Get the process id of the running process. */ diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in index a9fd05d..4acdc4f 100644 --- a/Source/kwsys/SystemInformation.hxx.in +++ b/Source/kwsys/SystemInformation.hxx.in @@ -130,6 +130,10 @@ public: // Get system RAM used by this process id in units of KiB. LongLong GetProcMemoryUsed(); + // Return the load average of the machine or -0.0 if it cannot + // be determined. + double GetLoadAverage(); + // enable/disable stack trace signal handler. In order to // produce an informative stack trace the application should // be dynamically linked and compiled with debug symbols. diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx index 82620da..1596fe4 100644 --- a/Source/kwsys/kwsysPlatformTestsCXX.cxx +++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx @@ -452,6 +452,19 @@ int main() } #endif +#ifdef TEST_KWSYS_CXX_HAS_GETLOADAVG +// Match feature definitions from SystemInformation.cxx +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include <stdlib.h> +int main() +{ + double loadavg[3] = { 0.0, 0.0, 0.0 }; + return getloadavg(loadavg, 3); +} +#endif + #ifdef TEST_KWSYS_CXX_HAS_RLIMIT64 # if defined(KWSYS_HAS_LFS) # define _LARGEFILE_SOURCE diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx index 53d51ac..fc8ea55 100644 --- a/Source/kwsys/testSystemInformation.cxx +++ b/Source/kwsys/testSystemInformation.cxx @@ -87,6 +87,7 @@ int testSystemInformation(int, char*[]) printMethod3(info, GetProcMemoryAvailable("KWSHL","KWSPL"), "KiB"); printMethod3(info, GetHostMemoryUsed(), "KiB"); printMethod3(info, GetProcMemoryUsed(), "KiB"); + printMethod(info, GetLoadAverage); for (long int i = 0; i <= 31; i++) { |