mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-09 23:59:53 -05:00
Ninja: Fix Fortran INCLUDE directive dependencies when not preprocessing
Since commit b0a6161190 (Fortran: Add Fortran_PREPROCESS property,
2020-04-24, v3.18.0-rc1~116^2~3), if `Fortran_PREPROCESS` is `OFF`, the
Ninja generator does not properly detect dependencies on sources loaded
via the Fortran INCLUDE directive. Fix this and add a test.
This commit is contained in:
@@ -2227,7 +2227,7 @@ Compilation of source files within a target is split into the following steps:
|
||||
command = gfortran -cpp $DEFINES $INCLUDES $FLAGS -E $in -o $out &&
|
||||
cmake -E cmake_ninja_depends \
|
||||
--tdi=FortranDependInfo.json --lang=Fortran \
|
||||
--src=$out --dep=$DEP_FILE --obj=$OBJ_FILE \
|
||||
--src=$out --out=$out --dep=$DEP_FILE --obj=$OBJ_FILE \
|
||||
--ddi=$DYNDEP_INTERMEDIATE_FILE
|
||||
|
||||
build src.f90-pp.f90 | src.f90.o.ddi: Fortran_PREPROCESS src.f90
|
||||
@@ -2304,6 +2304,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
|
||||
{
|
||||
std::string arg_tdi;
|
||||
std::string arg_src;
|
||||
std::string arg_out;
|
||||
std::string arg_dep;
|
||||
std::string arg_obj;
|
||||
std::string arg_ddi;
|
||||
@@ -2313,6 +2314,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
|
||||
arg_tdi = arg.substr(6);
|
||||
} else if (cmHasLiteralPrefix(arg, "--src=")) {
|
||||
arg_src = arg.substr(6);
|
||||
} else if (cmHasLiteralPrefix(arg, "--out=")) {
|
||||
arg_out = arg.substr(6);
|
||||
} else if (cmHasLiteralPrefix(arg, "--dep=")) {
|
||||
arg_dep = arg.substr(6);
|
||||
} else if (cmHasLiteralPrefix(arg, "--obj=")) {
|
||||
@@ -2322,8 +2325,9 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
|
||||
} else if (cmHasLiteralPrefix(arg, "--lang=")) {
|
||||
arg_lang = arg.substr(7);
|
||||
} else if (cmHasLiteralPrefix(arg, "--pp=")) {
|
||||
// CMake 3.26 and below used '--pp=' instead of '--src='.
|
||||
// CMake 3.26 and below used '--pp=' instead of '--src=' and '--out='.
|
||||
arg_src = arg.substr(5);
|
||||
arg_out = arg_src;
|
||||
} else {
|
||||
cmSystemTools::Error(
|
||||
cmStrCat("-E cmake_ninja_depends unknown argument: ", arg));
|
||||
@@ -2338,6 +2342,10 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
|
||||
cmSystemTools::Error("-E cmake_ninja_depends requires value for --src=");
|
||||
return 1;
|
||||
}
|
||||
if (arg_out.empty()) {
|
||||
cmSystemTools::Error("-E cmake_ninja_depends requires value for --out=");
|
||||
return 1;
|
||||
}
|
||||
if (arg_dep.empty()) {
|
||||
cmSystemTools::Error("-E cmake_ninja_depends requires value for --dep=");
|
||||
return 1;
|
||||
@@ -2374,7 +2382,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
|
||||
|
||||
{
|
||||
cmGeneratedFileStream depfile(arg_dep);
|
||||
depfile << cmSystemTools::ConvertToUnixOutputPath(arg_src) << ":";
|
||||
depfile << cmSystemTools::ConvertToUnixOutputPath(arg_out) << ":";
|
||||
for (std::string const& include : info->Includes) {
|
||||
depfile << " \\\n " << cmSystemTools::ConvertToUnixOutputPath(include);
|
||||
}
|
||||
|
||||
@@ -545,7 +545,7 @@ std::string GetScanCommand(cm::string_view cmakeCmd, cm::string_view tdi,
|
||||
cm::string_view ddiFile)
|
||||
{
|
||||
return cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi,
|
||||
" --lang=", lang, " --src=", srcFile,
|
||||
" --lang=", lang, " --src=", srcFile, " --out=$out",
|
||||
" --dep=$DEP_FILE --obj=$OBJ_FILE --ddi=", ddiFile);
|
||||
}
|
||||
|
||||
@@ -1258,6 +1258,7 @@ namespace {
|
||||
cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
|
||||
const std::string& ppFileName,
|
||||
bool compilePP, bool compilePPWithDefines,
|
||||
bool compilationPreprocesses,
|
||||
cmNinjaBuild& objBuild, cmNinjaVars& vars,
|
||||
const std::string& objectFileName,
|
||||
cmLocalGenerator* lg)
|
||||
@@ -1314,6 +1315,13 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
|
||||
} else {
|
||||
scanBuild.Outputs.push_back(ddiFile);
|
||||
scanBuild.Variables["PREPROCESSED_OUTPUT_FILE"] = ppFileName;
|
||||
if (!compilationPreprocesses) {
|
||||
// Compilation does not preprocess and we are not compiling an
|
||||
// already-preprocessed source. Make compilation depend on the scan
|
||||
// results to honor implicit dependencies discovered during scanning
|
||||
// (such as Fortran INCLUDE directives).
|
||||
objBuild.ImplicitDeps.emplace_back(ddiFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Scanning always provides a depfile for preprocessor dependencies. This
|
||||
@@ -1520,8 +1528,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
|
||||
}
|
||||
|
||||
cmNinjaBuild ppBuild = GetScanBuildStatement(
|
||||
scanRuleName, ppFileName, compilePP, compilePPWithDefines, objBuild,
|
||||
vars, objectFileName, this->LocalGenerator);
|
||||
scanRuleName, ppFileName, compilePP, compilePPWithDefines,
|
||||
compilationPreprocesses, objBuild, vars, objectFileName,
|
||||
this->LocalGenerator);
|
||||
|
||||
if (compilePP) {
|
||||
// In case compilation requires flags that are incompatible with
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.*
|
||||
@@ -0,0 +1 @@
|
||||
.*
|
||||
@@ -0,0 +1,20 @@
|
||||
enable_language(Fortran)
|
||||
|
||||
set(check_pairs "")
|
||||
|
||||
add_executable(preprocess FortranIncludePreprocess.F)
|
||||
set_property(TARGET preprocess PROPERTY Fortran_PREPROCESS ON)
|
||||
target_include_directories(preprocess PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
list(APPEND check_pairs "$<TARGET_FILE:preprocess>|${CMAKE_CURRENT_BINARY_DIR}/preprocess.inc")
|
||||
|
||||
# LCC < 1.24 has no way to disable Fortran preprocessor
|
||||
if(NOT CMAKE_Fortran_COMPILER_ID STREQUAL "LCC" OR CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL "1.24.00")
|
||||
add_executable(no_preprocess FortranIncludeNoPreprocess.f)
|
||||
set_property(TARGET no_preprocess PROPERTY Fortran_PREPROCESS OFF)
|
||||
target_include_directories(no_preprocess PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
list(APPEND check_pairs "$<TARGET_FILE:no_preprocess>|${CMAKE_CURRENT_BINARY_DIR}/no_preprocess.inc")
|
||||
endif()
|
||||
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
|
||||
set(check_pairs \"${check_pairs}\")
|
||||
")
|
||||
@@ -0,0 +1,2 @@
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/preprocess.inc" "\tPRINT *, 'FortranIncludePreprocess 1'\n")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/no_preprocess.inc" "\tPRINT *, 'FortranIncludeNoPreprocess 1'\n")
|
||||
@@ -0,0 +1,2 @@
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/preprocess.inc" "\tPRINT *, 'FortranIncludePreprocess 2'\n")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/no_preprocess.inc" "\tPRINT *, 'FortranIncludeNoPreprocess 2'\n")
|
||||
@@ -0,0 +1,3 @@
|
||||
PROGRAM FortranIncludeNoPreprocess
|
||||
INCLUDE 'no_preprocess.inc'
|
||||
END
|
||||
@@ -0,0 +1,3 @@
|
||||
PROGRAM FortranIncludePreprocess
|
||||
#include "preprocess.inc"
|
||||
END
|
||||
@@ -68,6 +68,10 @@ if(NOT RunCMake_GENERATOR STREQUAL "Xcode")
|
||||
unset(run_BuildDepends_skip_step_2)
|
||||
endif()
|
||||
|
||||
if(CMake_TEST_Fortran)
|
||||
run_BuildDepends(FortranInclude)
|
||||
endif()
|
||||
|
||||
run_BuildDepends(Custom-Symbolic-and-Byproduct)
|
||||
run_BuildDepends(Custom-Always)
|
||||
|
||||
|
||||
@@ -292,6 +292,10 @@ if(NOT DEFINED CMake_TEST_BuildDepends_GNU_AS
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_Fortran_COMPILER)
|
||||
list(APPEND BuildDepends_ARGS -DCMake_TEST_Fortran=1)
|
||||
endif()
|
||||
|
||||
add_RunCMake_test(BuildDepends
|
||||
-DMSVC_VERSION=${MSVC_VERSION}
|
||||
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||
|
||||
Reference in New Issue
Block a user