瀏覽代碼

VS: Add support for using Intel oneAPI Fortran compiler in .vfproj files

Add a `fortran={ifort,ifx}` field to `CMAKE_GENERATOR_TOOLSET` to
specify which Intel Fortran compiler to use.

Fixes: #25427
Brad King 1 年之前
父節點
當前提交
43d218d970

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

@@ -131,6 +131,7 @@ Variables that Provide Information
    /variable/CMAKE_VS_PLATFORM_TOOLSET
    /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA
    /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR
+   /variable/CMAKE_VS_PLATFORM_TOOLSET_FORTRAN
    /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
    /variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION
    /variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER

+ 7 - 0
Help/release/dev/vs-ifx.rst

@@ -0,0 +1,7 @@
+vs-ifx
+------
+
+* :ref:`Visual Studio Generators` now support selecting between the
+  Intel oneAPI Fortran compiler (``ifx``) and the Intel classic Fortran
+  compiler (``ifort``) using a ``fortran=`` field in
+  :variable:`CMAKE_GENERATOR_TOOLSET`.

+ 14 - 0
Help/variable/CMAKE_GENERATOR_TOOLSET.rst

@@ -48,6 +48,20 @@ Supported pairs are:
   See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_CUDA` and
   :variable:`CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR` variables.
 
+``fortran=<compiler>``
+  .. versionadded:: 3.29
+
+  Specify the Fortran compiler to use, among those that integrate with VS.
+  The value may be one of:
+
+  ``ifort``
+    Intel classic Fortran compiler.
+
+  ``ifx``
+    Intel oneAPI Fortran compiler.
+
+  See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_FORTRAN` variable.
+
 ``host=<arch>``
   Specify the host tools architecture as ``x64`` or ``x86``.
   Supported by VS 2013 and above.

+ 12 - 0
Help/variable/CMAKE_VS_PLATFORM_TOOLSET_FORTRAN.rst

@@ -0,0 +1,12 @@
+CMAKE_VS_PLATFORM_TOOLSET_FORTRAN
+---------------------------------
+
+.. versionadded:: 3.29
+
+Fortran compiler to be used by Visual Studio projects.
+
+:ref:`Visual Studio Generators` support selecting among Fortran compilers
+whose Visual Studio Integration is installed.  The compiler may be specified
+by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of the form ``fortran=...``.
+CMake provides the selected Fortran compiler in this variable.
+The value may be empty if the field was not specified.

+ 7 - 1
Modules/CMakeDetermineCompilerId.cmake

@@ -402,7 +402,13 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
     elseif(lang STREQUAL Fortran)
       set(v Intel)
       set(ext vfproj)
-      set(id_cl ifort.exe)
+      if(CMAKE_VS_PLATFORM_TOOLSET_FORTRAN)
+        set(id_cl "${CMAKE_VS_PLATFORM_TOOLSET_FORTRAN}.exe")
+        set(id_UseCompiler "UseCompiler=\"${CMAKE_VS_PLATFORM_TOOLSET_FORTRAN}Compiler\"")
+      else()
+        set(id_cl ifort.exe)
+        set(id_UseCompiler "")
+      endif()
     elseif(lang STREQUAL CSharp)
       set(v 10)
       set(ext csproj)

+ 1 - 1
Modules/CompilerId/VS-Intel.vfproj.in

@@ -13,7 +13,7 @@
 			Name="Debug|@id_platform@"
 			OutputDirectory="."
 			IntermediateDirectory="$(ConfigurationName)"
-			>
+			@id_UseCompiler@>
 			<Tool
 				Name="VFFortranCompilerTool"
 				DebugInformationFormat="debugEnabled"

+ 24 - 0
Source/cmGlobalVisualStudio10Generator.cxx

@@ -191,6 +191,23 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
     }
   }
 
+  if (this->GeneratorToolsetFortran) {
+    if (*this->GeneratorToolsetFortran != "ifx" &&
+        *this->GeneratorToolsetFortran != "ifort") {
+      mf->IssueMessage(MessageType::FATAL_ERROR,
+                       cmStrCat("Generator\n"
+                                "  ",
+                                this->GetName(),
+                                "\n"
+                                "given toolset\n"
+                                "  fortran=",
+                                *this->GeneratorToolsetFortran,
+                                "\n"
+                                "but the value is not \"ifx\" or \"ifort\"."));
+      this->GeneratorToolsetFortran = cm::nullopt;
+    }
+  }
+
   if (!this->GeneratorToolsetVersion.empty() &&
       this->GeneratorToolsetVersion != "Test Toolset Version"_s) {
     // If a specific minor version of the MSVC toolset is requested, verify
@@ -300,6 +317,9 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
   if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) {
     mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir);
   }
