浏览代码

Refactor per-source generator expression evaluation

Prepare to add generator expression support to more source properties.
Factor out some duplicated code into a helper to avoid further
duplication.
Marc Chevrier 8 年之前
父节点
当前提交
6bffc13ef1

+ 2 - 3
Source/cmExtraSublimeTextGenerator.cxx

@@ -362,9 +362,8 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
 
   // Add source file specific flags.
   if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
-    cmGeneratorExpression ge;
-    const char* processed = ge.Parse(cflags)->Evaluate(lg, config);
-    lg->AppendFlags(flags, processed);
+    cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config);
+    lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags));
   }
 
   return flags;

+ 50 - 0
Source/cmGeneratorExpression.h

@@ -153,4 +153,54 @@ private:
   bool EvaluateForBuildsystem;
 };
 
+class cmGeneratorExpressionInterpreter
+{
+  CM_DISABLE_COPY(cmGeneratorExpressionInterpreter)
+
+public:
+  cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
+                                   cmGeneratorTarget* generatorTarget,
+                                   const std::string& config)
+    : LocalGenerator(localGenerator)
+    , GeneratorTarget(generatorTarget)
+    , Config(config)
+  {
+  }
+
+  const char* Evaluate(const char* expression)
+  {
+    this->CompiledGeneratorExpression =
+      this->GeneratorExpression.Parse(expression);
+
+    return this->CompiledGeneratorExpression->Evaluate(
+      this->LocalGenerator, this->Config, false, this->GeneratorTarget);
+  }
+  const char* Evaluate(const std::string& expression)
+  {
+    return this->Evaluate(expression.c_str());
+  }
+
+protected:
+  cmGeneratorExpression& GetGeneratorExpression()
+  {
+    return this->GeneratorExpression;
+  }
+
+  cmCompiledGeneratorExpression& GetCompiledGeneratorExpression()
+  {
+    return *(this->CompiledGeneratorExpression);
+  }
+
+  cmLocalGenerator* GetLocalGenerator() { return this->LocalGenerator; }
+
+  cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
+
+private:
+  cmGeneratorExpression GeneratorExpression;
+  std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression;
+  cmLocalGenerator* LocalGenerator = nullptr;
+  cmGeneratorTarget* GeneratorTarget = nullptr;
+  std::string Config;
+};
+
 #endif

+ 43 - 18
Source/cmGlobalXCodeGenerator.cxx

@@ -676,9 +676,51 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
   return buildFile;
 }
 
+class XCodeGeneratorExpressionInterpreter
+  : public cmGeneratorExpressionInterpreter
+{
+  CM_DISABLE_COPY(XCodeGeneratorExpressionInterpreter)
+
+public:
+  XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile,
+                                      cmLocalGenerator* localGenerator,
+                                      cmGeneratorTarget* generatorTarget)
+    : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget,
+                                       "NO-PER-CONFIG-SUPPORT-IN-XCODE")
+    , SourceFile(sourceFile)
+  {
+  }
+
+  using cmGeneratorExpressionInterpreter::Evaluate;
+
+  const char* Evaluate(const char* expression, const char* property)
+  {
+    const char* processed = this->Evaluate(expression);
+    if (this->GetCompiledGeneratorExpression()
+          .GetHadContextSensitiveCondition()) {
+      std::ostringstream e;
+      /* clang-format off */
+      e <<
+          "Xcode does not support per-config per-source " << property << ":\n"
+          "  " << expression << "\n"
+          "specified for source:\n"
+          "  " << this->SourceFile->GetFullPath() << "\n";
+      /* clang-format on */
+      this->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str());
+    }
+
+    return processed;
+  }
+
+private:
+  cmSourceFile* SourceFile = nullptr;
+};
+
 cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
   cmLocalGenerator* lg, cmSourceFile* sf, cmGeneratorTarget* gtgt)
 {
+  XCodeGeneratorExpressionInterpreter genexInterpreter(sf, lg, gtgt);
+
   // Add flags from target and source file properties.
   std::string flags;
   const char* srcfmt = sf->GetProperty("Fortran_FORMAT");
@@ -693,24 +735,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
       break;
   }
   if (const char* cflags = sf->GetProperty("COMPILE_FLAGS")) {
-    cmGeneratorExpression ge;
-    std::string configName = "NO-PER-CONFIG-SUPPORT-IN-XCODE";
-    std::unique_ptr<cmCompiledGeneratorExpression> compiledExpr =
-      ge.Parse(cflags);
-    const char* processed =
-      compiledExpr->Evaluate(lg, configName, false, gtgt);
-    if (compiledExpr->GetHadContextSensitiveCondition()) {
-      std::ostringstream e;
-      /* clang-format off */
-      e <<
-        "Xcode does not support per-config per-source COMPILE_FLAGS:\n"
-        "  " << cflags << "\n"
-        "specified for source:\n"
-        "  " << sf->GetFullPath() << "\n";
-      /* clang-format on */
-      lg->IssueMessage(cmake::FATAL_ERROR, e.str());
-    }
-    lg->AppendFlags(flags, processed);
+    lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, "COMPILE_FLAGS"));
   }
 
   // Add per-source definitions.

+ 2 - 3
Source/cmLocalVisualStudio7Generator.cxx

