Browse Source

Fortran: Add Fortran_PREPROCESS property

Issue: #18870
Peter Hill 5 years ago
parent
commit
b0a6161190
37 changed files with 243 additions and 4 deletions
  1. 2 0
      Auxiliary/vim/syntax/cmake.vim
  2. 2 0
      Help/manual/cmake-properties.7.rst
  3. 1 0
      Help/manual/cmake-variables.7.rst
  4. 6 4
      Help/prop_sf/Fortran_FORMAT.rst
  5. 12 0
      Help/prop_sf/Fortran_PREPROCESS.rst
  6. 18 0
      Help/prop_tgt/Fortran_PREPROCESS.rst
  7. 6 0
      Help/release/dev/fortran-preprocess-property.rst
  8. 8 0
      Help/variable/CMAKE_Fortran_PREPROCESS.rst
  9. 2 0
      Modules/Compiler/Absoft-Fortran.cmake
  10. 8 0
      Modules/Compiler/Cray-Fortran.cmake
  11. 3 0
      Modules/Compiler/Flang-Fortran.cmake
  12. 2 0
      Modules/Compiler/G95-Fortran.cmake
  13. 5 0
      Modules/Compiler/GNU-Fortran.cmake
  14. 3 0
      Modules/Compiler/HP-Fortran.cmake
  15. 2 0
      Modules/Compiler/Intel-Fortran.cmake
  16. 1 0
      Modules/Compiler/NAG-Fortran.cmake
  17. 1 0
      Modules/Compiler/PGI-Fortran.cmake
  18. 3 0
      Modules/Compiler/PathScale-Fortran.cmake
  19. 2 0
      Modules/Compiler/SunPro-Fortran.cmake
  20. 5 0
      Modules/Compiler/XL-Fortran.cmake
  21. 28 0
      Source/cmCommonTargetGenerator.cxx
  22. 3 0
      Source/cmCommonTargetGenerator.h
  23. 27 0
      Source/cmLocalVisualStudio7Generator.cxx
  24. 1 0
      Source/cmMakefileTargetGenerator.cxx
  25. 1 0
      Source/cmNinjaTargetGenerator.cxx
  26. 11 0
      Source/cmOutputConverter.cxx
  27. 8 0
      Source/cmOutputConverter.h
  28. 1 0
      Source/cmTarget.cxx
  29. 45 0
      Tests/FortranOnly/CMakeLists.txt
  30. 3 0
      Tests/FortranOnly/no_preprocess_source_fpp.fpp
  31. 3 0
      Tests/FortranOnly/no_preprocess_source_lower.f
  32. 3 0
      Tests/FortranOnly/no_preprocess_source_upper.F
  33. 3 0
      Tests/FortranOnly/no_preprocess_target_fpp.fpp
  34. 3 0
      Tests/FortranOnly/no_preprocess_target_lower.f
  35. 3 0
      Tests/FortranOnly/no_preprocess_target_upper.F
  36. 4 0
      Tests/FortranOnly/preprocess2.f
  37. 4 0
      Tests/FortranOnly/preprocess3.f

+ 2 - 0
Auxiliary/vim/syntax/cmake.vim

@@ -170,6 +170,7 @@ syn keyword cmakeProperty contained
             \ FRAMEWORK_VERSION
             \ Fortran_FORMAT
             \ Fortran_MODULE_DIRECTORY
+            \ Fortran_PREPROCESS
             \ GENERATED
             \ GENERATOR_FILE_NAME
             \ GENERATOR_IS_MULTI_CONFIG
@@ -1019,6 +1020,7 @@ syn keyword cmakeVariable contained
             \ CMAKE_Fortran_MODULE_DIRECTORY
             \ CMAKE_Fortran_OUTPUT_EXTENSION
             \ CMAKE_Fortran_PLATFORM_ID
+            \ CMAKE_Fortran_PREPROCESS
             \ CMAKE_Fortran_SIMULATE_ID
             \ CMAKE_Fortran_SIMULATE_VERSION
             \ CMAKE_Fortran_SIZEOF_DATA_PTR

+ 2 - 0
Help/manual/cmake-properties.7.rst

@@ -201,6 +201,7 @@ Properties on Targets
    /prop_tgt/FOLDER
    /prop_tgt/Fortran_FORMAT
    /prop_tgt/Fortran_MODULE_DIRECTORY
