summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2013-01-10 15:22:52 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2013-01-10 15:22:52 (GMT)
commit378899ce8744c2e2b43d0859234eea714dcef368 (patch)
tree9419bbdbfa1ca672a06219f61cfe232c25b73b77 /Source
parent325e92fa22cb20a3d4bccbf1f663c28b34f8b04c (diff)
parent3581b96caa1d7bd6c02e85baf72ce28b5128e5e7 (diff)
downloadCMake-378899ce8744c2e2b43d0859234eea714dcef368.zip
CMake-378899ce8744c2e2b43d0859234eea714dcef368.tar.gz
CMake-378899ce8744c2e2b43d0859234eea714dcef368.tar.bz2
Merge topic 'INTERFACE_POSITION_INDEPENDENT_CODE'
3581b96 Process the INTERFACE_PIC property from linked dependencies 042ecf0 Add API to calculate link-interface-dependent bool properties or error. bf5ece5 Keep track of properties used to determine linker libraries.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGeneratorExpression.cxx10
-rw-r--r--Source/cmGeneratorExpression.h4
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx8
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h1
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx6
-rw-r--r--Source/cmLocalGenerator.cxx17
-rw-r--r--Source/cmLocalGenerator.h2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx3
-rw-r--r--Source/cmNinjaTargetGenerator.cxx3
-rw-r--r--Source/cmTarget.cxx184
-rw-r--r--Source/cmTarget.h13
11 files changed, 241 insertions, 10 deletions
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 6d003e1..4063697 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -94,7 +94,15 @@ const char *cmCompiledGeneratorExpression::Evaluate(
for ( ; it != end; ++it)
{
- this->Output += (*it)->Evaluate(&context, dagChecker);
+ const std::string result = (*it)->Evaluate(&context, dagChecker);
+ this->Output += result;
+
+ for(std::set<cmStdString>::const_iterator
+ p = context.SeenTargetProperties.begin();
+ p != context.SeenTargetProperties.end(); ++p)
+ {
+ this->SeenTargetProperties[*p] += result + ";";
+ }
if (context.HadError)
{
this->Output = "";
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index dcdfefb..b58dde5 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -83,6 +83,9 @@ public:
std::set<cmTarget*> const& GetTargets() const
{ return this->Targets; }
+ std::map<cmStdString, cmStdString> const& GetSeenTargetProperties() const
+ { return this->SeenTargetProperties; }
+
~cmCompiledGeneratorExpression();
std::string GetInput() const
@@ -110,6 +113,7 @@ private:
bool NeedsParsing;
mutable std::set<cmTarget*> Targets;
+ mutable std::map<cmStdString, cmStdString> SeenTargetProperties;
mutable std::string Output;
};
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 82becaf..f4e4131 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -380,6 +380,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
}
+ if (target == context->HeadTarget)
+ {
+ // Keep track of the properties seen while processing.
+ // The evaluation of the LINK_LIBRARIES generator expressions
+ // will check this to ensure that properties form a DAG.
+ context->SeenTargetProperties.insert(propertyName);
+ }
+
if (propertyName.empty())
{
reportError(context, content->GetOriginalExpression(),
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 59804ff..fb6c7ee 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -24,6 +24,7 @@ struct cmGeneratorExpressionContext
{
cmListFileBacktrace Backtrace;
std::set<cmTarget*> Targets;
+ std::set<cmStdString> SeenTargetProperties;
cmMakefile *Makefile;
const char *Config;
cmTarget *HeadTarget; // The target whose property is being evaluated.
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 4c26b82..2cfe4da 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1639,14 +1639,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
if(strcmp(lang, "CXX") == 0)
{
this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName);
- this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, "C");
+ this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target,
+ "C", configName);
}
// Add language-specific flags.
this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName);
// Add shared-library flags if needed.
- this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, lang);
+ this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target,
+ lang, configName);
}
else if(binary)
{
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index b557ca1..ecf6b41 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1984,7 +1984,8 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
//----------------------------------------------------------------------------
void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
- std::string const& lang)
+ std::string const& lang,
+ const char *config)
{
int targetType = target->GetType();
@@ -1997,8 +1998,18 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
}
else
{
- // Add position independendent flags, if needed.
- if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE"))
+ if (target->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE"))
+ {
+ this->AddPositionIndependentFlags(flags, lang, targetType);
+ }
+ return;
+ }
+
+ if (target->GetLinkInterfaceDependentBoolProperty(
+ "POSITION_INDEPENDENT_CODE",
+ config))
{
this->AddPositionIndependentFlags(flags, lang, targetType);
}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 63559d7..b2ff0c4 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -142,7 +142,7 @@ public:
void AddLanguageFlags(std::string& flags, const char* lang,
const char* config);
void AddCMP0018Flags(std::string &flags, cmTarget* target,
- std::string const& lang);
+ std::string const& lang, const char *config);
void AddConfigVariableFlags(std::string& flags, const char* var,
const char* config);
///! Append flags to a string.
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 9bf6b7d..64fcfce 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -268,7 +268,8 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l)
this->AddFortranFlags(flags);
}
- this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang);
+ this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
+ lang, this->ConfigName);
// Add include directory flags.
this->AddIncludeFlags(flags, lang);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 15842e4..0f484da 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -147,7 +147,8 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
// Add shared-library flags if needed.
this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
- language.c_str());
+ language.c_str(),
+ this->GetConfigName());
// Add include directory flags.
{
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 25054c5..2cfb1bf 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -878,6 +878,20 @@ void cmTarget::DefineProperties(cmake *cm)
"created.");
cm->DefineProperty
+ ("INTERFACE_POSITION_INDEPENDENT_CODE", cmProperty::TARGET,
+ "Whether consumers need to create a position-independent target",
+ "The INTERFACE_POSITION_INDEPENDENT_CODE property informs consumers of "
+ "this target whether they must set their POSITION_INDEPENDENT_CODE "
+ "property to ON. If this property is set to ON, then the "
+ "POSITION_INDEPENDENT_CODE property on all consumers will be set to "
+ "ON. Similarly, if this property is set to OFF, then the "
+ "POSITION_INDEPENDENT_CODE property on all consumers will be set to "
+ "OFF. If this property is undefined, then consumers will determine "
+ "their POSITION_INDEPENDENT_CODE property by other means. Consumers "
+ "must ensure that the targets that they link to have a consistent "
+ "requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property.");
+
+ cm->DefineProperty
("POST_INSTALL_SCRIPT", cmProperty::TARGET,
"Deprecated install support.",
"The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
@@ -2164,16 +2178,19 @@ void cmTarget::GetDirectLinkLibraries(const char *config,
{
cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
+ const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
this->GetName(),
"LINK_LIBRARIES", 0, 0);
- cmSystemTools::ExpandListArgument(ge.Parse(prop)->Evaluate(this->Makefile,
+ cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
config,
false,
head,
&dagChecker),
libs);
+
+ this->AddLinkDependentTargetsForProperties(cge->GetSeenTargetProperties());
}
}
@@ -4377,6 +4394,171 @@ const char* cmTarget::GetExportMacro()
}
//----------------------------------------------------------------------------
+void cmTarget::GetLinkDependentTargetsForProperty(const std::string &p,
+ std::set<std::string> &targets)
+{
+ const std::map<cmStdString, std::set<std::string> >::const_iterator findIt
+ = this->LinkDependentProperties.find(p);
+ if (findIt != this->LinkDependentProperties.end())
+ {
+ targets = findIt->second;
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p)
+{
+ return this->LinkImplicitNullProperties.find(p)
+ != this->LinkImplicitNullProperties.end();
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::AddLinkDependentTargetsForProperties(
+ const std::map<cmStdString, cmStdString> &map)
+{
+ for (std::map<cmStdString, cmStdString>::const_iterator it = map.begin();
+ it != map.end(); ++it)
+ {
+ std::vector<std::string> targets;
+ cmSystemTools::ExpandListArgument(it->second.c_str(), targets);
+ this->LinkDependentProperties[it->first].insert(targets.begin(),
+ targets.end());
+ if (!this->GetProperty(it->first.c_str()))
+ {
+ this->LinkImplicitNullProperties.insert(it->first);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
+ const char *config)
+{
+ bool propContent = this->GetPropertyAsBool(p.c_str());
+ const bool explicitlySet = this->GetProperties()
+ .find(p.c_str())
+ != this->GetProperties().end();
+ std::set<std::string> dependentTargets;
+ this->GetLinkDependentTargetsForProperty(p,
+ dependentTargets);
+ const bool impliedByUse =
+ this->IsNullImpliedByLinkLibraries(p);
+ assert((impliedByUse ^ explicitlySet)
+ || (!impliedByUse && !explicitlySet));
+
+ cmComputeLinkInformation *info = this->GetLinkInformation(config);
+ const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
+ bool propInitialized = explicitlySet;
+
+ for(cmComputeLinkInformation::ItemVector::const_iterator li =
+ deps.begin();
+ li != deps.end(); ++li)
+ {
+ // An error should be reported if one dependency
+ // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
+ // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the
+ // target itself has a POSITION_INDEPENDENT_CODE which disagrees
+ // with a dependency.
+
+ if (!li->Target)
+ {
+ continue;
+ }
+
+ const bool ifaceIsSet = li->Target->GetProperties()
+ .find("INTERFACE_" + p)
+ != li->Target->GetProperties().end();
+ const bool ifacePropContent = li->Target->GetPropertyAsBool(
+ ("INTERFACE_" + p).c_str());
+ if (explicitlySet)
+ {
+ if (ifaceIsSet)
+ {
+ if (propContent != ifacePropContent)
+ {
+ cmOStringStream e;
+ e << "Property " << p << " on target \""
+ << this->GetName() << "\" does\nnot match the "
+ "INTERFACE_" << p << " property requirement\nof "
+ "dependency \"" << li->Target->GetName() << "\".\n";
+ cmSystemTools::Error(e.str().c_str());
+ }
+ else
+ {
+ // Agree
+ continue;
+ }
+ }
+ else
+ {
+ // Explicitly set on target and not set in iface. Can't disagree.
+ continue;
+ }
+ }
+ else if (impliedByUse)
+ {
+ if (ifaceIsSet)
+ {
+ if (propContent != ifacePropContent)
+ {
+ cmOStringStream e;
+ e << "Property " << p << " on target \""
+ << this->GetName() << "\" is\nimplied to be FALSE because it "
+ "was used to determine the link libraries\nalready. The "
+ "INTERFACE_" << p << " property on\ndependency \""
+ << li->Target->GetName() << "\" is in conflict.\n";
+ cmSystemTools::Error(e.str().c_str());
+ }
+ else
+ {
+ // Agree
+ continue;
+ }
+ }
+ else
+ {
+ // Implicitly set on target and not set in iface. Can't disagree.
+ continue;
+ }
+ }
+ else
+ {
+ if (ifaceIsSet)
+ {
+ if (propInitialized)
+ {
+ if (propContent != ifacePropContent)
+ {
+ cmOStringStream e;
+ e << "The INTERFACE_" << p << " property of \""
+ << li->Target->GetName() << "\" does\nnot agree with the value "
+ "of " << p << " already determined\nfor \""
+ << this->GetName() << "\".\n";
+ cmSystemTools::Error(e.str().c_str());
+ }
+ else
+ {
+ // Agree.
+ continue;
+ }
+ }
+ else
+ {
+ propContent = ifacePropContent;
+ propInitialized = true;
+ }
+ }
+ else
+ {
+ // Not set. Nothing to agree on.
+ continue;
+ }
+ }
+ }
+ return propContent;
+}
+
+//----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
{
for(std::vector<cmSourceFile*>::const_iterator
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index d4069fa..1188a6a 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -487,6 +487,16 @@ public:
std::vector<std::string> GetIncludeDirectories(const char *config);
void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry,
bool before = false);
+
+ void GetLinkDependentTargetsForProperty(const std::string &p,
+ std::set<std::string> &targets);
+ bool IsNullImpliedByLinkLibraries(const std::string &p);
+
+ void AddLinkDependentTargetsForProperties(
+ const std::map<cmStdString, cmStdString> &map);
+
+ bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
+ const char *config);
private:
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
@@ -596,6 +606,9 @@ private:
bool DLLPlatform;
bool IsApple;
bool IsImportedTarget;
+ mutable std::map<cmStdString, std::set<std::string> >
+ LinkDependentProperties;
+ mutable std::set<std::string> LinkImplicitNullProperties;
// Cache target output paths for each configuration.
struct OutputInfo;