diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index 72b5d62f6..1d3e4b5a9 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -79,6 +79,7 @@ macro(__windows_compiler_gnu lang) set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "") # No -fPIC on Windows set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS ${__WINDOWS_GNU_LD_RESPONSE}) + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1) # We prefer "@" for response files but it is not supported by gcc 3. execute_process(COMMAND ${CMAKE_${lang}_COMPILER} --version OUTPUT_VARIABLE _ver ERROR_VARIABLE _ver) @@ -92,6 +93,8 @@ macro(__windows_compiler_gnu lang) # Use "-Wl,@" to pass the response file to the linker. set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-Wl,@") endif() + # The GNU 3.x compilers do not support response files (only linkers). + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 0) elseif(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS) # Use "@" to pass the response file to the front-end. set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@") diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index bb6dc3f0d..f2431e63f 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1475,6 +1475,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE__STANDARD_LIBRARIES_INIT", cmProperty::VARIABLE,0,0); + cm->DefineProperty("CMAKE__USE_RESPONSE_FILE_FOR_INCLUDES", + cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE__USE_RESPONSE_FILE_FOR_OBJECTS", cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_EXECUTABLE_SUFFIX_", diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index cd265c16c..7b3fc86a8 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -575,6 +575,7 @@ void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, flags += this->Makefile->GetSafeDefinition(varString.c_str()); flags += " "; flags += this->GetIncludeFlags(lang); + flags += this->Makefile->GetDefineFlags(); // Construct the command lines. cmCustomCommandLines commandLines; @@ -1184,15 +1185,18 @@ cmLocalGenerator::ConvertToOutputForExisting(RelativeRoot remote, } //---------------------------------------------------------------------------- -const char* cmLocalGenerator::GetIncludeFlags(const char* lang) +const char* cmLocalGenerator::GetIncludeFlags(const char* lang, + bool forResponseFile) { if(!lang) { return ""; } - if(this->LanguageToIncludeFlags.count(lang)) + std::string key = lang; + key += forResponseFile? "@" : ""; + if(this->LanguageToIncludeFlags.count(key)) { - return this->LanguageToIncludeFlags[lang].c_str(); + return this->LanguageToIncludeFlags[key].c_str(); } cmOStringStream includeFlags; @@ -1250,10 +1254,10 @@ const char* cmLocalGenerator::GetIncludeFlags(const char* lang) frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str()); if(emitted.insert(frameworkDir).second) { + OutputFormat format = forResponseFile? RESPONSE : SHELL; includeFlags << "-F" << this->Convert(frameworkDir.c_str(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::SHELL, true) + START_OUTPUT, format, true) << " "; } continue; @@ -1273,7 +1277,16 @@ const char* cmLocalGenerator::GetIncludeFlags(const char* lang) } flagUsed = true; } - std::string includePath = this->ConvertToOutputForExisting(i->c_str()); + std::string includePath; + if(forResponseFile) + { + includePath = this->Convert(i->c_str(), START_OUTPUT, + RESPONSE, true); + } + else + { + includePath = this->ConvertToOutputForExisting(i->c_str()); + } if(quotePaths && includePath.size() && includePath[0] != '\"') { includeFlags << "\""; @@ -1291,13 +1304,11 @@ const char* cmLocalGenerator::GetIncludeFlags(const char* lang) { flags[flags.size()-1] = ' '; } - std::string defineFlags = this->Makefile->GetDefineFlags(); - flags += defineFlags; - this->LanguageToIncludeFlags[lang] = flags; + this->LanguageToIncludeFlags[key] = flags; // Use this temorary variable for the return value to work-around a // bogus GCC 2.95 warning. - const char* ret = this->LanguageToIncludeFlags[lang].c_str(); + const char* ret = this->LanguageToIncludeFlags[key].c_str(); return ret; } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 35aab99ec..aebf9f39a 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -143,7 +143,8 @@ public: const char* config); virtual void AppendFlags(std::string& flags, const char* newFlags); ///! Get the include flags for the current makefile and language - const char* GetIncludeFlags(const char* lang); + const char* GetIncludeFlags(const char* lang, + bool forResponseFile = false); /** * Encode a list of preprocessor definitions for the compiler diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index ff48009ba..d1214d211 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -880,6 +880,20 @@ cmLocalUnixMakefileGenerator3 } } +//---------------------------------------------------------------------------- +void +cmLocalUnixMakefileGenerator3 +::AppendRuleDepends(std::vector& depends, + std::vector const& ruleFiles) +{ + // Add a dependency on the rule file itself unless an option to skip + // it is specifically enabled by the user or project. + if(!this->Makefile->IsOn("CMAKE_SKIP_RULE_DEPENDENCY")) + { + depends.insert(depends.end(), ruleFiles.begin(), ruleFiles.end()); + } +} + //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3 diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 790eff10c..9ff6e5e51 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -320,6 +320,8 @@ protected: void AppendRuleDepend(std::vector& depends, const char* ruleFileName); + void AppendRuleDepends(std::vector& depends, + std::vector const& ruleFiles); void AppendCustomDepends(std::vector& depends, const std::vector& ccs); void AppendCustomDepend(std::vector& depends, diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 4426241c5..cd75d7977 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -47,12 +47,12 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles() // write rules used to help build object files this->WriteCommonCodeRules(); - // write in rules for object files and custom commands - this->WriteTargetBuildRules(); - // write the per-target per-language flags this->WriteTargetLanguageFlags(); + // write in rules for object files and custom commands + this->WriteTargetBuildRules(); + // write the link rules this->WriteExecutableRule(false); if(this->Target->NeedRelinkBeforeInstall(this->ConfigName)) diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 1e9a6708c..31f7be5cf 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -72,12 +72,12 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() // write rules used to help build object files this->WriteCommonCodeRules(); - // write in rules for object files and custom commands - this->WriteTargetBuildRules(); - // write the per-target per-language flags this->WriteTargetLanguageFlags(); + // write in rules for object files and custom commands + this->WriteTargetBuildRules(); + // write the link rules // Write the rule for this target type. switch(this->Target->GetType()) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 9dcd8f18e..69320dac4 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -310,8 +310,12 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() this->LocalGenerator->AddSharedFlags(flags, lang, shared); // Add include directory flags. + this->AddIncludeFlags(flags, lang); + + // Append old-style preprocessor definition flags. this->LocalGenerator-> - AppendFlags(flags, this->LocalGenerator->GetIncludeFlags(lang)); + AppendFlags(flags, this->Makefile->GetDefineFlags()); + // Add include directory flags. this->LocalGenerator-> AppendFlags(flags,this->GetFrameworkFlags().c_str()); @@ -482,6 +486,8 @@ cmMakefileTargetGenerator { this->LocalGenerator->AppendRuleDepend(depends, this->FlagFileNameFull.c_str()); + this->LocalGenerator->AppendRuleDepends(depends, + this->FlagFileDepends[lang]); // generate the depend scanning rule this->WriteObjectDependRules(source, depends); @@ -1719,6 +1725,38 @@ cmMakefileTargetGenerator } } +//---------------------------------------------------------------------------- +void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, + const char* lang) +{ + std::string responseVar = "CMAKE_"; + responseVar += lang; + responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES"; + bool useResponseFile = this->Makefile->IsOn(responseVar.c_str()); + + std::string includeFlags = + this->LocalGenerator->GetIncludeFlags(lang, useResponseFile); + if(includeFlags.empty()) + { + return; + } + + if(useResponseFile) + { + std::string name = "includes_"; + name += lang; + name += ".rsp"; + std::string arg = "@" + + this->CreateResponseFile(name.c_str(), includeFlags, + this->FlagFileDepends[lang]); + this->LocalGenerator->AppendFlags(flags, arg.c_str()); + } + else + { + this->LocalGenerator->AppendFlags(flags, includeFlags.c_str()); + } +} + //---------------------------------------------------------------------------- const char* cmMakefileTargetGenerator::GetFortranModuleDirectory() { diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index c9aede2f2..bd26795d3 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -146,6 +146,8 @@ protected: bool useResponseFile, std::string& buildObjs, std::vector& makefile_depends); + void AddIncludeFlags(std::string& flags, const char* lang); + virtual void CloseFileStreams(); void RemoveForbiddenFlags(const char* flagVar, const char* linkLang, std::string& linkFlags); @@ -177,6 +179,8 @@ protected: // the stream for the flag file std::string FlagFileNameFull; cmGeneratedFileStream *FlagFileStream; + class StringList: public std::vector {}; + std::map FlagFileDepends; // the stream for the info file std::string InfoFileNameFull;