From 76ea420fb9a8ceada0e806f1201230e5a7c1202c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 19 Nov 2012 19:30:56 +0100 Subject: [PATCH 1/3] Use cmsys::auto_ptr to manage cmCompiledGeneratorExpressions The compiled generator expressions need to outlive the creating type. For the same reason, store the input string in a std::string. --- Source/cmCustomCommandGenerator.cxx | 4 +-- Source/cmGeneratorExpression.cxx | 46 ++++++++++++----------------- Source/cmGeneratorExpression.h | 24 +++++++++------ Source/cmGeneratorTarget.cxx | 4 +-- Source/cmTarget.cxx | 7 +++-- Source/cmTestGenerator.cxx | 4 +-- 6 files changed, 44 insertions(+), 45 deletions(-) diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 07df7d5e0..f2f77eea0 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -47,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const { return target->GetLocation(this->Config); } - return this->GE->Parse(argv0).Evaluate(this->Makefile, this->Config); + return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config); } //---------------------------------------------------------------------------- @@ -58,7 +58,7 @@ cmCustomCommandGenerator cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; for(unsigned int j=1;j < commandLine.size(); ++j) { - std::string arg = this->GE->Parse(commandLine[j]).Evaluate(this->Makefile, + std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile, this->Config); cmd += " "; if(this->OldStyle) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 32bf941eb..3fd4a5f8e 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -25,44 +25,29 @@ //---------------------------------------------------------------------------- cmGeneratorExpression::cmGeneratorExpression( cmListFileBacktrace const& backtrace): - Backtrace(backtrace), CompiledExpression(0) + Backtrace(backtrace) { } //---------------------------------------------------------------------------- -const cmCompiledGeneratorExpression & +cmsys::auto_ptr cmGeneratorExpression::Parse(std::string const& input) { return this->Parse(input.c_str()); } //---------------------------------------------------------------------------- -const cmCompiledGeneratorExpression & +cmsys::auto_ptr cmGeneratorExpression::Parse(const char* input) { - cmGeneratorExpressionLexer l; - std::vector tokens = l.Tokenize(input); - bool needsParsing = l.GetSawGeneratorExpression(); - std::vector evaluators; - - if (needsParsing) - { - cmGeneratorExpressionParser p(tokens); - p.Parse(evaluators); - } - - delete this->CompiledExpression; - this->CompiledExpression = new cmCompiledGeneratorExpression( - this->Backtrace, - evaluators, - input, - needsParsing); - return *this->CompiledExpression; + return cmsys::auto_ptr( + new cmCompiledGeneratorExpression( + this->Backtrace, + input)); } cmGeneratorExpression::~cmGeneratorExpression() { - delete this->CompiledExpression; } //---------------------------------------------------------------------------- @@ -73,7 +58,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( { if (!this->NeedsParsing) { - return this->Input; + return this->Input.c_str(); } this->Output = ""; @@ -108,12 +93,19 @@ const char *cmCompiledGeneratorExpression::Evaluate( cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( cmListFileBacktrace const& backtrace, - const std::vector &evaluators, - const char *input, bool needsParsing) - : Backtrace(backtrace), Evaluators(evaluators), Input(input), - NeedsParsing(needsParsing) + const char *input) + : Backtrace(backtrace), Input(input ? input : "") { + cmGeneratorExpressionLexer l; + std::vector tokens = + l.Tokenize(this->Input.c_str()); + this->NeedsParsing = l.GetSawGeneratorExpression(); + if (this->NeedsParsing) + { + cmGeneratorExpressionParser p(tokens); + p.Parse(this->Evaluators); + } } diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index ea3e7d03b..961e53d75 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -14,10 +14,12 @@ #define cmGeneratorExpression_h #include "cmStandardIncludes.h" +#include "cmListFileCache.h" #include #include +#include class cmTarget; class cmMakefile; @@ -44,8 +46,9 @@ public: cmGeneratorExpression(cmListFileBacktrace const& backtrace); ~cmGeneratorExpression(); - const cmCompiledGeneratorExpression& Parse(std::string const& input); - const cmCompiledGeneratorExpression& Parse(const char* input); + cmsys::auto_ptr Parse( + std::string const& input); + cmsys::auto_ptr Parse(const char* input); enum PreprocessContext { StripAllGeneratorExpressions @@ -59,7 +62,6 @@ private: void operator=(const cmGeneratorExpression &); cmListFileBacktrace const& Backtrace; - cmCompiledGeneratorExpression *CompiledExpression; }; class cmCompiledGeneratorExpression @@ -76,20 +78,24 @@ public: ~cmCompiledGeneratorExpression(); + std::string GetInput() const + { + return this->Input; + } + private: cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, - const std::vector &evaluators, - const char *input, bool needsParsing); + const char *input); friend class cmGeneratorExpression; cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression &); void operator=(const cmCompiledGeneratorExpression &); - cmListFileBacktrace const& Backtrace; - const std::vector Evaluators; - const char* const Input; - const bool NeedsParsing; + cmListFileBacktrace Backtrace; + std::vector Evaluators; + const std::string Input; + bool NeedsParsing; mutable std::set Targets; mutable std::string Output; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index de8b5e369..55507ddf3 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -267,7 +267,7 @@ std::vector cmGeneratorTarget::GetIncludeDirectories( "INCLUDE_DIRECTORIES", 0, 0); cmSystemTools::ExpandListArgument(ge.Parse(prop) - .Evaluate(this->Makefile, + ->Evaluate(this->Makefile, config, false, this->Target, @@ -315,7 +315,7 @@ std::string cmGeneratorTarget::GetCompileDefinitions(const char *config) cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), defPropName, 0, 0); - return ge.Parse(prop).Evaluate(this->Makefile, + return ge.Parse(prop)->Evaluate(this->Makefile, config, false, this->Target, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index de3b23c78..e7b34ee42 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1728,9 +1728,10 @@ cmTargetTraceDependencies for(cmCustomCommandLine::const_iterator cli = cit->begin(); cli != cit->end(); ++cli) { - const cmCompiledGeneratorExpression &cge = ge.Parse(*cli); - cge.Evaluate(this->Makefile, 0, true); - std::set geTargets = cge.GetTargets(); + const cmsys::auto_ptr cge + = ge.Parse(*cli); + cge->Evaluate(this->Makefile, 0, true); + std::set geTargets = cge->GetTargets(); for(std::set::const_iterator it = geTargets.begin(); it != geTargets.end(); ++it) { diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 2f650e72e..42f511ea3 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -112,7 +112,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, else { // Use the command name given. - exe = ge.Parse(exe.c_str()).Evaluate(mf, config); + exe = ge.Parse(exe.c_str())->Evaluate(mf, config); cmSystemTools::ConvertToUnixSlashes(exe); } @@ -122,7 +122,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, for(std::vector::const_iterator ci = command.begin()+1; ci != command.end(); ++ci) { - os << " " << lg->EscapeForCMake(ge.Parse(*ci).Evaluate(mf, config)); + os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config)); } // Finish the test command. From 18a3195ad57cafd06851ecf4cb7265cab95cfa38 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 19 Nov 2012 22:47:30 +0100 Subject: [PATCH 2/3] Keep track of INCLUDE_DIRECTORIES as a vector of structs. The struct can keep track of where the include came from, which gives us proper backtraces. --- Source/cmGeneratorTarget.cxx | 40 +----- Source/cmMakefile.cxx | 90 +++++++------ Source/cmMakefile.h | 10 ++ Source/cmMakefileIncludeDirectoriesEntry.h | 28 ++++ Source/cmTarget.cxx | 125 +++++++++++++++++- Source/cmTarget.h | 4 + .../BadInvalidName1-stderr.txt | 4 +- .../BadInvalidName2-stderr.txt | 6 +- .../BadInvalidName3-stderr.txt | 6 +- .../BadInvalidName4-stderr.txt | 6 +- .../BadInvalidName5-stderr.txt | 4 +- .../BadInvalidName6-stderr.txt | 4 +- .../BadInvalidName7-stderr.txt | 4 +- .../BadInvalidName8-stderr.txt | 4 +- .../BadNonTarget-stderr.txt | 6 +- 15 files changed, 243 insertions(+), 98 deletions(-) create mode 100644 Source/cmMakefileIncludeDirectoriesEntry.h diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 55507ddf3..62ee26a22 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -252,45 +252,7 @@ const char* cmGeneratorTarget::GetCreateRuleVariable() std::vector cmGeneratorTarget::GetIncludeDirectories( const char *config) { - std::vector includes; - const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES"); - if(!prop) - { - return includes; - } - - cmListFileBacktrace lfbt; - cmGeneratorExpression ge(lfbt); - - cmGeneratorExpressionDAGChecker dagChecker(lfbt, - this->GetName(), - "INCLUDE_DIRECTORIES", 0, 0); - - cmSystemTools::ExpandListArgument(ge.Parse(prop) - ->Evaluate(this->Makefile, - config, - false, - this->Target, - &dagChecker), - includes); - - std::set uniqueIncludes; - std::vector orderedAndUniqueIncludes; - for(std::vector::const_iterator - li = includes.begin(); li != includes.end(); ++li) - { - std::string inc = *li; - if (!cmSystemTools::IsOff(inc.c_str())) - { - cmSystemTools::ConvertToUnixSlashes(inc); - } - if(uniqueIncludes.insert(inc).second) - { - orderedAndUniqueIncludes.push_back(inc); - } - } - - return orderedAndUniqueIncludes; + return this->Target->GetIncludeDirectories(config); } //---------------------------------------------------------------------------- diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index d943c450f..b432986a8 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1485,9 +1485,12 @@ void cmMakefile::InitializeFromParent() // Initialize definitions with the closure of the parent scope. this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure(); - // copy include paths - this->SetProperty("INCLUDE_DIRECTORIES", - parent->GetProperty("INCLUDE_DIRECTORIES")); + const std::vector parentIncludes = + parent->GetIncludeDirectoriesEntries(); + this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(), + parentIncludes.begin(), + parentIncludes.end()); + this->SystemIncludeDirectories = parent->SystemIncludeDirectories; // define flags @@ -1612,41 +1615,6 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath, } } -//---------------------------------------------------------------------------- -void AddStringToProperty(cmProperty *prop, const char* name, const char* s, - bool before) -{ - if (!prop) - { - return; - } - - // Don't worry about duplicates at this point. We eliminate them when - // we convert the property to a vector in GetIncludeDirectories. - - if (before) - { - const char *val = prop->GetValue(); - cmOStringStream oss; - - if(val && *val) - { - oss << s << ";" << val; - } - else - { - oss << s; - } - - std::string newVal = oss.str(); - prop->Set(name, newVal.c_str()); - } - else - { - prop->Append(name, s); - } -} - //---------------------------------------------------------------------------- void cmMakefile::AddIncludeDirectory(const char* inc, bool before) { @@ -1655,18 +1623,21 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before) return; } - // Directory property: - cmProperty *prop = - this->GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES"); - AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before); + std::vector::iterator position = + before ? this->IncludeDirectoriesEntries.begin() + : this->IncludeDirectoriesEntries.end(); + + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + IncludeDirectoriesEntry entry(inc, lfbt); + this->IncludeDirectoriesEntries.insert(position, entry); // Property on each target: for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end(); ++l) { cmTarget &t = l->second; - prop = t.GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES"); - AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before); + t.InsertInclude(entry, before); } } @@ -3451,6 +3422,15 @@ void cmMakefile::SetProperty(const char* prop, const char* value) this->SetLinkDirectories(varArgsExpanded); return; } + if (propname == "INCLUDE_DIRECTORIES") + { + this->IncludeDirectoriesEntries.clear(); + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->IncludeDirectoriesEntries.push_back( + IncludeDirectoriesEntry(value, lfbt)); + return; + } if ( propname == "INCLUDE_REGULAR_EXPRESSION" ) { @@ -3482,6 +3462,14 @@ void cmMakefile::AppendProperty(const char* prop, const char* value, // handle special props std::string propname = prop; + if (propname == "INCLUDE_DIRECTORIES") + { + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->IncludeDirectoriesEntries.push_back( + IncludeDirectoriesEntry(value, lfbt)); + return; + } if ( propname == "LINK_DIRECTORIES" ) { std::vector varArgsExpanded; @@ -3593,6 +3581,20 @@ const char *cmMakefile::GetProperty(const char* prop, output = str.str(); return output.c_str(); } + else if (!strcmp("INCLUDE_DIRECTORIES",prop)) + { + std::string sep; + for (std::vector::const_iterator + it = this->IncludeDirectoriesEntries.begin(), + end = this->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + output += sep; + output += it->Value; + sep = ";"; + } + return output.c_str(); + } bool chain = false; const char *retVal = diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index eff05d091..a85015fe6 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -22,6 +22,7 @@ #include "cmNewLineStyle.h" #include "cmGeneratorTarget.h" #include "cmake.h" +#include "cmMakefileIncludeDirectoriesEntry.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmSourceGroup.h" @@ -861,6 +862,13 @@ public: /** Set whether or not to report a CMP0000 violation. */ void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } + typedef cmMakefileIncludeDirectoriesEntry IncludeDirectoriesEntry; + + std::vector GetIncludeDirectoriesEntries() const + { + return this->IncludeDirectoriesEntries; + } + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); @@ -909,6 +917,8 @@ protected: std::vector HeaderFileExtensions; std::string DefineFlags; + std::vector IncludeDirectoriesEntries; + // Track the value of the computed DEFINITIONS property. void AddDefineFlag(const char*, std::string&); void RemoveDefineFlag(const char*, std::string::size_type, std::string&); diff --git a/Source/cmMakefileIncludeDirectoriesEntry.h b/Source/cmMakefileIncludeDirectoriesEntry.h new file mode 100644 index 000000000..f35642dfb --- /dev/null +++ b/Source/cmMakefileIncludeDirectoriesEntry.h @@ -0,0 +1,28 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 Stephen Kelly + + 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 cmMakefileIncludeDirectoriesEntry_h +#define cmMakefileIncludeDirectoriesEntry_h + +#include +#include "cmListFileCache.h" + +struct cmMakefileIncludeDirectoriesEntry { + cmMakefileIncludeDirectoriesEntry(const std::string &value, + const cmListFileBacktrace &bt) + : Value(value), Backtrace(bt) + {} + std::string Value; + cmListFileBacktrace Backtrace; +}; + +#endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e7b34ee42..0c6bb1c5f 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -21,6 +21,7 @@ #include "cmDocumentLocationUndefined.h" #include "cmListFileCache.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionDAGChecker.h" #include #include #include @@ -118,6 +119,14 @@ public: struct SourceEntry { std::vector Depends; }; typedef std::map SourceEntriesType; SourceEntriesType SourceEntries; + + struct IncludeDirectoriesEntry { + IncludeDirectoriesEntry(cmsys::auto_ptr cge) + : ge(cge) + {} + const cmsys::auto_ptr ge; + }; + std::vector IncludeDirectoriesEntries; }; //---------------------------------------------------------------------------- @@ -1392,8 +1401,14 @@ void cmTarget::SetMakefile(cmMakefile* mf) // Initialize the INCLUDE_DIRECTORIES property based on the current value // of the same directory property: - this->SetProperty("INCLUDE_DIRECTORIES", - this->Makefile->GetProperty("INCLUDE_DIRECTORIES")); + const std::vector parentIncludes = + this->Makefile->GetIncludeDirectoriesEntries(); + + for (std::vector::const_iterator it + = parentIncludes.begin(); it != parentIncludes.end(); ++it) + { + this->InsertInclude(*it); + } if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) @@ -2445,6 +2460,20 @@ void cmTarget::GatherDependencies( const cmMakefile& mf, } } +//---------------------------------------------------------------------------- +void deleteAndClear( + std::vector &entries) +{ + for (std::vector::const_iterator + it = entries.begin(), + end = entries.end(); + it != end; ++it) + { + delete *it; + } + entries.clear(); +} + //---------------------------------------------------------------------------- void cmTarget::SetProperty(const char* prop, const char* value) { @@ -2453,6 +2482,16 @@ void cmTarget::SetProperty(const char* prop, const char* value) return; } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + deleteAndClear(this->Internal->IncludeDirectoriesEntries); + cmsys::auto_ptr cge = ge.Parse(value); + this->Internal->IncludeDirectoriesEntries.push_back( + new cmTargetInternals::IncludeDirectoriesEntry(cge)); + return; + } this->Properties.SetProperty(prop, value, cmProperty::TARGET); this->MaybeInvalidatePropertyCache(prop); } @@ -2465,10 +2504,73 @@ void cmTarget::AppendProperty(const char* prop, const char* value, { return; } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + this->Internal->IncludeDirectoriesEntries.push_back( + new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value))); + return; + } this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString); this->MaybeInvalidatePropertyCache(prop); } +//---------------------------------------------------------------------------- +void cmTarget::InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, + bool before) +{ + cmGeneratorExpression ge(entry.Backtrace); + + std::vector::iterator position + = before ? this->Internal->IncludeDirectoriesEntries.begin() + : this->Internal->IncludeDirectoriesEntries.end(); + + this->Internal->IncludeDirectoriesEntries.insert(position, + new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value))); +} + +//---------------------------------------------------------------------------- +std::vector cmTarget::GetIncludeDirectories(const char *config) +{ + std::vector includes; + std::set uniqueIncludes; + cmListFileBacktrace lfbt; + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "INCLUDE_DIRECTORIES", 0, 0); + + for (std::vector::const_iterator + it = this->Internal->IncludeDirectoriesEntries.begin(), + end = this->Internal->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + std::vector entryIncludes; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile, + config, + false, + this, + &dagChecker), + entryIncludes); + for(std::vector::const_iterator + li = entryIncludes.begin(); li != entryIncludes.end(); ++li) + { + std::string inc = *li; + if (!cmSystemTools::IsOff(inc.c_str())) + { + cmSystemTools::ConvertToUnixSlashes(inc); + } + + if(uniqueIncludes.insert(inc).second) + { + includes.push_back(*li); + } + } + } + return includes; +} + //---------------------------------------------------------------------------- void cmTarget::MaybeInvalidatePropertyCache(const char* prop) { @@ -2796,6 +2898,24 @@ const char *cmTarget::GetProperty(const char* prop, } } } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + static std::string output; + output = ""; + std::string sep; + typedef cmTargetInternals::IncludeDirectoriesEntry + IncludeDirectoriesEntry; + for (std::vector::const_iterator + it = this->Internal->IncludeDirectoriesEntries.begin(), + end = this->Internal->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } + return output.c_str(); + } if (strcmp(prop,"IMPORTED") == 0) { @@ -4919,6 +5039,7 @@ cmTargetInternalPointer //---------------------------------------------------------------------------- cmTargetInternalPointer::~cmTargetInternalPointer() { + deleteAndClear(this->Pointer->IncludeDirectoriesEntries); delete this->Pointer; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 0dfbc68a1..3f3605043 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -15,6 +15,7 @@ #include "cmCustomCommand.h" #include "cmPropertyMap.h" #include "cmPolicies.h" +#include "cmMakefileIncludeDirectoriesEntry.h" #include @@ -470,6 +471,9 @@ public: /** @return the Mac framework directory without the base. */ std::string GetFrameworkDirectory(const char* config = 0); + std::vector GetIncludeDirectories(const char *config); + void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, + bool before = false); private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt index 3287d19ac..9c146e057 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName1.cmake:7 \(include_directories\): Error evaluating generator expression: \$ Target name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\) diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt index e527e2275..451888cc6 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName2.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Target name and property name not supported.$ + Target name and property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt index 517debbca..39692c4ef 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName3.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Property name not supported.$ + Property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt index eab6fb690..c3aa1b1a9 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName4.cmake:9 \(include_directories\): Error evaluating generator expression: \$ - Property name not supported.$ + Property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt index e2b4fc6fa..1c6fad4b0 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt @@ -1,7 +1,9 @@ -CMake Error: +CMake Error at BadInvalidName5.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty target name and property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt index e94f52fa2..8b147dca6 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName6.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty target name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt index 2548215f4..dad6bf86a 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName7.cmake:9 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt index 2a98f6f06..4e8c14c99 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName8.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt index d2ac7a963..3b3bab07d 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadNonTarget.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Target "NonExistant" not found.$ + Target "NonExistant" not found. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ From 0941d6232a979a129a651915972ab7332c15550d Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 18 Dec 2012 16:16:14 +0100 Subject: [PATCH 3/3] Add a way to print the origins of used include directories. --- Source/cmDocumentVariables.cxx | 9 ++++ Source/cmGeneratorExpression.h | 5 +++ Source/cmTarget.cxx | 27 ++++++++++++ .../DebugIncludes-result.txt | 1 + .../DebugIncludes-stderr.txt | 42 +++++++++++++++++++ .../include_directories/DebugIncludes.cmake | 38 +++++++++++++++++ .../include_directories/RunCMakeTest.cmake | 1 + 7 files changed, 123 insertions(+) create mode 100644 Tests/RunCMake/include_directories/DebugIncludes-result.txt create mode 100644 Tests/RunCMake/include_directories/DebugIncludes-stderr.txt create mode 100644 Tests/RunCMake/include_directories/DebugIncludes.cmake diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 32c543dce..d4a876d0a 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -896,6 +896,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm) " script, it may get fatal error messages from the script.",false, "Variables That Change Behavior"); + cm->DefineProperty + ("CMAKE_DEBUG_TARGET_PROPERTIES", cmProperty::VARIABLE, + "Enables tracing output for target properties.", + "This variable can be populated with a list of properties to generate " + "debug output for when evaluating target properties. Currently it can " + "only be used when evaluating the INCLUDE_DIRECTORIES target property. " + "In that case, it outputs a backtrace for each include directory in " + "the build. Default is unset.",false,"Variables That Change Behavior"); + // Variables defined by CMake that describe the system cm->DefineProperty diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 961e53d75..15e637cb7 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -83,6 +83,11 @@ public: return this->Input; } + cmListFileBacktrace GetBacktrace() const + { + return this->Backtrace; + } + private: cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, const char *input); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 0c6bb1c5f..58fab80cc 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2485,6 +2485,7 @@ void cmTarget::SetProperty(const char* prop, const char* value) if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) { cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); cmGeneratorExpression ge(lfbt); deleteAndClear(this->Internal->IncludeDirectoriesEntries); cmsys::auto_ptr cge = ge.Parse(value); @@ -2507,6 +2508,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value, if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) { cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); cmGeneratorExpression ge(lfbt); this->Internal->IncludeDirectoriesEntries.push_back( new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value))); @@ -2541,6 +2543,20 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) this->GetName(), "INCLUDE_DIRECTORIES", 0, 0); + + std::vector debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugIncludes = std::find(debugProperties.begin(), + debugProperties.end(), + "INCLUDE_DIRECTORIES") + != debugProperties.end(); + for (std::vector::const_iterator it = this->Internal->IncludeDirectoriesEntries.begin(), end = this->Internal->IncludeDirectoriesEntries.end(); @@ -2553,6 +2569,7 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) this, &dagChecker), entryIncludes); + std::string usedIncludes; for(std::vector::const_iterator li = entryIncludes.begin(); li != entryIncludes.end(); ++li) { @@ -2565,8 +2582,18 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) if(uniqueIncludes.insert(inc).second) { includes.push_back(*li); + if (debugIncludes) + { + usedIncludes += " * " + *li + "\n"; + } } } + if (!usedIncludes.empty()) + { + this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, + "Used includes:\n" + usedIncludes, + (*it)->ge->GetBacktrace()); + } } return includes; } diff --git a/Tests/RunCMake/include_directories/DebugIncludes-result.txt b/Tests/RunCMake/include_directories/DebugIncludes-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt new file mode 100644 index 000000000..948def117 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt @@ -0,0 +1,42 @@ +CMake Warning at DebugIncludes.cmake:8 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/one + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:8 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/two + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:13 \(set_property\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/three + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:18 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/four + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:25 \(set_property\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/five + \* .*/Tests/RunCMake/include_directories/six + +Call Stack \(most recent call first\): + DebugIncludes.cmake:35 \(some_macro\) + DebugIncludes.cmake:38 \(some_function\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/include_directories/DebugIncludes.cmake b/Tests/RunCMake/include_directories/DebugIncludes.cmake new file mode 100644 index 000000000..51daf7480 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes.cmake @@ -0,0 +1,38 @@ + +project(DebugIncludes) + +set(CMAKE_DEBUG_TARGET_PROPERTIES INCLUDE_DIRECTORIES) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/DebugIncludes.cpp" "enum { dummy };\n") + +include_directories( + "${CMAKE_CURRENT_SOURCE_DIR}/one" + "${CMAKE_CURRENT_SOURCE_DIR}/two" +) + +set_property(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES + "${CMAKE_CURRENT_SOURCE_DIR}/three") + +add_library(lll "${CMAKE_CURRENT_BINARY_DIR}/DebugIncludes.cpp") + +include_directories( + "${CMAKE_CURRENT_SOURCE_DIR}/two" + "${CMAKE_CURRENT_SOURCE_DIR}/three" + "${CMAKE_CURRENT_SOURCE_DIR}/four" +) + +macro(some_macro) + set_property(TARGET lll APPEND PROPERTY + INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/one" + "${CMAKE_CURRENT_SOURCE_DIR}/three" + "${CMAKE_CURRENT_SOURCE_DIR}/four" + "${CMAKE_CURRENT_SOURCE_DIR}/five" + "${CMAKE_CURRENT_SOURCE_DIR}/six" + ) +endmacro() + +function(some_function) + some_macro() +endfunction() + +some_function() diff --git a/Tests/RunCMake/include_directories/RunCMakeTest.cmake b/Tests/RunCMake/include_directories/RunCMakeTest.cmake index aee3f799b..de3725226 100644 --- a/Tests/RunCMake/include_directories/RunCMakeTest.cmake +++ b/Tests/RunCMake/include_directories/RunCMakeTest.cmake @@ -1,3 +1,4 @@ include(RunCMake) run_cmake(NotFoundContent) +run_cmake(DebugIncludes)