+   /prop_tgt/Fortran_PREPROCESS
    /prop_tgt/FRAMEWORK
    /prop_tgt/FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG
    /prop_tgt/FRAMEWORK_VERSION
@@ -465,6 +466,7 @@ Properties on Source Files
    /prop_sf/COMPILE_OPTIONS
    /prop_sf/EXTERNAL_OBJECT
    /prop_sf/Fortran_FORMAT
+   /prop_sf/Fortran_PREPROCESS
    /prop_sf/GENERATED
    /prop_sf/HEADER_FILE_ONLY
    /prop_sf/INCLUDE_DIRECTORIES

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -391,6 +391,7 @@ Variables that Control the Build
    /variable/CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG
    /variable/CMAKE_Fortran_FORMAT
    /variable/CMAKE_Fortran_MODULE_DIRECTORY
+   /variable/CMAKE_Fortran_PREPROCESS
    /variable/CMAKE_GHS_NO_SOURCE_GROUP_FILE
    /variable/CMAKE_GLOBAL_AUTOGEN_TARGET
    /variable/CMAKE_GLOBAL_AUTOGEN_TARGET_NAME

+ 6 - 4
Help/prop_sf/Fortran_FORMAT.rst

@@ -4,7 +4,9 @@ Fortran_FORMAT
 Set to ``FIXED`` or ``FREE`` to indicate the Fortran source layout.
 
 This property tells CMake whether a given Fortran source file uses
-fixed-format or free-format.  CMake will pass the corresponding format
-flag to the compiler.  Consider using the target-wide
-:prop_tgt:`Fortran_FORMAT` property if all source files in a target
-share the same format.
+fixed-format or free-format.  CMake will pass the corresponding format flag
+to the compiler.  Consider using the target-wide :prop_tgt:`Fortran_FORMAT`
+property if all source files in a target share the same format.
+
+.. note:: For some compilers, ``NAG``, ``PGI`` and ``Solaris Studio``,
+          setting this to ``OFF`` will have no effect.

+ 12 - 0
Help/prop_sf/Fortran_PREPROCESS.rst

@@ -0,0 +1,12 @@
+Fortran_PREPROCESS
+------------------
+
+Control whether the Fortran source file should be unconditionally preprocessed.
+
+If unset or empty, rely on the compiler to determine whether the file
+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.
+
+Consider using the target-wide :prop_tgt:`Fortran_PREPROCESS` property
+if all source files in a target need to be preprocessed.

+ 18 - 0
Help/prop_tgt/Fortran_PREPROCESS.rst

@@ -0,0 +1,18 @@
+Fortran_PREPROCESS
+------------------
+
+Control whether the Fortran source file should be unconditionally
+preprocessed.
+
+If unset or empty, rely on the compiler to determine whether the file
+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.
+
+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
+value is used to initialize this property.
+
+.. note:: For some compilers, ``NAG``, ``PGI`` and ``Solaris Studio``,
+          setting this to ``OFF`` will have no effect.

+ 6 - 0
Help/release/dev/fortran-preprocess-property.rst

@@ -0,0 +1,6 @@
+fortran-preprocess-property
+---------------------------
+
+* The :prop_tgt:`Fortran_PREPROCESS` target property and
+  :prop_sf:`Fortran_PREPROCESS` source-file property were added to
+  control preprocessing of Fortran source files.

+ 8 - 0
Help/variable/CMAKE_Fortran_PREPROCESS.rst

@@ -0,0 +1,8 @@
+CMAKE_Fortran_PREPROCESS
+------------------------
+
+Default value for :prop_tgt:`Fortran_PREPROCESS` of targets.
+
+This variable is used to initialize the :prop_tgt:`Fortran_PREPROCESS`
+property on all the targets.  See that target property for additional
+information.

+ 2 - 0
Modules/Compiler/Absoft-Fortran.cmake

@@ -9,3 +9,5 @@ set(CMAKE_Fortran_VERBOSE_FLAG "-v")
 set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed")
 set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree")
 set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-X")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-no-cpp")

+ 8 - 0
Modules/Compiler/Cray-Fortran.cmake

