summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/prop_sf/Fortran_PREPROCESS.rst5
-rw-r--r--Help/prop_tgt/Fortran_PREPROCESS.rst5
-rw-r--r--Source/cmNinjaTargetGenerator.cxx64
-rw-r--r--Source/cmNinjaTargetGenerator.h2
-rw-r--r--Tests/FortranOnly/CMakeLists.txt46
5 files changed, 88 insertions, 34 deletions
diff --git a/Help/prop_sf/Fortran_PREPROCESS.rst b/Help/prop_sf/Fortran_PREPROCESS.rst
index 92542d9..25ea827 100644
--- a/Help/prop_sf/Fortran_PREPROCESS.rst
+++ b/Help/prop_sf/Fortran_PREPROCESS.rst
@@ -8,5 +8,10 @@ should be preprocessed. If explicitly set to ``OFF`` then the file
does not need to be preprocessed. If explicitly set to ``ON``, then
the file does need to be preprocessed as part of the compilation step.
+When using the :generator:`Ninja` generator, all source files are
+first preprocessed in order to generate module dependency
+information. Setting this property to ``OFF`` will make ``Ninja``
+skip this step.
+
Consider using the target-wide :prop_tgt:`Fortran_PREPROCESS` property
if all source files in a target need to be preprocessed.
diff --git a/Help/prop_tgt/Fortran_PREPROCESS.rst b/Help/prop_tgt/Fortran_PREPROCESS.rst
index 069d04a..47a15c0 100644
--- a/Help/prop_tgt/Fortran_PREPROCESS.rst
+++ b/Help/prop_tgt/Fortran_PREPROCESS.rst
@@ -9,6 +9,11 @@ should be preprocessed. If explicitly set to ``OFF`` then the file does not
need to be preprocessed. If explicitly set to ``ON``, then the file does
need to be preprocessed as part of the compilation step.
+When using the :generator:`Ninja` generator, all source files are
+first preprocessed in order to generate module dependency
+information. Setting this property to ``OFF`` will make ``Ninja``
+skip this step.
+
Use the source-specific :prop_sf:`Fortran_PREPROCESS` property if a single
file needs to be preprocessed. If the variable
:variable:`CMAKE_Fortran_PREPROCESS` is set when a target is created its
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 63e95ee..a499bc8 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -106,7 +106,16 @@ std::string cmNinjaTargetGenerator::LanguagePreprocessRule(
std::string const& lang, const std::string& config) const
{
return cmStrCat(
- lang, "_PREPROCESS__",
+ lang, "_PREPROCESS_SCAN__",
+ cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()),
+ '_', config);
+}
+
+std::string cmNinjaTargetGenerator::LanguageDependencyRule(
+ std::string const& lang, const std::string& config) const
+{
+ return cmStrCat(
+ lang, "_SCAN__",
cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()),
'_', config);
}
@@ -671,6 +680,22 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
// Remove preprocessor definitions from compilation step
vars.Defines = "";
}
+
+ // Just dependency scanning for files that have preprocessing turned off
+ const auto scanCommand =
+ GetScanCommand(cmakeCmd, tdi, lang, "$in", needDyndep, "$out");
+
+ auto scanRule = GetPreprocessScanRule(
+ this->LanguageDependencyRule(lang, config), vars, "", flags, launcher,
+ rulePlaceholderExpander.get(), scanCommand, this->GetLocalGenerator());
+
+ // Write the rule for generating dependencies for the given language.
+ scanRule.Comment = cmStrCat("Rule for generating ", lang,
+ " dependencies on non-preprocessed files.");
+ scanRule.Description =
+ cmStrCat("Generating ", lang, " dependencies for $in");
+
+ this->GetGlobalGenerator()->AddRule(scanRule);
}
if (needDyndep) {
@@ -1091,8 +1116,12 @@ cmNinjaBuild GetPreprocessOrScanBuild(
// Tell dependency scanner where to store dyndep intermediate results.
std::string const ddiFile = cmStrCat(objectFileName, ".ddi");
- ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
- ppBuild.ImplicitOuts.push_back(ddiFile);
+ if (ppFileName.empty()) {
+ ppBuild.Outputs.push_back(ddiFile);
+ } else {
+ ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
+ ppBuild.ImplicitOuts.push_back(ddiFile);
+ }
}
return ppBuild;
}
@@ -1237,19 +1266,34 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
bool const explicitPP = this->NeedExplicitPreprocessing(language);
if (explicitPP) {
- bool const compilePP = this->UsePreprocessedSource(language);
+ // If source/target has preprocessing turned off, we still need to
+ // generate an explicit dependency step
+ const auto srcpp = source->GetSafeProperty("Fortran_PREPROCESS");
+ cmOutputConverter::FortranPreprocess preprocess =
+ cmOutputConverter::GetFortranPreprocess(srcpp);
+ if (preprocess == cmOutputConverter::FortranPreprocess::Unset) {
+ const auto& tgtpp =
+ this->GeneratorTarget->GetSafeProperty("Fortran_PREPROCESS");
+ preprocess = cmOutputConverter::GetFortranPreprocess(tgtpp);
+ }
+
+ bool const compilePP = this->UsePreprocessedSource(language) &&
+ (preprocess != cmOutputConverter::FortranPreprocess::NotNeeded);
bool const compilePPWithDefines =
compilePP && this->CompilePreprocessedSourceWithDefines(language);
- std::string const ppFileName =
- this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config));
+ std::string const ppFileName = compilePP
+ ? this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config))
+ : "";
- std::string const buildName =
- this->LanguagePreprocessRule(language, config);
+ std::string const buildName = compilePP
+ ? this->LanguagePreprocessRule(language, config)
+ : this->LanguageDependencyRule(language, config);
+ const auto depExtension = compilePP ? ".pp.d" : ".d";
const std::string depFileName =
this->GetLocalGenerator()->ConvertToOutputFormat(
- cmStrCat(objectFileName, ".pp.d"), cmOutputConverter::SHELL);
+ cmStrCat(objectFileName, depExtension), cmOutputConverter::SHELL);
cmNinjaBuild ppBuild = GetPreprocessOrScanBuild(
buildName, ppFileName, compilePP, compilePPWithDefines, objBuild, vars,
@@ -1276,7 +1320,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
if (firstForConfig && needDyndep) {
- const std::string& ddiFile = ppBuild.ImplicitOuts.back();
+ std::string const ddiFile = cmStrCat(objectFileName, ".ddi");
this->Configs[config].DDIFiles[language].push_back(ddiFile);
}
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 8678dc3..2e0a511 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -70,6 +70,8 @@ protected:
const std::string& config) const;
std::string LanguagePreprocessRule(std::string const& lang,
const std::string& config) const;
+ std::string LanguageDependencyRule(std::string const& lang,
+ const std::string& config) const;
bool NeedExplicitPreprocessing(std::string const& lang) const;
std::string LanguageDyndepRule(std::string const& lang,
const std::string& config) const;
diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt
index 59f139b..d24df2d 100644
--- a/Tests/FortranOnly/CMakeLists.txt
+++ b/Tests/FortranOnly/CMakeLists.txt
@@ -135,29 +135,27 @@ if(test_pp_flags)
set_property(SOURCE preprocess3.f PROPERTY Fortran_PREPROCESS ON)
endif()
-if(NOT CMAKE_GENERATOR MATCHES "Ninja")
- # Test that neither the compiler nor CMake performs unnecessary preprocessing.
- add_library(no_preprocess_target_lower STATIC no_preprocess_target_lower.f)
- target_compile_options(no_preprocess_target_lower PRIVATE -DINTEGER=nonsense)
- set_property(TARGET no_preprocess_target_lower PROPERTY Fortran_PREPROCESS OFF)
- add_library(no_preprocess_source_lower STATIC no_preprocess_source_lower.f)
- target_compile_options(no_preprocess_source_lower PRIVATE -DINTEGER=nonsense)
- set_property(SOURCE no_preprocess_source_lower.f PROPERTY Fortran_PREPROCESS OFF)
-
- # Test that we can explicitly not preprocess a target or source.
- # This will not work on certain compilers due to either missing a
- # "don't preprocess" flag, or due to choice of file extension.
- if(test_pp_flags AND NOT CMAKE_Fortran_COMPILER_ID MATCHES "(Flang|NAG|PGI|SunPro|XL)")
- add_library(no_preprocess_target STATIC no_preprocess_target_upper.F)
- target_compile_options(no_preprocess_target PRIVATE -DINTEGER=nonsense)
- add_library(no_preprocess_source STATIC no_preprocess_source_upper.F)
- target_compile_options(no_preprocess_source PRIVATE -DINTEGER=nonsense)
- if(NOT CMAKE_Fortran_COMPILER_ID STREQUAL "Cray"
- AND NOT "${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "Intel;MSVC")
- target_sources(no_preprocess_target PRIVATE no_preprocess_target_fpp.fpp)
- target_sources(no_preprocess_source PRIVATE no_preprocess_source_fpp.fpp)
- endif()
- set_property(TARGET no_preprocess_target PROPERTY Fortran_PREPROCESS OFF)
- set_property(SOURCE no_preprocess_source_upper.F no_preprocess_source_fpp.fpp PROPERTY Fortran_PREPROCESS OFF)
+# Test that neither the compiler nor CMake performs unnecessary preprocessing.
+add_library(no_preprocess_target_lower STATIC no_preprocess_target_lower.f)
+target_compile_options(no_preprocess_target_lower PRIVATE -DINTEGER=nonsense)
+set_property(TARGET no_preprocess_target_lower PROPERTY Fortran_PREPROCESS OFF)
+add_library(no_preprocess_source_lower STATIC no_preprocess_source_lower.f)
+target_compile_options(no_preprocess_source_lower PRIVATE -DINTEGER=nonsense)
+set_property(SOURCE no_preprocess_source_lower.f PROPERTY Fortran_PREPROCESS OFF)
+
+# Test that we can explicitly not preprocess a target or source.
+# This will not work on certain compilers due to either missing a
+# "don't preprocess" flag, or due to choice of file extension.
+if(test_pp_flags AND NOT CMAKE_Fortran_COMPILER_ID MATCHES "(Flang|NAG|PGI|SunPro|XL)")
+ add_library(no_preprocess_target STATIC no_preprocess_target_upper.F)
+ target_compile_options(no_preprocess_target PRIVATE -DINTEGER=nonsense)
+ add_library(no_preprocess_source STATIC no_preprocess_source_upper.F)
+ target_compile_options(no_preprocess_source PRIVATE -DINTEGER=nonsense)
+ if(NOT CMAKE_Fortran_COMPILER_ID STREQUAL "Cray"
+ AND NOT "${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "Intel;MSVC")
+ target_sources(no_preprocess_target PRIVATE no_preprocess_target_fpp.fpp)
+ target_sources(no_preprocess_source PRIVATE no_preprocess_source_fpp.fpp)
endif()
+ set_property(TARGET no_preprocess_target PROPERTY Fortran_PREPROCESS OFF)
+ set_property(SOURCE no_preprocess_source_upper.F no_preprocess_source_fpp.fpp PROPERTY Fortran_PREPROCESS OFF)
endif()