From 2679a34a943cddb61f816299476f15997f9b5980 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 1 Jul 2013 22:23:08 +0200 Subject: [PATCH 1/6] Remove unused variable. --- Source/cmLocalGenerator.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 00846d5f8..83f1d6db1 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1294,7 +1294,6 @@ std::string cmLocalGenerator::GetIncludeFlags( continue; } - std::string include = *i; if(!flagUsed || repeatFlag) { if(sysIncludeFlag && From f1fcbe3fdedb0d04fe89423331c0f2789bfe911e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 1 Jul 2013 22:28:26 +0200 Subject: [PATCH 2/6] Add Target API to determine if an include is a system include. The implementation can be modified later so that system includes can be determined on a per-target basis. --- Source/cmExtraSublimeTextGenerator.cxx | 2 +- Source/cmGeneratorTarget.cxx | 7 +++++++ Source/cmGeneratorTarget.h | 2 ++ Source/cmLocalGenerator.cxx | 7 ++++--- Source/cmLocalGenerator.h | 1 + Source/cmMakefileTargetGenerator.cxx | 3 ++- Source/cmNinjaTargetGenerator.cxx | 3 ++- Source/cmake.cxx | 2 +- 8 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 012013c38..39b6add50 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -421,7 +421,7 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source, std::vector includes; lg->GetIncludeDirectories(includes, gtgt, language, config); std::string includeFlags = - lg->GetIncludeFlags(includes, language, true); // full include paths + lg->GetIncludeFlags(includes, gtgt, language, true); // full include paths lg->AppendFlags(flags, includeFlags.c_str()); } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f5d15607e..61ff8d511 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -47,6 +47,13 @@ const char *cmGeneratorTarget::GetProperty(const char *prop) return this->Target->GetProperty(prop); } +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir, + const char *config) +{ + return this->Makefile->IsSystemIncludeDirectory(dir, config); +} + //---------------------------------------------------------------------------- bool cmGeneratorTarget::GetPropertyAsBool(const char *prop) { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 5f7019deb..c0fd7726c 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -72,6 +72,8 @@ public: /** Get the include directories for this target. */ std::vector GetIncludeDirectories(const char *config); + bool IsSystemIncludeDirectory(const char *dir, const char *config); + private: void ClassifySources(); void LookupObjectLibraries(); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 83f1d6db1..2971c3bf6 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -577,7 +577,7 @@ void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, { std::vector includes; this->GetIncludeDirectories(includes, &target, lang); - flags += this->GetIncludeFlags(includes, lang); + flags += this->GetIncludeFlags(includes, &target, lang); } flags += this->Makefile->GetDefineFlags(); @@ -1224,6 +1224,7 @@ cmLocalGenerator::ConvertToIncludeReference(std::string const& path) //---------------------------------------------------------------------------- std::string cmLocalGenerator::GetIncludeFlags( const std::vector &includes, + cmGeneratorTarget* target, const char* lang, bool forResponseFile, const char *config) { @@ -1296,8 +1297,8 @@ std::string cmLocalGenerator::GetIncludeFlags( if(!flagUsed || repeatFlag) { - if(sysIncludeFlag && - this->Makefile->IsSystemIncludeDirectory(i->c_str(), config)) + if(sysIncludeFlag && target && + target->IsSystemIncludeDirectory(i->c_str(), config)) { includeFlags << sysIncludeFlag; } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index f35ef8e2b..ef4b1c628 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -152,6 +152,7 @@ public: virtual void AppendFlagEscape(std::string& flags, const char* rawFlag); ///! Get the include flags for the current makefile and language std::string GetIncludeFlags(const std::vector &includes, + cmGeneratorTarget* target, const char* lang, bool forResponseFile = false, const char *config = 0); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 1492dfabe..c9e4161b7 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1853,7 +1853,8 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, lang, config); std::string includeFlags = - this->LocalGenerator->GetIncludeFlags(includes, lang, useResponseFile); + this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget, + lang, useResponseFile); if(includeFlags.empty()) { return; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 65173ca26..b5ca78ac2 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -161,7 +161,8 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, this->GeneratorTarget, language.c_str(), config); std::string includeFlags = - this->LocalGenerator->GetIncludeFlags(includes, language.c_str(), + this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget, + language.c_str(), language == "RC" ? true : false); // full include paths for RC // needed by cmcldeps if(cmGlobalNinjaGenerator::IsMinGW()) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index fcec068b7..592b5ecf8 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -612,7 +612,7 @@ bool cmake::FindPackage(const std::vector& args) std::vector includeDirs; cmSystemTools::ExpandListArgument(includes, includeDirs); - std::string includeFlags = lg->GetIncludeFlags(includeDirs, + std::string includeFlags = lg->GetIncludeFlags(includeDirs, 0, language.c_str(), false); std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS"); From 83498d413530570f7ab9affee5b8301c888bf91e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 1 Jul 2013 22:55:25 +0200 Subject: [PATCH 3/6] Store system include directories in the cmTarget. Entries from the cmMakefile are processed and maintained similarly to other include directories. The include_directories(SYSTEM) signature affects all following targets, and all prior targets in the same makefile. --- Source/cmGeneratorTarget.cxx | 18 +++++++++++++++++- Source/cmMakefile.cxx | 22 ++++------------------ Source/cmMakefile.h | 3 +++ Source/cmTarget.cxx | 33 +++++++++++++++++++++++++++++++++ Source/cmTarget.h | 9 +++++++++ 5 files changed, 66 insertions(+), 19 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 61ff8d511..9167b25a3 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -51,7 +51,23 @@ const char *cmGeneratorTarget::GetProperty(const char *prop) bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir, const char *config) { - return this->Makefile->IsSystemIncludeDirectory(dir, config); + for (std::set::const_iterator + it = this->Target->GetSystemIncludeDirectories().begin(); + it != this->Target->GetSystemIncludeDirectories().end(); ++it) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + std::vector incs; + cmSystemTools::ExpandListArgument(ge.Parse(*it) + ->Evaluate(this->Makefile, + config, false), incs); + if (std::find(incs.begin(), incs.end(), dir) != incs.end()) + { + return true; + } + } + return false; } //---------------------------------------------------------------------------- diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f3a66bab8..ecc094222 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1675,27 +1675,13 @@ cmMakefile::AddSystemIncludeDirectories(const std::set &incs) { this->SystemIncludeDirectories.insert(*li); } -} -//---------------------------------------------------------------------------- -bool cmMakefile::IsSystemIncludeDirectory(const char* dir, const char *config) -{ - for (std::set::const_iterator - it = this->SystemIncludeDirectories.begin(); - it != this->SystemIncludeDirectories.end(); ++it) + for (cmTargets::iterator l = this->Targets.begin(); + l != this->Targets.end(); ++l) { - cmListFileBacktrace lfbt; - cmGeneratorExpression ge(lfbt); - - std::vector incs; - cmSystemTools::ExpandListArgument(ge.Parse(*it) - ->Evaluate(this, config, false), incs); - if (std::find(incs.begin(), incs.end(), dir) != incs.end()) - { - return true; - } + cmTarget &t = l->second; + t.AddSystemIncludeDirectories(incs); } - return false; } void cmMakefile::AddDefinition(const char* name, const char* value) diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 42971559e..082224026 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -875,6 +875,9 @@ public: bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; } void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; } + std::set const & GetSystemIncludeDirectories() const + { return this->SystemIncludeDirectories; } + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index a90fa74cb..7ad42f826 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1647,6 +1647,17 @@ void cmTarget::SetMakefile(cmMakefile* mf) { this->InsertInclude(*it); } + + const std::set parentSystemIncludes = + this->Makefile->GetSystemIncludeDirectories(); + + for (std::set::const_iterator it + = parentSystemIncludes.begin(); + it != parentSystemIncludes.end(); ++it) + { + this->SystemIncludeDirectories.insert(*it); + } + const std::vector parentOptions = this->Makefile->GetCompileOptionsEntries(); @@ -2522,6 +2533,28 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, } +//---------------------------------------------------------------------------- +void +cmTarget::AddSystemIncludeDirectories(const std::set &incs) +{ + for(std::set::const_iterator li = incs.begin(); + li != incs.end(); ++li) + { + this->SystemIncludeDirectories.insert(*li); + } +} + +//---------------------------------------------------------------------------- +void +cmTarget::AddSystemIncludeDirectories(const std::vector &incs) +{ + for(std::vector::const_iterator li = incs.begin(); + li != incs.end(); ++li) + { + this->SystemIncludeDirectories.insert(*li); + } +} + //---------------------------------------------------------------------------- void cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 3bc0ab2e2..ff6d9235d 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -533,7 +533,16 @@ public: std::string GetDebugGeneratorExpressions(const std::string &value, cmTarget::LinkLibraryType llt); + + void AddSystemIncludeDirectories(const std::set &incs); + void AddSystemIncludeDirectories(const std::vector &incs); + std::set const & GetSystemIncludeDirectories() const + { return this->SystemIncludeDirectories; } private: + // The set of include directories that are marked as system include + // directories. + std::set SystemIncludeDirectories; + /** * A list of direct dependencies. Use in conjunction with DependencyMap. */ From 286f22770907fad3453eadf34e641ad736237292 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 1 Jul 2013 23:19:25 +0200 Subject: [PATCH 4/6] Extend the cmTargetPropCommandBase interface property handling. This can be used to handle INTERFACE SYSTEM include directories in particular. --- Source/cmTargetPropCommandBase.cxx | 36 ++++++++++++++++++------------ Source/cmTargetPropCommandBase.h | 3 +++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 771097ca2..64f40d6b3 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -126,19 +126,27 @@ void cmTargetPropCommandBase } if (scope == "INTERFACE" || scope == "PUBLIC") { - if (prepend) - { - const std::string propName = std::string("INTERFACE_") + this->Property; - const char *propValue = this->Target->GetProperty(propName.c_str()); - const std::string totalContent = this->Join(content) + (propValue - ? std::string(";") + propValue - : std::string()); - this->Target->SetProperty(propName.c_str(), totalContent.c_str()); - } - else - { - this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(), - this->Join(content).c_str()); - } + this->HandleInterfaceContent(this->Target, content, prepend); + } +} + +//---------------------------------------------------------------------------- +void cmTargetPropCommandBase::HandleInterfaceContent(cmTarget *tgt, + const std::vector &content, + bool prepend) +{ + if (prepend) + { + const std::string propName = std::string("INTERFACE_") + this->Property; + const char *propValue = tgt->GetProperty(propName.c_str()); + const std::string totalContent = this->Join(content) + (propValue + ? std::string(";") + propValue + : std::string()); + tgt->SetProperty(propName.c_str(), totalContent.c_str()); + } + else + { + tgt->AppendProperty(("INTERFACE_" + this->Property).c_str(), + this->Join(content).c_str()); } } diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 8047a48aa..9db7581fd 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -36,6 +36,9 @@ protected: std::string Property; cmTarget *Target; + virtual void HandleInterfaceContent(cmTarget *tgt, + const std::vector &content, + bool prepend); private: virtual void HandleImportedTarget(const std::string &tgt) = 0; virtual void HandleMissingTarget(const std::string &name) = 0; From 1925cffa083bcbe3c54b8a0f2c63dc96f5168db0 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 20 Jan 2013 14:04:13 +0100 Subject: [PATCH 5/6] Add a SYSTEM parameter to target_include_directories (#14180) This is similar to the include_directories(SYSTEM) signature in that it allows telling the compiler to ignore warnings from such headers. --- Source/cmTargetCompileDefinitionsCommand.cxx | 2 +- Source/cmTargetCompileDefinitionsCommand.h | 2 +- Source/cmTargetCompileOptionsCommand.cxx | 2 +- Source/cmTargetCompileOptionsCommand.h | 2 +- Source/cmTargetIncludeDirectoriesCommand.cxx | 23 ++++++++++++++-- Source/cmTargetIncludeDirectoriesCommand.h | 8 ++++-- Source/cmTargetPropCommandBase.cxx | 28 ++++++++++++++------ Source/cmTargetPropCommandBase.h | 12 +++++---- 8 files changed, 58 insertions(+), 21 deletions(-) diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index ba0ad5986..46c9666ef 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -60,7 +60,7 @@ std::string cmTargetCompileDefinitionsCommand //---------------------------------------------------------------------------- void cmTargetCompileDefinitionsCommand ::HandleDirectContent(cmTarget *tgt, const std::vector &content, - bool) + bool, bool) { tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str()); } diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index 22d8fa8e9..bc58b3174 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -82,7 +82,7 @@ private: virtual void HandleDirectContent(cmTarget *tgt, const std::vector &content, - bool prepend); + bool prepend, bool system); virtual std::string Join(const std::vector &content); }; diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index e80c8456b..254acc73d 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -53,7 +53,7 @@ std::string cmTargetCompileOptionsCommand //---------------------------------------------------------------------------- void cmTargetCompileOptionsCommand ::HandleDirectContent(cmTarget *tgt, const std::vector &content, - bool) + bool, bool) { cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h index 87fa1a720..b9afd7169 100644 --- a/Source/cmTargetCompileOptionsCommand.h +++ b/Source/cmTargetCompileOptionsCommand.h @@ -83,7 +83,7 @@ private: virtual void HandleDirectContent(cmTarget *tgt, const std::vector &content, - bool prepend); + bool prepend, bool system); virtual std::string Join(const std::vector &content); }; diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 12d0a515f..ee915212c 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -15,7 +15,8 @@ bool cmTargetIncludeDirectoriesCommand ::InitialPass(std::vector const& args, cmExecutionStatus &) { - return this->HandleArguments(args, "INCLUDE_DIRECTORIES", PROCESS_BEFORE); + return this->HandleArguments(args, "INCLUDE_DIRECTORIES", + ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM)); } //---------------------------------------------------------------------------- @@ -65,10 +66,28 @@ std::string cmTargetIncludeDirectoriesCommand //---------------------------------------------------------------------------- void cmTargetIncludeDirectoriesCommand ::HandleDirectContent(cmTarget *tgt, const std::vector &content, - bool prepend) + bool prepend, bool system) { cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); cmValueWithOrigin entry(this->Join(content), lfbt); tgt->InsertInclude(entry, prepend); + if (system) + { + tgt->AddSystemIncludeDirectories(content); + } +} + +//---------------------------------------------------------------------------- +void cmTargetIncludeDirectoriesCommand +::HandleInterfaceContent(cmTarget *tgt, + const std::vector &content, + bool prepend, bool system) +{ + if (system) + { + // Error. + } + cmTargetPropCommandBase::HandleInterfaceContent(tgt, content, + prepend, system); } diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index 4a1a4df34..a84ddd0cd 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -54,7 +54,7 @@ public: virtual const char* GetFullDocumentation() const { return - " target_include_directories( [BEFORE] " + " target_include_directories( [SYSTEM] [BEFORE] " " [items1...]\n" " [ [items2...] ...])\n" "Specify include directories or targets to use when compiling a given " @@ -87,7 +87,11 @@ private: virtual void HandleDirectContent(cmTarget *tgt, const std::vector &content, - bool prepend); + bool prepend, bool system); + virtual void HandleInterfaceContent(cmTarget *tgt, + const std::vector &content, + bool prepend, bool system); + virtual std::string Join(const std::vector &content); }; diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 64f40d6b3..287ce46a2 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -48,8 +48,20 @@ bool cmTargetPropCommandBase return false; } + bool system = false; unsigned int argIndex = 1; + if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") + { + if (args.size() < 4) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + system = true; + ++argIndex; + } + bool prepend = false; if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") { @@ -66,7 +78,7 @@ bool cmTargetPropCommandBase while (argIndex < args.size()) { - if (!this->ProcessContentArgs(args, argIndex, prepend)) + if (!this->ProcessContentArgs(args, argIndex, prepend, system)) { return false; } @@ -77,7 +89,7 @@ bool cmTargetPropCommandBase //---------------------------------------------------------------------------- bool cmTargetPropCommandBase ::ProcessContentArgs(std::vector const& args, - unsigned int &argIndex, bool prepend) + unsigned int &argIndex, bool prepend, bool system) { const std::string scope = args[argIndex]; @@ -105,12 +117,12 @@ bool cmTargetPropCommandBase || args[i] == "PRIVATE" || args[i] == "INTERFACE" ) { - this->PopulateTargetProperies(scope, content, prepend); + this->PopulateTargetProperies(scope, content, prepend, system); return true; } content.push_back(args[i]); } - this->PopulateTargetProperies(scope, content, prepend); + this->PopulateTargetProperies(scope, content, prepend, system); return true; } @@ -118,22 +130,22 @@ bool cmTargetPropCommandBase void cmTargetPropCommandBase ::PopulateTargetProperies(const std::string &scope, const std::vector &content, - bool prepend) + bool prepend, bool system) { if (scope == "PRIVATE" || scope == "PUBLIC") { - this->HandleDirectContent(this->Target, content, prepend); + this->HandleDirectContent(this->Target, content, prepend, system); } if (scope == "INTERFACE" || scope == "PUBLIC") { - this->HandleInterfaceContent(this->Target, content, prepend); + this->HandleInterfaceContent(this->Target, content, prepend, system); } } //---------------------------------------------------------------------------- void cmTargetPropCommandBase::HandleInterfaceContent(cmTarget *tgt, const std::vector &content, - bool prepend) + bool prepend, bool) { if (prepend) { diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 9db7581fd..690582fdd 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -25,7 +25,8 @@ public: enum ArgumentFlags { NO_FLAGS = 0, - PROCESS_BEFORE = 1 + PROCESS_BEFORE = 1, + PROCESS_SYSTEM = 2 }; bool HandleArguments(std::vector const& args, @@ -38,21 +39,22 @@ protected: virtual void HandleInterfaceContent(cmTarget *tgt, const std::vector &content, - bool prepend); + bool prepend, bool system); private: virtual void HandleImportedTarget(const std::string &tgt) = 0; virtual void HandleMissingTarget(const std::string &name) = 0; virtual void HandleDirectContent(cmTarget *tgt, const std::vector &content, - bool prepend) = 0; + bool prepend, bool system) = 0; + virtual std::string Join(const std::vector &content) = 0; bool ProcessContentArgs(std::vector const& args, - unsigned int &argIndex, bool prepend); + unsigned int &argIndex, bool prepend, bool system); void PopulateTargetProperies(const std::string &scope, const std::vector &content, - bool prepend); + bool prepend, bool system); }; #endif From 9cf3547e1cd56d42bc96c3dc3adf9f745faea5ee Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 2 Jul 2013 14:30:10 +0200 Subject: [PATCH 6/6] Add the INTERFACE_SYSTEM_INCLUDE_DIRECTORIES target property. Unlike other target properties, this does not have a corresponding non-INTERFACE variant. This allows propagation of system attribute on include directories from link dependents. --- Source/cmExportInstallFileGenerator.cxx | 4 ++ Source/cmGeneratorExpressionDAGChecker.cxx | 8 ++++ Source/cmGeneratorExpressionDAGChecker.h | 2 + Source/cmGeneratorExpressionEvaluator.cxx | 4 ++ Source/cmGeneratorTarget.cxx | 44 ++++++++++++++----- Source/cmGeneratorTarget.h | 2 + Source/cmGlobalGenerator.cxx | 11 +++++ Source/cmTarget.cxx | 44 +++++++++++++++++++ Source/cmTarget.h | 3 ++ Source/cmTargetIncludeDirectoriesCommand.cxx | 19 ++++++-- Source/cmTargetIncludeDirectoriesCommand.h | 8 ++++ Tests/IncludeDirectories/CMakeLists.txt | 17 +++++++ .../SystemIncludeDirectories/CMakeLists.txt | 19 ++++++++ .../SystemIncludeDirectories/consumer.cpp | 7 +++ .../SystemIncludeDirectories/systemlib.cpp | 4 ++ .../systemlib/systemlib.h | 19 ++++++++ .../SystemIncludeDirectories/upstream.cpp | 4 ++ .../SystemIncludeDirectories/upstream.h | 12 +++++ 18 files changed, 216 insertions(+), 15 deletions(-) create mode 100644 Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt create mode 100644 Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp create mode 100644 Tests/IncludeDirectories/SystemIncludeDirectories/systemlib.cpp create mode 100644 Tests/IncludeDirectories/SystemIncludeDirectories/systemlib/systemlib.h create mode 100644 Tests/IncludeDirectories/SystemIncludeDirectories/upstream.cpp create mode 100644 Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index a966b1605..43b17c602 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -126,6 +126,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateIncludeDirectoriesInterface(te, cmGeneratorExpression::InstallInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", + te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te, cmGeneratorExpression::InstallInterface, diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 5b79e3531..d04e19542 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -171,6 +171,14 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories() const || strcmp(prop, "INTERFACE_INCLUDE_DIRECTORIES") == 0 ); } +//---------------------------------------------------------------------------- +bool +cmGeneratorExpressionDAGChecker::EvaluatingSystemIncludeDirectories() const +{ + const char *prop = this->Property.c_str(); + return strcmp(prop, "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") == 0; +} + //---------------------------------------------------------------------------- bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const { diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 95d466ae3..f0524f290 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -18,11 +18,13 @@ #define CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(F) \ F(EvaluatingIncludeDirectories) \ + F(EvaluatingSystemIncludeDirectories) \ F(EvaluatingCompileDefinitions) \ F(EvaluatingCompileOptions) #define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F) \ F(INTERFACE_INCLUDE_DIRECTORIES) \ + F(INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) \ F(INTERFACE_COMPILE_DEFINITIONS) \ F(INTERFACE_COMPILE_OPTIONS) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 05bbc1ce8..53fb35d6e 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -879,6 +879,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES"; } + else if (propertyName == "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") + { + interfacePropertyName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"; + } else if (propertyName == "INTERFACE_COMPILE_DEFINITIONS" || propertyName == "COMPILE_DEFINITIONS" || strncmp(propertyName.c_str(), "COMPILE_DEFINITIONS_", 20) == 0) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 9167b25a3..5ce0e6be1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -51,21 +51,43 @@ const char *cmGeneratorTarget::GetProperty(const char *prop) bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir, const char *config) { - for (std::set::const_iterator - it = this->Target->GetSystemIncludeDirectories().begin(); - it != this->Target->GetSystemIncludeDirectories().end(); ++it) + std::string config_upper; + if(config && *config) { - cmListFileBacktrace lfbt; - cmGeneratorExpression ge(lfbt); + config_upper = cmSystemTools::UpperCase(config); + } - std::vector incs; - cmSystemTools::ExpandListArgument(ge.Parse(*it) - ->Evaluate(this->Makefile, - config, false), incs); - if (std::find(incs.begin(), incs.end(), dir) != incs.end()) + typedef std::map > IncludeCacheType; + IncludeCacheType::iterator iter = + this->SystemIncludesCache.find(config_upper); + + if (iter == this->SystemIncludesCache.end()) + { + std::vector result; + for (std::set::const_iterator + it = this->Target->GetSystemIncludeDirectories().begin(); + it != this->Target->GetSystemIncludeDirectories().end(); ++it) { - return true; + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", 0, 0); + + cmSystemTools::ExpandListArgument(ge.Parse(*it) + ->Evaluate(this->Makefile, + config, false, this->Target, + &dagChecker), result); } + IncludeCacheType::value_type entry(config_upper, result); + iter = this->SystemIncludesCache.insert(entry).first; + } + + if (std::find(iter->second.begin(), + iter->second.end(), dir) != iter->second.end()) + { + return true; } return false; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index c0fd7726c..dedfa60aa 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -78,6 +78,8 @@ private: void ClassifySources(); void LookupObjectLibraries(); + std::map > SystemIncludesCache; + cmGeneratorTarget(cmGeneratorTarget const&); void operator=(cmGeneratorTarget const&); }; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index ad74767f7..2897114ab 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1001,6 +1001,17 @@ void cmGlobalGenerator::Generate() // it builds by default. this->FillLocalGeneratorToTargetMap(); + for (i = 0; i < this->LocalGenerators.size(); ++i) + { + cmMakefile* mf = this->LocalGenerators[i]->GetMakefile(); + cmTargets* targets = &(mf->GetTargets()); + for ( cmTargets::iterator it = targets->begin(); + it != targets->end(); ++ it ) + { + it->second.FinalizeSystemIncludeDirectories(); + } + } + // Generate project files for (i = 0; i < this->LocalGenerators.size(); ++i) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 7ad42f826..806f77c34 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -842,6 +842,17 @@ void cmTarget::DefineProperties(cmake *cm) CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS); + cm->DefineProperty + ("SYSTEM_INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET, + "List of public system include directories for a library.", + "Targets may populate this property to publish the include directories " + "which contain system headers, and therefore should not result in " + "compiler warnings. Consuming targets will then mark the same include " + "directories as system headers." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS); + cm->DefineProperty ("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET, "List of public compile definitions for a library.", @@ -2555,6 +2566,39 @@ cmTarget::AddSystemIncludeDirectories(const std::vector &incs) } } +//---------------------------------------------------------------------------- +void cmTarget::FinalizeSystemIncludeDirectories() +{ + for (std::vector::const_iterator + it = this->Internal->LinkInterfacePropertyEntries.begin(), + end = this->Internal->LinkInterfacePropertyEntries.end(); + it != end; ++it) + { + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr cge = + ge.Parse(it->Value); + std::string targetName = cge->Evaluate(this->Makefile, 0, + false, this, 0, 0); + if (!this->Makefile->FindTargetToUse(targetName.c_str())) + { + continue; + } + } + std::string includeGenex = "$Value + ",INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>"; + if (cmGeneratorExpression::Find(it->Value) != std::string::npos) + { + // Because it->Value is a generator expression, ensure that it + // evaluates to the non-empty string before being used in the + // TARGET_PROPERTY expression. + includeGenex = "$<$Value + ">:" + includeGenex + ">"; + } + this->SystemIncludeDirectories.insert(includeGenex); + } +} + //---------------------------------------------------------------------------- void cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index ff6d9235d..09cddaf45 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -538,6 +538,9 @@ public: void AddSystemIncludeDirectories(const std::vector &incs); std::set const & GetSystemIncludeDirectories() const { return this->SystemIncludeDirectories; } + + void FinalizeSystemIncludeDirectories(); + private: // The set of include directories that are marked as system include // directories. diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index ee915212c..e7b906c9e 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -84,10 +84,21 @@ void cmTargetIncludeDirectoriesCommand const std::vector &content, bool prepend, bool system) { - if (system) - { - // Error. - } cmTargetPropCommandBase::HandleInterfaceContent(tgt, content, prepend, system); + + if (system) + { + std::string joined; + std::string sep; + for(std::vector::const_iterator it = content.begin(); + it != content.end(); ++it) + { + joined += sep; + sep = ";"; + joined += *it; + } + tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", + joined.c_str()); + } } diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index a84ddd0cd..29686183c 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -71,6 +71,14 @@ public: "The following arguments specify include directories. Specified " "include directories may be absolute paths or relative paths. " "Repeated calls for the same append items in the order called." + "If SYSTEM is specified, the compiler will be told the " + "directories are meant as system include directories on some " + "platforms (signalling this setting might achieve effects such as " + "the compiler skipping warnings, or these fixed-install system files " + "not being considered in dependency calculations - see compiler " + "docs). If SYSTEM is used together with PUBLIC or INTERFACE, the " + "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES target property will be " + "populated with the specified directories." "\n" "Arguments to target_include_directories may use \"generator " "expressions\" with the syntax \"$<...>\". " diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt index 3e3ecc90d..596a28066 100644 --- a/Tests/IncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/CMakeLists.txt @@ -1,6 +1,23 @@ cmake_minimum_required (VERSION 2.6) project(IncludeDirectories) +if (((CMAKE_C_COMPILER_ID STREQUAL GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4) + OR CMAKE_C_COMPILER_ID STREQUAL Clang) + AND (CMAKE_GENERATOR STREQUAL "Unix Makefiles" OR CMAKE_GENERATOR STREQUAL "Ninja")) + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-Wunused-variable run_sys_includes_test) + if(run_sys_includes_test) + # The Bullseye wrapper appears to break the -isystem effect. + execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE out ERROR_VARIABLE out) + if("x${out}" MATCHES "Bullseye") + set(run_sys_includes_test 0) + endif() + endif() + if (run_sys_includes_test) + add_subdirectory(SystemIncludeDirectories) + endif() +endif() + file(WRITE ${CMAKE_BINARY_DIR}/Flags/Flags.h "//Flags.h ") diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt new file mode 100644 index 000000000..aec6ff981 --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt @@ -0,0 +1,19 @@ + +cmake_minimum_required(VERSION 2.8) + +project(SystemIncludeDirectories) + +add_library(systemlib systemlib.cpp) +target_include_directories(systemlib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/systemlib") + +add_library(upstream upstream.cpp) +target_link_libraries(upstream LINK_PUBLIC systemlib) +target_compile_options(upstream PRIVATE -Werror=unused-variable) + +target_include_directories(upstream SYSTEM PUBLIC + $ +) + +add_library(consumer consumer.cpp) +target_link_libraries(consumer upstream) +target_compile_options(consumer PRIVATE -Werror=unused-variable) diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp new file mode 100644 index 000000000..197dae86d --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp @@ -0,0 +1,7 @@ + +#include "upstream.h" + +int consumer() +{ + return upstream(); +} diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib.cpp new file mode 100644 index 000000000..f111bfa55 --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib.cpp @@ -0,0 +1,4 @@ + +#include "systemlib.h" + +int systemlib() { return 0; } diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib/systemlib.h b/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib/systemlib.h new file mode 100644 index 000000000..c84de6a28 --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib/systemlib.h @@ -0,0 +1,19 @@ + +#ifndef SYSTEMLIB_H +#define SYSTEMLIB_H + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int systemlib(); + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int unusedFunc() +{ + int unused; + return systemlib(); +} + +#endif diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.cpp new file mode 100644 index 000000000..f716b99e6 --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.cpp @@ -0,0 +1,4 @@ + +#include "upstream.h" + +int upstream() { return systemlib(); } diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h new file mode 100644 index 000000000..3628568cf --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h @@ -0,0 +1,12 @@ + +#ifndef UPSTREAM_H +#define UPSTREAM_H + +#include "systemlib.h" + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int upstream(); + +#endif