@@ -11,3 +11,11 @@ set(CMAKE_Fortran_MODDIR_FLAG -J)
 set(CMAKE_Fortran_MODDIR_DEFAULT .)
 set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-f fixed")
 set(CMAKE_Fortran_FORMAT_FREE_FLAG "-f free")
+
+if (NOT CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 8.5)
+  set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-eT")
+  set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-dT")
+else()
+  set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-eZ")
+  set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-dZ")
+endif()

+ 3 - 0
Modules/Compiler/Flang-Fortran.cmake

@@ -11,3 +11,6 @@ set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
 set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
 
 set(CMAKE_Fortran_MODDIR_FLAG "-J")
+
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")

+ 2 - 0
Modules/Compiler/G95-Fortran.cmake

@@ -9,3 +9,5 @@ set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
 set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
 set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
 set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-no-cpp")

+ 5 - 0
Modules/Compiler/GNU-Fortran.cmake

@@ -10,6 +10,11 @@ set(CMAKE_Fortran_PREPROCESS_SOURCE
 set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
 set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
 
+if (NOT CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 4.4)
+  set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+  set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
+endif()
+
 set(CMAKE_Fortran_POSTPROCESS_FLAG "-fpreprocessed")
 
 # No -DNDEBUG for Fortran.

+ 3 - 0
Modules/Compiler/HP-Fortran.cmake

@@ -7,3 +7,6 @@ set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES>
 
 set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
 set(CMAKE_Fortran_LINKER_WRAPPER_FLAG ",")
+
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "+cpp=yes")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "+cpp=no")

+ 2 - 0
Modules/Compiler/Intel-Fortran.cmake

@@ -15,3 +15,5 @@ set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <IN
 
 set(CMAKE_Fortran_PREPROCESS_SOURCE
   "<CMAKE_Fortran_COMPILER> -fpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-fpp")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nofpp")

+ 1 - 0
Modules/Compiler/NAG-Fortran.cmake

@@ -37,3 +37,4 @@ set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free")
 set(CMAKE_Fortran_COMPILE_OPTIONS_PIC "-PIC")
 set(CMAKE_Fortran_COMPILE_OPTIONS_PIE "-PIC")
 set(CMAKE_Fortran_RESPONSE_FILE_LINK_FLAG "-Wl,@")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-fpp")

+ 1 - 0
Modules/Compiler/PGI-Fortran.cmake

@@ -6,6 +6,7 @@ set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
 
 set(CMAKE_Fortran_PREPROCESS_SOURCE
   "<CMAKE_Fortran_COMPILER> -Mpreprocess <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-Mpreprocess")
 
 set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-Mnofreeform")
 set(CMAKE_Fortran_FORMAT_FREE_FLAG "-Mfreeform")

+ 3 - 0
Modules/Compiler/PathScale-Fortran.cmake

@@ -4,3 +4,6 @@ __compiler_pathscale(Fortran)
 set(CMAKE_Fortran_MODDIR_FLAG "-module ")
 set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-fixedform")
 set(CMAKE_Fortran_FORMAT_FREE_FLAG "-freeform")
+
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")

+ 2 - 0
Modules/Compiler/SunPro-Fortran.cmake

@@ -30,3 +30,5 @@ set(CMAKE_Fortran_PREPROCESS_SOURCE
 
 set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -F -fpp <SOURCE> -o <PREPROCESSED_SOURCE>")
 set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
+
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-fpp")

+ 5 - 0
Modules/Compiler/XL-Fortran.cmake

@@ -23,3 +23,8 @@ set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE)
 set(CMAKE_Fortran_PREPROCESS_SOURCE
   "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -qpreprocess -qnoobject -qsuppress=1517-020 -tF -B \"${CMAKE_CURRENT_LIST_DIR}/XL-Fortran/\" -WF,--cpp,\"${CMAKE_Fortran_XL_CPP}\",--out,<PREPROCESSED_SOURCE> <SOURCE>"
   )
+
+if (NOT CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 15.1.6)
+  set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-qpreprocess")
+  set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-qnopreprocess")
+endif()

+ 28 - 0
Source/cmCommonTargetGenerator.cxx

@@ -98,6 +98,34 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags(
   }
 }
 
