|  | @@ -238,6 +238,7 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  |                         const GeneratorExpressionContent *,
 | 
	
		
			
				|  |  |                         cmGeneratorExpressionDAGChecker *) const
 | 
	
		
			
				|  |  |    {
 | 
	
		
			
				|  |  | +    context->HadContextSensitiveCondition = true;
 | 
	
		
			
				|  |  |      return context->Config ? context->Config : "";
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  } configurationNode;
 | 
	
	
		
			
				|  | @@ -262,6 +263,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  |                    "Expression syntax not recognized.");
 | 
	
		
			
				|  |  |        return std::string();
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | +    context->HadContextSensitiveCondition = true;
 | 
	
		
			
				|  |  |      if (!context->Config)
 | 
	
		
			
				|  |  |        {
 | 
	
		
			
				|  |  |        return parameters.front().empty() ? "1" : "0";
 | 
	
	
		
			
				|  | @@ -435,6 +437,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  |      case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
 | 
	
		
			
				|  |  |        // No error. We just skip cyclic references.
 | 
	
		
			
				|  |  |        return std::string();
 | 
	
		
			
				|  |  | +    case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
 | 
	
		
			
				|  |  | +      // No error. We're not going to find anything new here.
 | 
	
		
			
				|  |  | +      return std::string();
 | 
	
		
			
				|  |  |      case cmGeneratorExpressionDAGChecker::DAG:
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |        }
 | 
	
	
		
			
				|  | @@ -452,12 +457,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        if (propertyName == "POSITION_INDEPENDENT_CODE")
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | +        context->HadContextSensitiveCondition = true;
 | 
	
		
			
				|  |  |          return target->GetLinkInterfaceDependentBoolProperty(
 | 
	
		
			
				|  |  |                      "POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0";
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
 | 
	
		
			
				|  |  |                                                         context->Config))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | +        context->HadContextSensitiveCondition = true;
 | 
	
		
			
				|  |  |          return target->GetLinkInterfaceDependentBoolProperty(
 | 
	
		
			
				|  |  |                                                  propertyName,
 | 
	
		
			
				|  |  |                                                  context->Config) ? "1" : "0";
 | 
	
	
		
			
				|  | @@ -465,9 +472,12 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  |        if (target->IsLinkInterfaceDependentStringProperty(propertyName,
 | 
	
		
			
				|  |  |                                                           context->Config))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -        return target->GetLinkInterfaceDependentStringProperty(
 | 
	
		
			
				|  |  | +        context->HadContextSensitiveCondition = true;
 | 
	
		
			
				|  |  | +        const char *propContent =
 | 
	
		
			
				|  |  | +                              target->GetLinkInterfaceDependentStringProperty(
 | 
	
		
			
				|  |  |                                                  propertyName,
 | 
	
		
			
				|  |  |                                                  context->Config);
 | 
	
		
			
				|  |  | +        return propContent ? propContent : "";
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        return std::string();
 | 
	
	
		
			
				|  | @@ -481,12 +491,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  |        if (targetPropertyTransitiveWhitelist[i] == propertyName)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |          cmGeneratorExpression ge(context->Backtrace);
 | 
	
		
			
				|  |  | -        return ge.Parse(prop)->Evaluate(context->Makefile,
 | 
	
		
			
				|  |  | +        cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
 | 
	
		
			
				|  |  | +        std::string result = cge->Evaluate(context->Makefile,
 | 
	
		
			
				|  |  |                              context->Config,
 | 
	
		
			
				|  |  |                              context->Quiet,
 | 
	
		
			
				|  |  |                              context->HeadTarget,
 | 
	
		
			
				|  |  |                              target,
 | 
	
		
			
				|  |  |                              &dagChecker);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (cge->GetHadContextSensitiveCondition())
 | 
	
		
			
				|  |  | +          {
 | 
	
		
			
				|  |  | +          context->HadContextSensitiveCondition = true;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      return prop;
 | 
	
	
		
			
				|  | @@ -580,6 +597,9 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  |            "be used with add_custom_command.");
 | 
	
		
			
				|  |  |        return std::string();
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    context->HadContextSensitiveCondition = true;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      for (size_t i = 0;
 | 
	
		
			
				|  |  |           i < (sizeof(targetPolicyWhitelist) /
 | 
	
		
			
				|  |  |                sizeof(*targetPolicyWhitelist));
 | 
	
	
		
			
				|  | @@ -619,19 +639,114 @@ static const struct InstallPrefixNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    InstallPrefixNode() {}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  virtual bool GeneratesContent() const { return false; }
 | 
	
		
			
				|  |  | +  virtual bool GeneratesContent() const { return true; }
 | 
	
		
			
				|  |  |    virtual int NumExpectedParameters() const { return 0; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    std::string Evaluate(const std::vector<std::string> &,
 | 
	
		
			
				|  |  | -                       cmGeneratorExpressionContext *,
 | 
	
		
			
				|  |  | -                       const GeneratorExpressionContent *,
 | 
	
		
			
				|  |  | +                       cmGeneratorExpressionContext *context,
 | 
	
		
			
				|  |  | +                       const GeneratorExpressionContent *content,
 | 
	
		
			
				|  |  |                         cmGeneratorExpressionDAGChecker *) const
 | 
	
		
			
				|  |  |    {
 | 
	
		
			
				|  |  | +    reportError(context, content->GetOriginalExpression(),
 | 
	
		
			
				|  |  | +                "INSTALL_PREFIX is a marker for install(EXPORT) only.  It "
 | 
	
		
			
				|  |  | +                "should never be evaluated.");
 | 
	
		
			
				|  |  |      return std::string();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  } installPrefixNode;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +//----------------------------------------------------------------------------
 | 
	
		
			
				|  |  | +static const struct LinkedNode : public cmGeneratorExpressionNode
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  LinkedNode() {}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  virtual bool GeneratesContent() const { return true; }
 | 
	
		
			
				|  |  | +  virtual int NumExpectedParameters() const { return 1; }
 | 
	
		
			
				|  |  | +  virtual bool RequiresLiteralInput() const { return true; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  std::string Evaluate(const std::vector<std::string> ¶meters,
 | 
	
		
			
				|  |  | +                       cmGeneratorExpressionContext *context,
 | 
	
		
			
				|  |  | +                       const GeneratorExpressionContent *content,
 | 
	
		
			
				|  |  | +                       cmGeneratorExpressionDAGChecker *dagChecker) const
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +    if (dagChecker->EvaluatingIncludeDirectories())
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      return this->GetInterfaceProperty(parameters.front(),
 | 
	
		
			
				|  |  | +                                        "INCLUDE_DIRECTORIES",
 | 
	
		
			
				|  |  | +                                        context, content, dagChecker);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    if (dagChecker->EvaluatingCompileDefinitions())
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      return this->GetInterfaceProperty(parameters.front(),
 | 
	
		
			
				|  |  | +                                        "COMPILE_DEFINITIONS",
 | 
	
		
			
				|  |  | +                                        context, content, dagChecker);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    reportError(context, content->GetOriginalExpression(),
 | 
	
		
			
				|  |  | +                "$<LINKED:...> may only be used in INCLUDE_DIRECTORIES and "
 | 
	
		
			
				|  |  | +                "COMPILE_DEFINITIONS properties.");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return std::string();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +private:
 | 
	
		
			
				|  |  | +  std::string GetInterfaceProperty(const std::string &item,
 | 
	
		
			
				|  |  | +                      const std::string &prop,
 | 
	
		
			
				|  |  | +                      cmGeneratorExpressionContext *context,
 | 
	
		
			
				|  |  | +                      const GeneratorExpressionContent *content,
 | 
	
		
			
				|  |  | +                      cmGeneratorExpressionDAGChecker *dagCheckerParent) const
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +    cmTarget *target = context->CurrentTarget
 | 
	
		
			
				|  |  | +                              ->GetMakefile()->FindTargetToUse(item.c_str());
 | 
	
		
			
				|  |  | +    if (!target)
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      return std::string();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    std::string propertyName = "INTERFACE_" + prop;
 | 
	
		
			
				|  |  | +    const char *propContent = target->GetProperty(propertyName.c_str());
 | 
	
		
			
				|  |  | +    if (!propContent)
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      return std::string();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
 | 
	
		
			
				|  |  | +                                               target->GetName(),
 | 
	
		
			
				|  |  | +                                               propertyName,
 | 
	
		
			
				|  |  | +                                               content,
 | 
	
		
			
				|  |  | +                                               dagCheckerParent);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    switch (dagChecker.check())
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +    case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
 | 
	
		
			
				|  |  | +      dagChecker.reportError(context, content->GetOriginalExpression());
 | 
	
		
			
				|  |  | +      return std::string();
 | 
	
		
			
				|  |  | +    case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
 | 
	
		
			
				|  |  | +      // No error. We just skip cyclic references.
 | 
	
		
			
				|  |  | +      return std::string();
 | 
	
		
			
				|  |  | +    case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
 | 
	
		
			
				|  |  | +      // No error. We're not going to find anything new here.
 | 
	
		
			
				|  |  | +      return std::string();
 | 
	
		
			
				|  |  | +    case cmGeneratorExpressionDAGChecker::DAG:
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    cmGeneratorExpression ge(context->Backtrace);
 | 
	
		
			
				|  |  | +    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propContent);
 | 
	
		
			
				|  |  | +    std::string result = cge->Evaluate(context->Makefile,
 | 
	
		
			
				|  |  | +                        context->Config,
 | 
	
		
			
				|  |  | +                        context->Quiet,
 | 
	
		
			
				|  |  | +                        context->HeadTarget,
 | 
	
		
			
				|  |  | +                        target,
 | 
	
		
			
				|  |  | +                        &dagChecker);
 | 
	
		
			
				|  |  | +    if (cge->GetHadContextSensitiveCondition())
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      context->HadContextSensitiveCondition = true;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    return result;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +} linkedNode;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  //----------------------------------------------------------------------------
 | 
	
		
			
				|  |  |  template<bool linker, bool soname>
 | 
	
		
			
				|  |  |  struct TargetFilesystemArtifactResultCreator
 | 
	
	
		
			
				|  | @@ -869,6 +984,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
 | 
	
		
			
				|  |  |      return &targetDefinedNode;
 | 
	
		
			
				|  |  |    else if (identifier == "INSTALL_PREFIX")
 | 
	
		
			
				|  |  |      return &installPrefixNode;
 | 
	
		
			
				|  |  | +  else if (identifier == "LINKED")
 | 
	
		
			
				|  |  | +    return &linkedNode;
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  }
 |