From 36dc8d6d50e0724d6f4bcebdada5610db8dbd698 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 18 Mar 2024 19:28:09 -0400 Subject: Ninja: Fix Fortran module deps in files INCLUDEd by preprocessed sources If a preprocessed source also uses the Fortran `INCLUDE` directive, search the original source file's directory. Fixes: #25792 --- Source/cmGlobalNinjaGenerator.cxx | 21 ++++++++++++++++++--- Source/cmNinjaTargetGenerator.cxx | 15 +++++++++------ Tests/FortranModules/CMakeLists.txt | 2 +- Tests/FortranModules/non_pp_include.f90 | 7 ++++--- Tests/FortranModules/test_non_pp_include_main.f90 | 8 ++++---- Tests/FortranModules/test_non_pp_include_module.f90 | 6 ++++++ 6 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 Tests/FortranModules/test_non_pp_include_module.f90 diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 6acdc34..f350efa 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2327,7 +2327,8 @@ struct cmSourceInfo }; cm::optional cmcmd_cmake_ninja_depends_fortran( - std::string const& arg_tdi, std::string const& arg_src); + std::string const& arg_tdi, std::string const& arg_src, + std::string const& arg_src_orig); } int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, @@ -2335,6 +2336,7 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, { std::string arg_tdi; std::string arg_src; + std::string arg_src_orig; std::string arg_out; std::string arg_dep; std::string arg_obj; @@ -2345,6 +2347,8 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, arg_tdi = arg.substr(6); } else if (cmHasLiteralPrefix(arg, "--src=")) { arg_src = arg.substr(6); + } else if (cmHasLiteralPrefix(arg, "--src-orig=")) { + arg_src_orig = arg.substr(11); } else if (cmHasLiteralPrefix(arg, "--out=")) { arg_out = arg.substr(6); } else if (cmHasLiteralPrefix(arg, "--dep=")) { @@ -2396,7 +2400,7 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, cm::optional info; if (arg_lang == "Fortran") { - info = cmcmd_cmake_ninja_depends_fortran(arg_tdi, arg_src); + info = cmcmd_cmake_ninja_depends_fortran(arg_tdi, arg_src, arg_src_orig); } else { cmSystemTools::Error( cmStrCat("-E cmake_ninja_depends does not understand the ", arg_lang, @@ -2431,13 +2435,24 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, namespace { cm::optional cmcmd_cmake_ninja_depends_fortran( - std::string const& arg_tdi, std::string const& arg_src) + std::string const& arg_tdi, std::string const& arg_src, + std::string const& arg_src_orig) { cm::optional info; cmFortranCompiler fc; std::vector includes; std::string dir_top_bld; std::string module_dir; + + if (!arg_src_orig.empty()) { + // Prepend the original source file's directory as an include directory + // so Fortran INCLUDE statements can look for files in it. + std::string src_orig_dir = cmSystemTools::GetParentDirectory(arg_src_orig); + if (!src_orig_dir.empty()) { + includes.push_back(src_orig_dir); + } + } + { Json::Value tdio; Json::Value const& tdi = tdio; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 58248fc..22cd48b 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -589,13 +590,15 @@ void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language, namespace { // Create the command to run the dependency scanner -std::string GetScanCommand(cm::string_view cmakeCmd, cm::string_view tdi, - cm::string_view lang, cm::string_view srcFile, - cm::string_view ddiFile) +std::string GetScanCommand( + cm::string_view cmakeCmd, cm::string_view tdi, cm::string_view lang, + cm::string_view srcFile, cm::string_view ddiFile, + cm::optional srcOrigFile = cm::nullopt) { return cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi, " --lang=", lang, " --src=", srcFile, " --out=$out", - " --dep=$DEP_FILE --obj=$OBJ_FILE --ddi=", ddiFile); + " --dep=$DEP_FILE --obj=$OBJ_FILE --ddi=", ddiFile, + srcOrigFile ? cmStrCat(" --src-orig=", *srcOrigFile) : ""); } // Helper function to create dependency scanning rule that may or may @@ -759,8 +762,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, for (auto& i : scanCommands) { i = cmStrCat(launcher, i); } - scanCommands.emplace_back(GetScanCommand(cmakeCmd, tdi, lang, "$out", - "$DYNDEP_INTERMEDIATE_FILE")); + scanCommands.emplace_back(GetScanCommand( + cmakeCmd, tdi, lang, "$out", "$DYNDEP_INTERMEDIATE_FILE", "$in")); } auto scanRule = GetScanRule( diff --git a/Tests/FortranModules/CMakeLists.txt b/Tests/FortranModules/CMakeLists.txt index 1e5ff89..61d06d9 100644 --- a/Tests/FortranModules/CMakeLists.txt +++ b/Tests/FortranModules/CMakeLists.txt @@ -67,7 +67,7 @@ add_definitions(-DFOO -DBAR=1) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) add_executable(test_preprocess test_preprocess.F90 test_preprocess_module.F90) -add_executable(test_non_pp_include test_non_pp_include_main.f90) +add_executable(test_non_pp_include test_non_pp_include_main.f90 test_non_pp_include_module.f90) # Build the external project separately using a custom target. # Make sure it uses the same build configuration as this test. diff --git a/Tests/FortranModules/non_pp_include.f90 b/Tests/FortranModules/non_pp_include.f90 index 7eb1725..5c28abc 100644 --- a/Tests/FortranModules/non_pp_include.f90 +++ b/Tests/FortranModules/non_pp_include.f90 @@ -1,3 +1,4 @@ -SUBROUTINE NON_PP_INCLUDE_SUBROUTINE - PRINT *, "Hello World!" -END SUBROUTINE NON_PP_INCLUDE_SUBROUTINE +subroutine non_pp_include_subroutine + use non_pp_include_module + call non_pp_include_module_subroutine +end subroutine diff --git a/Tests/FortranModules/test_non_pp_include_main.f90 b/Tests/FortranModules/test_non_pp_include_main.f90 index 8a04fbd..7236cc9 100644 --- a/Tests/FortranModules/test_non_pp_include_main.f90 +++ b/Tests/FortranModules/test_non_pp_include_main.f90 @@ -1,5 +1,5 @@ -INCLUDE "non_pp_include.f90" +include "non_pp_include.f90" -PROGRAM MAINF90 - CALL NON_PP_INCLUDE_SUBROUTINE -END PROGRAM MAINF90 +program test_non_pp_include_main + call non_pp_include_subroutine +end program diff --git a/Tests/FortranModules/test_non_pp_include_module.f90 b/Tests/FortranModules/test_non_pp_include_module.f90 new file mode 100644 index 0000000..764b7ca --- /dev/null +++ b/Tests/FortranModules/test_non_pp_include_module.f90 @@ -0,0 +1,6 @@ +module non_pp_include_module +contains + subroutine non_pp_include_module_subroutine + print *, "Hello World!" + end subroutine +end module -- cgit v0.12