From f39ee9c6a1ddd81c293bb8d2378d90eda0ddf1fc Mon Sep 17 00:00:00 2001
From: Alexander Alekhin <alexander.alekhin@intel.com>
Date: Wed, 13 Dec 2017 14:14:28 +0300
Subject: [PATCH] cmake: rework MAP_IMPORTED_CONFIG to prevent unintended build
 failures

Introduce CMake variable OPENCV_MAP_IMPORTED_CONFIG which controls this behaviour
Added defaults for MSVS targets
---
 cmake/templates/OpenCVConfig.cmake.in | 55 ++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 6 deletions(-)

diff --git a/cmake/templates/OpenCVConfig.cmake.in b/cmake/templates/OpenCVConfig.cmake.in
index 0ac8a984c..edc707549 100644
--- a/cmake/templates/OpenCVConfig.cmake.in
+++ b/cmake/templates/OpenCVConfig.cmake.in
@@ -126,6 +126,50 @@ if(NOT CMAKE_VERSION VERSION_LESS "2.8.11")
   endforeach()
 endif()
 
+
+if(NOT DEFINED OPENCV_MAP_IMPORTED_CONFIG)
+  if(CMAKE_GENERATOR MATCHES "Visual Studio" OR MSVC)
+    # OpenCV supports Debug and Release builds only.
+    # But MSVS has 'RelWithDebInfo' 'MinSizeRel' configurations for applications.
+    # By default CMake maps these configuration on the first available (Debug) which is wrong.
+    # Non-Debug build of Application can't be used with OpenCV Debug build (ABI mismatch problem)
+    # Add mapping of RelWithDebInfo and MinSizeRel to Release here
+    set(OPENCV_MAP_IMPORTED_CONFIG "RELWITHDEBINFO=!Release;MINSIZEREL=!Release")
+  endif()
+endif()
+set(__remap_warnings "")
+macro(ocv_map_imported_config target)
+  if(DEFINED OPENCV_MAP_IMPORTED_CONFIG) # list, "RELWITHDEBINFO=Release;MINSIZEREL=Release"
+    get_target_property(__available_configurations ${target} IMPORTED_CONFIGURATIONS)
+    foreach(remap ${OPENCV_MAP_IMPORTED_CONFIG})
+      if(remap MATCHES "^(.+)=(!?)([^!]+)$")
+        set(__remap_config "${CMAKE_MATCH_1}")
+        set(__final_config "${CMAKE_MATCH_3}")
+        set(__force_flag "${CMAKE_MATCH_2}")
+        string(TOUPPER "${__final_config}" __final_config_upper)
+        string(TOUPPER "${__remap_config}" __remap_config_upper)
+        if(";${__available_configurations};" MATCHES ";${__remap_config_upper};" AND NOT "${__force_flag}" STREQUAL "!")
+          # configuration already exists, skip remap
+          set(__remap_warnings "${__remap_warnings}... Configuration already exists ${__remap_config} (skip mapping ${__remap_config} => ${__final_config}) (available configurations: ${__available_configurations})\n")
+          continue()
+        endif()
+        if(__available_configurations AND NOT ";${__available_configurations};" MATCHES ";${__final_config_upper};")
+          # skip, configuration is not available
+          if(NOT "${__force_flag}" STREQUAL "!")
+            set(__remap_warnings "${__remap_warnings}... Configuration is not available '${__final_config}' for ${target}, build may fail (available configurations: ${__available_configurations})\n")
+          endif()
+        endif()
+        set_target_properties(${target} PROPERTIES
+            MAP_IMPORTED_CONFIG_${__remap_config} "${__final_config}"
+        )
+      else()
+        message(WARNING "Invalid entry of OPENCV_MAP_IMPORTED_CONFIG: '${remap}' (${OPENCV_MAP_IMPORTED_CONFIG})")
+      endif()
+    endforeach()
+  endif()
+endmacro()
+
+
 # ==============================================================
 #  Form list of modules (components) to find
 # ==============================================================
@@ -199,16 +243,15 @@ foreach(__cvcomponent ${OpenCV_FIND_COMPONENTS})
       )
     endif()
   endif()
-  # OpenCV supports Debug and Release only.
-  # RelWithDebInfo and MinSizeRel are mapped to Release
   if(TARGET ${__cvcomponent})
-      set_target_properties(${__cvcomponent} PROPERTIES
-          MAP_IMPORTED_CONFIG_MINSIZEREL "Release"
-          MAP_IMPORTED_CONFIG_RELWITHDEBINFO "Release"
-      )
+    ocv_map_imported_config(${__cvcomponent})
   endif()
 endforeach()
 
+if(__remap_warnings AND NOT OpenCV_FIND_QUIETLY)
+  message("OpenCV: configurations remap warnings:\n${__remap_warnings}OpenCV: Check variable OPENCV_MAP_IMPORTED_CONFIG=${OPENCV_MAP_IMPORTED_CONFIG}")
+endif()
+
 # ==============================================================
 # Compatibility stuff
 # ==============================================================
-- 
2.23.0