+void cmCommonTargetGenerator::AppendFortranPreprocessFlags(
+  std::string& flags, cmSourceFile const& source)
+{
+  const std::string srcpp = source.GetSafeProperty("Fortran_PREPROCESS");
+  cmOutputConverter::FortranPreprocess preprocess =
+    cmOutputConverter::GetFortranPreprocess(srcpp);
+  if (preprocess == cmOutputConverter::FortranPreprocess::Unset) {
+    std::string const& tgtpp =
+      this->GeneratorTarget->GetSafeProperty("Fortran_PREPROCESS");
+    preprocess = cmOutputConverter::GetFortranPreprocess(tgtpp);
+  }
+  const char* var = nullptr;
+  switch (preprocess) {
+    case cmOutputConverter::FortranPreprocess::Needed:
+      var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON";
+      break;
+    case cmOutputConverter::FortranPreprocess::NotNeeded:
+      var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF";
+      break;
+    default:
+      break;
+  }
+  if (var) {
+    this->LocalCommonGenerator->AppendCompileOptions(
+      flags, this->Makefile->GetSafeDefinition(var));
+  }
+}
+
 std::string cmCommonTargetGenerator::GetFlags(const std::string& l,
                                               const std::string& config,
                                               const std::string& arch)

+ 3 - 0
Source/cmCommonTargetGenerator.h

@@ -45,6 +45,9 @@ protected:
   void AppendFortranFormatFlags(std::string& flags,
                                 cmSourceFile const& source);
 
+  void AppendFortranPreprocessFlags(std::string& flags,
+                                    cmSourceFile const& source);
+
   virtual void AddIncludeFlags(std::string& flags, std::string const& lang,
                                const std::string& config) = 0;
 

+ 27 - 0
Source/cmLocalVisualStudio7Generator.cxx

@@ -284,6 +284,7 @@ void cmLocalVisualStudio7Generator::WriteConfigurations(
 }
 cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] = {
   { "Preprocess", "fpp", "Run Preprocessor on files", "preprocessYes", 0 },
+  { "Preprocess", "nofpp", "Run Preprocessor on files", "preprocessNo", 0 },
   { "SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0 },
   { "SourceFileFormat", "fixed", "Use Fixed Format", "fileFormatFixed", 0 },
   { "SourceFileFormat", "free", "Use Free Format", "fileFormatFree", 0 },
@@ -682,6 +683,18 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
       default:
         break;
     }
+
+    switch (cmOutputConverter::GetFortranPreprocess(
+      target->GetSafeProperty("Fortran_PREPROCESS"))) {
+      case cmOutputConverter::FortranPreprocess::Needed:
+        flags += " -fpp";
+        break;
+      case cmOutputConverter::FortranPreprocess::NotNeeded:
+        flags += " -nofpp";
+        break;
+      default:
+        break;
+    }
   }
 
   // Get preprocessor definitions for this directory.
@@ -1474,6 +1487,20 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
     }
 
     if (lg->FortranProject) {
+      switch (cmOutputConverter::GetFortranPreprocess(
+        sf.GetSafeProperty("Fortran_PREPROCESS"))) {
+        case cmOutputConverter::FortranPreprocess::Needed:
+          fc.CompileFlags = cmStrCat("-fpp ", fc.CompileFlags);
+          needfc = true;
+          break;
+        case cmOutputConverter::FortranPreprocess::NotNeeded:
+          fc.CompileFlags = cmStrCat("-nofpp ", fc.CompileFlags);
+          needfc = true;
+          break;
+        default:
+          break;
+      }
+
       switch (cmOutputConverter::GetFortranFormat(
         sf.GetSafeProperty("Fortran_FORMAT"))) {
         case cmOutputConverter::FortranFormatFixed:

+ 1 - 0
Source/cmMakefileTargetGenerator.cxx

@@ -541,6 +541,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
   // Add Fortran format flags.
   if (lang == "Fortran") {
     this->AppendFortranFormatFlags(flags, source);
+    this->AppendFortranPreprocessFlags(flags, source);
   }
 
   // Add flags from source file properties.

+ 1 - 0
Source/cmNinjaTargetGenerator.cxx

@@ -183,6 +183,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
   // Add Fortran format flags.
   if (language == "Fortran") {
     this->AppendFortranFormatFlags(flags, *source);
+    this->AppendFortranPreprocessFlags(flags, *source);
   }
 
   // Add source file specific flags.

+ 11 - 0
Source/cmOutputConverter.cxx

@@ -170,6 +170,17 @@ cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
   return format;
 }
 
+cmOutputConverter::FortranPreprocess cmOutputConverter::GetFortranPreprocess(
+  cm::string_view value)
+{
+  if (value.empty()) {
+    return FortranPreprocess::Unset;
+  }
+
+  return cmIsOn(value) ? FortranPreprocess::Needed
+                       : FortranPreprocess::NotNeeded;
+}
+
 void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell)
 {
   this->LinkScriptShell = linkScriptShell;

+ 8 - 0
Source/cmOutputConverter.h

@@ -95,6 +95,14 @@ public:
   };
   static FortranFormat GetFortranFormat(cm::string_view value);
 