@@ -1456,15 +1456,14 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
        i != configs.end(); ++i, ++ci) {
     std::string configUpper = cmSystemTools::UpperCase(*i);
     cmLVS7GFileConfig fc;
+    cmGeneratorExpressionInterpreter genexInterpreter(lg, gt, *i);
     bool needfc = false;
     if (!objectName.empty()) {
       fc.ObjectName = objectName;
       needfc = true;
     }
     if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
-      cmGeneratorExpression ge;
-      std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
-      fc.CompileFlags = cge->Evaluate(lg, *i, false, gt);
+      fc.CompileFlags = genexInterpreter.Evaluate(cflags);
       needfc = true;
     }
     if (lg->FortranProject) {

+ 3 - 4
Source/cmMakefileTargetGenerator.cxx

@@ -425,6 +425,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
 
   std::string config = this->LocalGenerator->GetConfigName();
   std::string configUpper = cmSystemTools::UpperCase(config);
+  cmGeneratorExpressionInterpreter genexInterpreter(
+    this->LocalGenerator, this->GeneratorTarget, config);
 
   // Add Fortran format flags.
   if (lang == "Fortran") {
@@ -433,10 +435,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
 
   // Add flags from source file properties.
   if (const char* cflags = source.GetProperty("COMPILE_FLAGS")) {
-    cmGeneratorExpression ge;
-    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
-    const char* evaluatedFlags = cge->Evaluate(this->LocalGenerator, config,
-                                               false, this->GeneratorTarget);
+    const char* evaluatedFlags = genexInterpreter.Evaluate(cflags);
     this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
     *this->FlagFileStream << "# Custom flags: " << relativeObj
                           << "_FLAGS = " << evaluatedFlags << "\n"

+ 5 - 6
Source/cmNinjaTargetGenerator.cxx

@@ -136,12 +136,11 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
 
   // Add source file specific flags.
   if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
-    std::string config = this->LocalGenerator->GetConfigName();
-    cmGeneratorExpression ge;
-    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
-    const char* evaluatedFlags = cge->Evaluate(this->LocalGenerator, config,
-                                               false, this->GeneratorTarget);
-    this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
+    cmGeneratorExpressionInterpreter genexInterpreter(
+      this->LocalGenerator, this->GeneratorTarget,
+      this->LocalGenerator->GetConfigName());
+    this->LocalGenerator->AppendFlags(flags,
+                                      genexInterpreter.Evaluate(cflags));
   }
 
   return flags;

+ 3 - 5
Source/cmServerProtocol.cxx

@@ -692,6 +692,8 @@ static Json::Value DumpSourceFilesList(
 
   std::vector<cmSourceFile*> files;
   target->GetSourceFiles(files, config);
+  cmGeneratorExpressionInterpreter genexInterpreter(
+    target->GetLocalGenerator(), target, config);
 
   std::unordered_map<LanguageData, std::vector<std::string>> fileGroups;
   for (cmSourceFile* file : files) {
@@ -703,11 +705,7 @@ static Json::Value DumpSourceFilesList(
 
       std::string compileFlags = ld.Flags;
       if (const char* cflags = file->GetProperty("COMPILE_FLAGS")) {
-        cmGeneratorExpression ge;
-        auto cge = ge.Parse(cflags);
-        const char* processed =
-          cge->Evaluate(target->GetLocalGenerator(), config);
-        lg->AppendFlags(compileFlags, processed);
+        lg->AppendFlags(compileFlags, genexInterpreter.Evaluate(cflags));
       }
       fileData.Flags = compileFlags;
 

+ 6 - 11
Source/cmVisualStudio10TargetGenerator.cxx

@@ -2062,10 +2062,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
   bool configDependentFlags = false;
   std::string defines;
   if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
-
-    if (cmGeneratorExpression::Find(cflags) != std::string::npos) {
-      configDependentFlags = true;
-    }
+    configDependentFlags =
+      cmGeneratorExpression::Find(cflags) != std::string::npos;
     flags += cflags;
   }
   if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
@@ -2122,8 +2120,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
     }
     // if we have flags or defines for this config then
     // use them
-    if (!flags.empty() || configDependentFlags || !configDefines.empty() ||
-        compileAs || noWinRT) {
+    if (!flags.empty() || !configDefines.empty() || compileAs || noWinRT) {
       (*this->BuildFileStream) << firstString;
       firstString = ""; // only do firstString once
       hasFlags = true;
@@ -2144,6 +2141,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
       } else if (srclang == "CSharp") {
         flagtable = gg->GetCSharpFlagTable();
       }
+      cmGeneratorExpressionInterpreter genexInterpreter(
+        this->LocalGenerator, this->GeneratorTarget, *config);
       cmVisualStudioGeneratorOptions clOptions(
         this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
         flagtable, 0, this);
@@ -2154,11 +2153,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
         clOptions.AddFlag("CompileAsWinRT", "false");
       }
       if (configDependentFlags) {
-        cmGeneratorExpression ge;
-        std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(flags);
-        std::string evaluatedFlags = cge->Evaluate(
-          this->LocalGenerator, *config, false, this->GeneratorTarget);
-        clOptions.Parse(evaluatedFlags.c_str());
+        clOptions.Parse(genexInterpreter.Evaluate(flags));
       } else {
         clOptions.Parse(flags.c_str());
       }