mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 19:08:07 +08:00
Ninja: Skip Fortran preprocessing if Fortran_PREPROCESS is OFF
If `Fortran_PREPROCESS` is explicitly turned off for a source file then we know it does not need to be preprocessed. Teach the Ninja generator to skip preprocessing in this case. Otherwise we still must preprocess just in case. Fixes: #18870
This commit is contained in:
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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 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 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()
|
||||
|
Reference in New Issue
Block a user