+  enum class FortranPreprocess
+  {
+    Unset,
+    NotNeeded,
+    Needed
+  };
+  static FortranPreprocess GetFortranPreprocess(cm::string_view value);
+
 private:
   cmState* GetState() const;
 

+ 1 - 0
Source/cmTarget.cxx

@@ -307,6 +307,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
     initProp("Fortran_FORMAT");
     initProp("Fortran_MODULE_DIRECTORY");
     initProp("Fortran_COMPILER_LAUNCHER");
+    initProp("Fortran_PREPROCESS");
     initProp("GNUtoMS");
     initProp("OSX_ARCHITECTURES");
     initProp("IOS_INSTALL_COMBINED");

+ 45 - 0
Tests/FortranOnly/CMakeLists.txt

@@ -116,3 +116,48 @@ if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
   set_property(TARGET IntelIfDef PROPERTY Fortran_FORMAT FIXED)
   target_compile_definitions(IntelIfDef PRIVATE SOME_DEF)
 endif()
+
+# Skip these tests if compiler/version doesn't have preprocessing flags
+if((CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 4.4)
+  OR (CMAKE_Fortran_COMPILER_ID STREQUAL "XL" AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 15.1.6))
+  set(test_pp_flags 0)
+else()
+  set(test_pp_flags 1)
+endif()
+
+if(test_pp_flags)
+  # Test that we can always preprocess a target
+  add_executable(preprocess_target preprocess2.f)
+  set_property(TARGET preprocess_target PROPERTY Fortran_PREPROCESS ON)
+
+  # Test that we can preprocess a single source file
+  add_executable(preprocess_source preprocess3.f)
+  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)
+  endif()
+endif()

+ 3 - 0
Tests/FortranOnly/no_preprocess_source_fpp.fpp

@@ -0,0 +1,3 @@
+      SUBROUTINE NOPREPROCESS_SOURCE_FPP
+      INTEGER F
+      END

+ 3 - 0
Tests/FortranOnly/no_preprocess_source_lower.f

@@ -0,0 +1,3 @@
+      SUBROUTINE NOPREPROCESS_SOURCE_LOWER
+      INTEGER F
+      END

+ 3 - 0
Tests/FortranOnly/no_preprocess_source_upper.F

@@ -0,0 +1,3 @@
+      SUBROUTINE NOPREPROCESS_SOURCE_UPPER
+      INTEGER F
+      END

+ 3 - 0
Tests/FortranOnly/no_preprocess_target_fpp.fpp

@@ -0,0 +1,3 @@
+      SUBROUTINE NOPREPROCESS_TARGET_FPP
+      INTEGER F
+      END

+ 3 - 0
Tests/FortranOnly/no_preprocess_target_lower.f

@@ -0,0 +1,3 @@
+      SUBROUTINE NOPREPROCESS_TARGET_LOWER
+      INTEGER F
+      END

+ 3 - 0
Tests/FortranOnly/no_preprocess_target_upper.F

@@ -0,0 +1,3 @@
+      SUBROUTINE NOPREPROCESS_TARGET_UPPER
+      INTEGER F
+      END

+ 4 - 0
Tests/FortranOnly/preprocess2.f

@@ -0,0 +1,4 @@
+#define int INTEGER
+       PROGRAM PREPRO
+       int f
+       END

+ 4 - 0
Tests/FortranOnly/preprocess3.f

@@ -0,0 +1,4 @@
+#define int INTEGER
+       PROGRAM PREPRO
+       int f
+       END