diff options
Diffstat (limited to 'Source/cmMakefile.cxx')
-rw-r--r-- | Source/cmMakefile.cxx | 252 |
1 files changed, 191 insertions, 61 deletions
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f067da491..47a6d2e66 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -23,6 +23,7 @@ #include "cmListFileCache.h" #include "cmCommandArgumentParserHelper.h" #include "cmDocumentCompileDefinitions.h" +#include "cmGeneratorExpression.h" #include "cmTest.h" #ifdef CMAKE_BUILD_WITH_CMAKE # include "cmVariableWatch.h" @@ -99,6 +100,7 @@ cmMakefile::cmMakefile(): Internal(new Internals) this->AddDefaultDefinitions(); this->Initialize(); this->PreOrder = false; + this->GeneratingBuildSystem = false; } cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals) @@ -814,7 +816,7 @@ bool cmMakefile::NeedBackwardsCompatibility(unsigned int major, void cmMakefile::FinalPass() { // do all the variable expansions here - this->ExpandVariables(); + this->ExpandVariablesCMP0019(); // give all the commands a chance to do something // after the file has been parsed before generation @@ -1485,9 +1487,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<cmValueWithOrigin> parentIncludes = + parent->GetIncludeDirectoriesEntries(); + this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(), + parentIncludes.begin(), + parentIncludes.end()); + this->SystemIncludeDirectories = parent->SystemIncludeDirectories; // define flags @@ -1613,74 +1618,72 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath, } //---------------------------------------------------------------------------- -void AddStringToProperty(cmProperty *prop, const char* name, const char* s, - bool before) +void cmMakefile::AddIncludeDirectories(const std::vector<std::string> &incs, + bool before) { - if (!prop) + if (incs.empty()) { 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 incString; + std::string sep; - std::string newVal = oss.str(); - prop->Set(name, newVal.c_str()); - } - else + for(std::vector<std::string>::const_iterator li = incs.begin(); + li != incs.end(); ++li) { - prop->Append(name, s); + incString += sep + *li; + sep = ";"; } -} -//---------------------------------------------------------------------------- -void cmMakefile::AddIncludeDirectory(const char* inc, bool before) -{ - if (!inc) - { - return; - } + std::vector<cmValueWithOrigin>::iterator position = + before ? this->IncludeDirectoriesEntries.begin() + : this->IncludeDirectoriesEntries.end(); - // Directory property: - cmProperty *prop = - this->GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES"); - AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before); + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + cmValueWithOrigin entry(incString, 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); } } //---------------------------------------------------------------------------- -void cmMakefile::AddSystemIncludeDirectory(const char* dir) +void +cmMakefile::AddSystemIncludeDirectories(const std::set<cmStdString> &incs) { - this->SystemIncludeDirectories.insert(dir); + for(std::set<cmStdString>::const_iterator li = incs.begin(); + li != incs.end(); ++li) + { + this->SystemIncludeDirectories.insert(*li); + } } //---------------------------------------------------------------------------- -bool cmMakefile::IsSystemIncludeDirectory(const char* dir) +bool cmMakefile::IsSystemIncludeDirectory(const char* dir, const char *config) { - return (this->SystemIncludeDirectories.find(dir) != - this->SystemIncludeDirectories.end()); + for (std::set<cmStdString>::const_iterator + it = this->SystemIncludeDirectories.begin(); + it != this->SystemIncludeDirectories.end(); ++it) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + std::vector<std::string> incs; + cmSystemTools::ExpandListArgument(ge.Parse(*it) + ->Evaluate(this, config, false), incs); + if (std::find(incs.begin(), incs.end(), dir) != incs.end()) + { + return true; + } + } + return false; } void cmMakefile::AddDefinition(const char* name, const char* value) @@ -2122,21 +2125,33 @@ void cmMakefile::AddExtraDirectory(const char* dir) this->AuxSourceDirectories.push_back(dir); } +static bool mightExpandVariablesCMP0019(const char* s) +{ + return s && *s && strstr(s,"${") && strchr(s,'}'); +} -// expand CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the -// include and library directories. - -void cmMakefile::ExpandVariables() +void cmMakefile::ExpandVariablesCMP0019() { - // Now expand variables in the include and link strings + // Drop this ancient compatibility behavior with a policy. + cmPolicies::PolicyStatus pol = this->GetPolicyStatus(cmPolicies::CMP0019); + if(pol != cmPolicies::OLD && pol != cmPolicies::WARN) + { + return; + } + cmOStringStream w; - // May not be necessary anymore... But may need a policy for strict - // backwards compatibility const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES"); - if (includeDirs) + if(mightExpandVariablesCMP0019(includeDirs)) { std::string dirs = includeDirs; this->ExpandVariablesInString(dirs, true, true); + if(pol == cmPolicies::WARN && dirs != includeDirs) + { + w << "Evaluated directory INCLUDE_DIRECTORIES\n" + << " " << includeDirs << "\n" + << "as\n" + << " " << dirs << "\n"; + } this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); } @@ -2146,10 +2161,17 @@ void cmMakefile::ExpandVariables() { cmTarget &t = l->second; includeDirs = t.GetProperty("INCLUDE_DIRECTORIES"); - if (includeDirs) + if(mightExpandVariablesCMP0019(includeDirs)) { std::string dirs = includeDirs; this->ExpandVariablesInString(dirs, true, true); + if(pol == cmPolicies::WARN && dirs != includeDirs) + { + w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n" + << " " << includeDirs << "\n" + << "as\n" + << " " << dirs << "\n"; + } t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); } } @@ -2157,13 +2179,45 @@ void cmMakefile::ExpandVariables() for(std::vector<std::string>::iterator d = this->LinkDirectories.begin(); d != this->LinkDirectories.end(); ++d) { - this->ExpandVariablesInString(*d, true, true); + if(mightExpandVariablesCMP0019(d->c_str())) + { + std::string orig = *d; + this->ExpandVariablesInString(*d, true, true); + if(pol == cmPolicies::WARN && *d != orig) + { + w << "Evaluated link directory\n" + << " " << orig << "\n" + << "as\n" + << " " << *d << "\n"; + } + } } for(cmTarget::LinkLibraryVectorType::iterator l = this->LinkLibraries.begin(); l != this->LinkLibraries.end(); ++l) { - this->ExpandVariablesInString(l->first, true, true); + if(mightExpandVariablesCMP0019(l->first.c_str())) + { + std::string orig = l->first; + this->ExpandVariablesInString(l->first, true, true); + if(pol == cmPolicies::WARN && l->first != orig) + { + w << "Evaluated link library\n" + << " " << orig << "\n" + << "as\n" + << " " << l->first << "\n"; + } + } + } + + if(!w.str().empty()) + { + cmOStringStream m; + m << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0019) + << "\n" + << "The following variable evaluations were encountered:\n" + << w.str(); + this->IssueMessage(cmake::AUTHOR_WARNING, m.str()); } } @@ -2221,7 +2275,7 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName) { return true; } - // If we are doing an in-source build, than the test will always fail + // If we are doing an in-source build, then the test will always fail if ( cmSystemTools::SameFile(this->GetHomeDirectory(), this->GetHomeOutputDirectory()) ) { @@ -2232,8 +2286,8 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName) return true; } - // Check if this is subdirectory of the source tree but not a - // subdirectory of a build tree + // Check if this is a subdirectory of the source tree but not a + // subdirectory of the build tree if ( cmSystemTools::IsSubDirectory(fileName, this->GetHomeDirectory()) && !cmSystemTools::IsSubDirectory(fileName, @@ -2951,6 +3005,7 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir, cm.SetStartDirectory(srcdir); cm.SetStartOutputDirectory(bindir); cm.SetCMakeCommand(cmakeCommand.c_str()); + cm.SetGeneratorToolset(this->GetCMakeInstance()->GetGeneratorToolset()); cm.LoadCache(); if(!gg->IsMultiConfig()) { @@ -3400,6 +3455,19 @@ void cmMakefile::SetProperty(const char* prop, const char* value) this->SetLinkDirectories(varArgsExpanded); return; } + if (propname == "INCLUDE_DIRECTORIES") + { + this->IncludeDirectoriesEntries.clear(); + if (!value) + { + return; + } + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->IncludeDirectoriesEntries.push_back( + cmValueWithOrigin(value, lfbt)); + return; + } if ( propname == "INCLUDE_REGULAR_EXPRESSION" ) { @@ -3431,6 +3499,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( + cmValueWithOrigin(value, lfbt)); + return; + } if ( propname == "LINK_DIRECTORIES" ) { std::vector<std::string> varArgsExpanded; @@ -3542,6 +3618,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<cmValueWithOrigin>::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 = @@ -3937,6 +4027,46 @@ void cmMakefile::DefineProperties(cmake *cm) "See the global property of the same name for details. " "This overrides the global property for a directory.", true); + + cm->DefineProperty + ("VS_GLOBAL_SECTION_PRE_<section>", cmProperty::DIRECTORY, + "Specify a preSolution global section in Visual Studio.", + "Setting a property like this generates an entry of the following form " + "in the solution file:\n" + " GlobalSection(<section>) = preSolution\n" + " <contents based on property value>\n" + " EndGlobalSection\n" + "The property must be set to a semicolon-separated list of key=value " + "pairs. Each such pair will be transformed into an entry in the solution " + "global section. Whitespace around key and value is ignored. List " + "elements which do not contain an equal sign are skipped." + "\n" + "This property only works for Visual Studio 7 and above; it is ignored " + "on other generators. The property only applies when set on a directory " + "whose CMakeLists.txt conatins a project() command."); + cm->DefineProperty + ("VS_GLOBAL_SECTION_POST_<section>", cmProperty::DIRECTORY, + "Specify a postSolution global section in Visual Studio.", + "Setting a property like this generates an entry of the following form " + "in the solution file:\n" + " GlobalSection(<section>) = postSolution\n" + " <contents based on property value>\n" + " EndGlobalSection\n" + "The property must be set to a semicolon-separated list of key=value " + "pairs. Each such pair will be transformed into an entry in the solution " + "global section. Whitespace around key and value is ignored. List " + "elements which do not contain an equal sign are skipped." + "\n" + "This property only works for Visual Studio 7 and above; it is ignored " + "on other generators. The property only applies when set on a directory " + "whose CMakeLists.txt conatins a project() command." + "\n" + "Note that CMake generates postSolution sections ExtensibilityGlobals " + "and ExtensibilityAddIns by default. If you set the corresponding " + "property, it will override the default section. For example, setting " + "VS_GLOBAL_SECTION_POST_ExtensibilityGlobals will override the default " + "contents of the ExtensibilityGlobals section, while keeping " + "ExtensibilityAddIns on its default."); } //---------------------------------------------------------------------------- |