Преглед изворни кода

Ninja: Add helper functions to generate Fortran preprocess rule

Peter Hill пре 5 година
родитељ
комит
5cca1ec893
1 измењених фајлова са 98 додато и 69 уклоњено
  1. 98 69
      Source/cmNinjaTargetGenerator.cxx

+ 98 - 69
Source/cmNinjaTargetGenerator.cxx

@@ -509,6 +509,91 @@ void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language,
   this->WriteCompileRule(language, config);
 }
 
+namespace {
+// Create the command to run the dependency scanner
+std::string GetScanCommand(const std::string& cmakeCmd, const std::string& tdi,
+                           const std::string& lang, const std::string& ppFile,
+                           bool needDyndep, const std::string& ddiFile)
+{
+  std::string ccmd =
+    cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi, " --lang=", lang,
+             " --pp=", ppFile, " --dep=$DEP_FILE");
+  if (needDyndep) {
+    ccmd = cmStrCat(ccmd, " --obj=$OBJ_FILE --ddi=", ddiFile);
+  }
+  return ccmd;
+}
+
+// Helper function to create dependency scanning rule, with optional
+// explicit preprocessing step if preprocessCommand is non-empty
+cmNinjaRule GetPreprocessScanRule(
+  const std::string& ruleName, cmRulePlaceholderExpander::RuleVariables& vars,
+  const std::string& responseFlag, const std::string& flags,
+  const std::string& launcher,
+  cmRulePlaceholderExpander* const rulePlaceholderExpander,
+  std::string scanCommand, cmLocalNinjaGenerator* generator,
+  const std::string& preprocessCommand = "")
+{
+  cmNinjaRule rule(ruleName);
+  // Explicit preprocessing always uses a depfile.
+  rule.DepType = ""; // no deps= for multiple outputs
+  rule.DepFile = "$DEP_FILE";
+
+  cmRulePlaceholderExpander::RuleVariables ppVars;
+  ppVars.CMTargetName = vars.CMTargetName;
+  ppVars.CMTargetType = vars.CMTargetType;
+  ppVars.Language = vars.Language;
+  ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
+  ppVars.PreprocessedSource = "$out";
+  ppVars.DependencyFile = rule.DepFile.c_str();
+
+  // Preprocessing uses the original source, compilation uses
+  // preprocessed output or original source
+  ppVars.Source = vars.Source;
+  vars.Source = "$in";
+
+  // Copy preprocessor definitions to the preprocessor rule.
+  ppVars.Defines = vars.Defines;
+
+  // Copy include directories to the preprocessor rule.  The Fortran
+  // compilation rule still needs them for the INCLUDE directive.
+  ppVars.Includes = vars.Includes;
+
+  // Preprocessing and compilation use the same flags.
+  std::string ppFlags = flags;
+
+  // If using a response file, move defines, includes, and flags into it.
+  if (!responseFlag.empty()) {
+    rule.RspFile = "$RSP_FILE";
+    rule.RspContent =
+      cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags);
+    ppFlags = cmStrCat(responseFlag, rule.RspFile);
+    ppVars.Defines = "";
+    ppVars.Includes = "";
+  }
+
+  ppVars.Flags = ppFlags.c_str();
+
+  // Rule for preprocessing source file.
+  std::vector<std::string> ppCmds;
+
+  if (!preprocessCommand.empty()) {
+    // Lookup the explicit preprocessing rule.
+    cmExpandList(preprocessCommand, ppCmds);
+    for (std::string& i : ppCmds) {
+      i = cmStrCat(launcher, i);
+      rulePlaceholderExpander->ExpandRuleVariables(generator, i, ppVars);
+    }
+  }
+
+  // Run CMake dependency scanner on either preprocessed output or source file
+  ppCmds.emplace_back(std::move(scanCommand));
+  rule.Command = generator->BuildCommandLine(ppCmds);
+
+  return rule;
+}
+}
+
 void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
                                               const std::string& config)
 {
@@ -566,82 +651,26 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
       cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
 
   if (explicitPP) {
-    cmNinjaRule rule(this->LanguagePreprocessRule(lang, config));
-    // Explicit preprocessing always uses a depfile.
-    rule.DepType = ""; // no deps= for multiple outputs
-    rule.DepFile = "$DEP_FILE";
+    // Combined preprocessing and dependency scanning
+    const auto ppScanCommand = GetScanCommand(
+      cmakeCmd, tdi, lang, "$out", needDyndep, "$DYNDEP_INTERMEDIATE_FILE");
+    const auto ppVar = cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE");
 
-    cmRulePlaceholderExpander::RuleVariables ppVars;
-    ppVars.CMTargetName = vars.CMTargetName;
-    ppVars.CMTargetType = vars.CMTargetType;
-    ppVars.Language = vars.Language;
-    ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
-    ppVars.PreprocessedSource = "$out";
-    ppVars.DependencyFile = rule.DepFile.c_str();
+    auto ppRule = GetPreprocessScanRule(
+      this->LanguagePreprocessRule(lang, config), vars, responseFlag, flags,
+      launcher, rulePlaceholderExpander.get(), ppScanCommand,
+      this->GetLocalGenerator(), mf->GetRequiredDefinition(ppVar));
 
-    // Preprocessing uses the original source,
-    // compilation uses preprocessed output.
-    ppVars.Source = vars.Source;
-    vars.Source = "$in";
+    // Write the rule for preprocessing file of the given language.
+    ppRule.Comment = cmStrCat("Rule for preprocessing ", lang, " files.");
+    ppRule.Description = cmStrCat("Building ", lang, " preprocessed $out");
 
-    // Preprocessing and compilation use the same flags.
-    std::string ppFlags = flags;
+    this->GetGlobalGenerator()->AddRule(ppRule);
 
     if (!compilePPWithDefines) {
-      // Move preprocessor definitions to the preprocessor rule.
-      ppVars.Defines = vars.Defines;
+      // Remove preprocessor definitions from compilation step
       vars.Defines = "";
-    } else {
-      // Copy preprocessor definitions to the preprocessor rule.
-      ppVars.Defines = vars.Defines;
-    }
-
-    // Copy include directories to the preprocessor rule.  The Fortran
-    // compilation rule still needs them for the INCLUDE directive.
-    ppVars.Includes = vars.Includes;
-
-    // If using a response file, move defines, includes, and flags into it.
-    if (!responseFlag.empty()) {
-      rule.RspFile = "$RSP_FILE";
-      rule.RspContent =
-        cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags);
-      ppFlags = cmStrCat(responseFlag, rule.RspFile);
-      ppVars.Defines = "";
-      ppVars.Includes = "";
-    }
-
-    ppVars.Flags = ppFlags.c_str();
-
-    // Rule for preprocessing source file.
-    std::vector<std::string> ppCmds;
-    {
-      // Lookup the explicit preprocessing rule.
-      std::string ppVar = cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE");
-      cmExpandList(this->GetMakefile()->GetRequiredDefinition(ppVar), ppCmds);
-    }
-
-    for (std::string& i : ppCmds) {
-      i = cmStrCat(launcher, i);
-      rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
-                                                   i, ppVars);
-    }
-
-    // Run CMake dependency scanner on preprocessed output.
-    {
-      std::string ccmd =
-        cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi,
-                 " --lang=", lang, " --pp=$out --dep=$DEP_FILE");
-      if (needDyndep) {
-        ccmd += " --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE";
-      }
-      ppCmds.emplace_back(std::move(ccmd));
     }
-    rule.Command = this->GetLocalGenerator()->BuildCommandLine(ppCmds);
-
-    // Write the rule for preprocessing file of the given language.
-    rule.Comment = cmStrCat("Rule for preprocessing ", lang, " files.");
-    rule.Description = cmStrCat("Building ", lang, " preprocessed $out");
-    this->GetGlobalGenerator()->AddRule(rule);
   }
 
   if (needDyndep) {