From d3d2c3cd497e09281a8f237b5a4cd35d8cd298f0 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Mon, 4 Feb 2019 09:41:57 -0500
Subject: VS: Fix Fortran target type selection when linking C++ targets

Since commit 2c9f35789d (VS: Decide project type by linker lang as
fallback, 2017-03-30, v3.9.0-rc1~340^2) we consider the linker language
when detecting whether to generate a `.vfproj` or `.vcxproj` file.
However, this could cause C-only projects to become `.vfproj` files if
they link to Fortran projects.  Instead we should consider only the
`LINKER_LANGUAGE` property on the target itself.  This approach is
already used for CSharp.  It allows project code to specify the project
file type for a target with no sources but does not allow linked targets
to affect it.

Fixes: #18687
---
 Source/cmGlobalVisualStudioGenerator.cxx | 31 ++++++++++++-------------------
 Tests/Fortran/CMakeLists.txt             |  5 +++++
 2 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 77be592..1922906 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -813,7 +813,6 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
   cmGeneratorTarget const* gt)
 {
   // check to see if this is a fortran build
-  std::set<std::string> languages;
   {
     // Issue diagnostic if the source files depend on the config.
     std::vector<cmSourceFile*> sources;
@@ -821,27 +820,21 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
       return false;
     }
   }
+
   // If there's only one source language, Fortran has to be used
   // in order for the sources to compile.
-  // Note: Via linker propagation, LINKER_LANGUAGE could become CXX in
-  // this situation and mismatch from the actual language of the linker.
+  std::set<std::string> languages;
   gt->GetLanguages(languages, "");
-  if (languages.size() == 1) {
-    if (*languages.begin() == "Fortran") {
-      return true;
-    }
-  }
-
-  // In the case of mixed object files or sources mixed with objects,
-  // decide the language based on the value of LINKER_LANGUAGE.
-  // This will not make it possible to mix source files of different
-  // languages, but object libraries will be linked together in the
-  // same fashion as other generators do.
-  if (gt->GetLinkerLanguage("") == "Fortran") {
-    return true;
-  }
-
-  return false;
+  // Consider an explicit linker language property, but *not* the
+  // computed linker language that may depend on linked targets.
+  // This allows the project to control the language choice in
+  // a target with none of its own sources, e.g. when also using
+  // object libraries.
+  const char* linkLang = gt->GetProperty("LINKER_LANGUAGE");
+  if (linkLang && *linkLang) {
+    languages.insert(linkLang);
+  }
+  return languages.size() == 1 && *languages.begin() == "Fortran";
 }
 
 bool cmGlobalVisualStudioGenerator::TargetCompare::operator()(
diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt
index 52623d0..7023615 100644
--- a/Tests/Fortran/CMakeLists.txt
+++ b/Tests/Fortran/CMakeLists.txt
@@ -99,6 +99,11 @@ function(test_fortran_c_interface_module)
   target_link_libraries(myc myfort)
   set_property(TARGET myc PROPERTY COMPILE_DEFINITIONS ${MYC_DEFS})
 
+  add_library(myfort_obj OBJECT mysub.f)
+  add_library(myc_use_obj myc.c $<TARGET_OBJECTS:myfort_obj>)
+  add_executable(mainc_use_obj mainc.c)
+  target_link_libraries(mainc_use_obj myc_use_obj)
+
   add_library(mycxx mycxx.cxx)
   target_link_libraries(mycxx myc)
 
-- 
cgit v0.12