+  if (cm::optional<std::string> fortran = this->GetPlatformToolsetFortran()) {
+    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_FORTRAN", *fortran);
+  }
   if (const char* vcTargetsDir = this->GetCustomVCTargetsPath()) {
     mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR",
                       vcTargetsDir);
@@ -410,6 +430,10 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
     cmSystemTools::ConvertToUnixSlashes(this->CustomFlagTableDir);
     return true;
   }
+  if (key == "fortran"_s) {
+    this->GeneratorToolsetFortran = value;
+    return true;
+  }
   if (key == "version"_s) {
     this->GeneratorToolsetVersion = value;
     return true;

+ 7 - 0
Source/cmGlobalVisualStudio10Generator.h

@@ -93,6 +93,12 @@ public:
    * directory */
   std::string const& GetPlatformToolsetCudaVSIntegrationSubdirString() const;
 
+  /** The fortran toolset name.  */
+  cm::optional<std::string> GetPlatformToolsetFortran() const override
+  {
+    return this->GeneratorToolsetFortran;
+  }
+
   /** Return whether we need to use No/Debug instead of false/true
       for GenerateDebugInformation.  */
   bool GetPlatformToolsetNeedsDebugEnum() const
@@ -221,6 +227,7 @@ protected:
   std::string GeneratorToolsetCudaCustomDir;
   std::string GeneratorToolsetCudaNvccSubdir;
   std::string GeneratorToolsetCudaVSIntegrationSubdir;
+  cm::optional<std::string> GeneratorToolsetFortran;
   std::string DefaultPlatformToolset;
   std::string DefaultPlatformToolsetHostArchitecture;
   std::string DefaultAndroidToolset;

+ 6 - 0
Source/cmGlobalVisualStudio7Generator.h

@@ -10,6 +10,8 @@
 #include <utility>
 #include <vector>
 
+#include <cm/optional>
+
 #include <cm3p/json/value.h>
 
 #include "cmGlobalVisualStudioGenerator.h"
@@ -102,6 +104,10 @@ public:
   }
 
   const std::string& GetIntelProjectVersion();
+  virtual cm::optional<std::string> GetPlatformToolsetFortran() const
+  {
+    return cm::nullopt;
+  }
 
   bool FindMakeProgram(cmMakefile* mf) override;
 

+ 3 - 0
Source/cmLocalVisualStudio7Generator.cxx

@@ -795,6 +795,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
       target->GetType() == cmStateEnums::OBJECT_LIBRARY
       ? ".lib"
       : cmSystemTools::GetFilenameLastExtension(targetNameFull);
+    if (cm::optional<std::string> fortran = gg->GetPlatformToolsetFortran()) {
+      fout << "\t\t\tUseCompiler=\"" << *fortran << "Compiler\"\n";
+    }
     /* clang-format off */
     fout <<
       "\t\t\tTargetName=\"" << this->EscapeForXML(targetName) << "\"\n"

+ 1 - 0
Tests/RunCMake/GeneratorToolset/BadToolsetFortran-result.txt

@@ -0,0 +1 @@
+1

+ 11 - 0
Tests/RunCMake/GeneratorToolset/BadToolsetFortran-stderr.txt

@@ -0,0 +1,11 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    [^
+]*
+
+  given toolset
+
+    fortran=bad
+
+  but the value is not "ifx" or "ifort"\.

+ 1 - 0
Tests/RunCMake/GeneratorToolset/BadToolsetFortran.cmake

@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")

+ 6 - 0
Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake

@@ -43,6 +43,12 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[0124567]")
     set(RunCMake_GENERATOR_TOOLSET "${VsNormal_Toolset},customFlagTableDir=does_not_exist")
     run_cmake(BadToolsetCustomFlagTableDir)
   endif()
+  set(RunCMake_GENERATOR_TOOLSET "fortran=ifort")
+  run_cmake(TestToolsetFortranIFORT)
+  set(RunCMake_GENERATOR_TOOLSET "fortran=ifx")
+  run_cmake(TestToolsetFortranIFX)
+  set(RunCMake_GENERATOR_TOOLSET "fortran=bad")
+  run_cmake(BadToolsetFortran)
   if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[24567]")
     set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64")
     run_cmake(TestToolsetHostArchBoth)

+ 1 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetFortranIFORT-stdout.txt

@@ -0,0 +1 @@
+-- CMAKE_VS_PLATFORM_TOOLSET_FORTRAN='ifort'

+ 1 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetFortranIFORT.cmake

@@ -0,0 +1 @@
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_FORTRAN='${CMAKE_VS_PLATFORM_TOOLSET_FORTRAN}'")

+ 1 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetFortranIFX-stdout.txt

@@ -0,0 +1 @@
+-- CMAKE_VS_PLATFORM_TOOLSET_FORTRAN='ifx'

+ 1 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetFortranIFX.cmake

@@ -0,0 +1 @@
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_FORTRAN='${CMAKE_VS_PLATFORM_TOOLSET_FORTRAN}'")