From c54e1cb52eab4c008cc7301d56e2dcb3b314819d Mon Sep 17 00:00:00 2001
From: Martchus <martchus@gmx.net>
Date: Sun, 18 Sep 2016 18:32:00 +0200
Subject: [PATCH 6/8] Pull dependencies of static libraries in CMake modules

When doing a static build of Qt, the dependencies of the Qt
libraries and plugins itself must be specified when linking
the final application.
---
 .../features/data/cmake/Qt5BasicConfig.cmake.in    | 149 ++++++++++++++++-----
 .../features/data/cmake/Qt5PluginTarget.cmake.in   |  11 +-
 qmake/generators/makefile.cpp                      |   7 +
 3 files changed, 129 insertions(+), 38 deletions(-)

diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
index 17da8b979e..f11d17b94b 100644
--- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
+++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
@@ -55,35 +55,52 @@ but not all the files it references.
 endmacro()
 
 !!IF !equals(TEMPLATE, aux)
-macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATION IMPLIB_LOCATION)
-    set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${Configuration})
+macro(_populate_$${CMAKE_MODULE_NAME}_target_properties TARGET_CONFIG LIB_LOCATION IMPLIB_LOCATION)
+    set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${TARGET_CONFIG})
 
 !!IF isEmpty(CMAKE_DLL_DIR_IS_ABSOLUTE)
     set(imported_location \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_DLL_DIR}${LIB_LOCATION}\")
 !!ELSE
     set(imported_location \"$${CMAKE_DLL_DIR}${LIB_LOCATION}\")
 !!ENDIF
+
     _qt5_$${CMAKE_MODULE_NAME}_check_file_exists(${imported_location})
+
+!!IF !isEmpty(CMAKE_STATIC_TYPE)
+    if (_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES)
+        set(_list_sep \";\")
+    endif()
+    set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
+        \"INTERFACE_LINK_LIBRARIES_${TARGET_CONFIG}\" \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}${_list_sep}${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${TARGET_CONFIG}_LIB_DEPENDENCIES}\"
+        \"IMPORTED_LOCATION_${TARGET_CONFIG}\" ${imported_location}
+!!IF !isEmpty(CMAKE_LIB_SONAME)
+        \"IMPORTED_SONAME_${TARGET_CONFIG}\" \"$${CMAKE_LIB_SONAME}\"
+!!ENDIF
+        # For backward compatibility with CMake < 2.8.12
+        \"IMPORTED_LINK_INTERFACE_LIBRARIES_${TARGET_CONFIG}\" \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}${_list_sep}${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${TARGET_CONFIG}_LIB_DEPENDENCIES}\"
+    )
+!!ELSE
     set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
-        \"INTERFACE_LINK_LIBRARIES\" \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
-        \"IMPORTED_LOCATION_${Configuration}\" ${imported_location}
+        \"INTERFACE_LINK_LIBRARIES_${TARGET_CONFIG}\" \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
+        \"IMPORTED_LOCATION_${TARGET_CONFIG}\" ${imported_location}
 !!IF !isEmpty(CMAKE_LIB_SONAME)
-        \"IMPORTED_SONAME_${Configuration}\" \"$${CMAKE_LIB_SONAME}\"
+        \"IMPORTED_SONAME_${TARGET_CONFIG}\" \"$${CMAKE_LIB_SONAME}\"
 !!ENDIF
         # For backward compatibility with CMake < 2.8.12
-        \"IMPORTED_LINK_INTERFACE_LIBRARIES_${Configuration}\" \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
+        \"IMPORTED_LINK_INTERFACE_LIBRARIES_${TARGET_CONFIG}\" \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
     )
+!!ENDIF
 
 !!IF !isEmpty(CMAKE_WINDOWS_BUILD)
 !!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
     set(imported_implib \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}${IMPLIB_LOCATION}\")
 !!ELSE
-    set(imported_implib \"IMPORTED_IMPLIB_${Configuration}\" \"$${CMAKE_LIB_DIR}${IMPLIB_LOCATION}\")
+    set(imported_implib \"IMPORTED_IMPLIB_${TARGET_CONFIG}\" \"$${CMAKE_LIB_DIR}${IMPLIB_LOCATION}\")
 !!ENDIF
     _qt5_$${CMAKE_MODULE_NAME}_check_file_exists(${imported_implib})
     if(NOT \"${IMPLIB_LOCATION}\" STREQUAL \"\")
         set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
-        \"IMPORTED_IMPLIB_${Configuration}\" ${imported_implib}
+        \"IMPORTED_IMPLIB_${TARGET_CONFIG}\" ${imported_implib}
         )
     endif()
 !!ENDIF
@@ -227,13 +244,48 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
 !!IF !isEmpty(CMAKE_STATIC_TYPE)
     add_library(Qt5::$${CMAKE_MODULE_NAME} STATIC IMPORTED)
     set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY IMPORTED_LINK_INTERFACE_LANGUAGES "CXX")
+    macro(_process_prl_file PRL_FILE_LOCATION CONFIGURATION)
+        if (EXISTS \"${PRL_FILE_LOCATION}\")
+            file(STRINGS \"${PRL_FILE_LOCATION}\" prl_strings REGEX \"QMAKE_PRL_LIBS_FOR_CMAKE\")
+            string(REGEX REPLACE \"QMAKE_PRL_LIBS_FOR_CMAKE *= *([^\\n]*)\" \"\\\\1\" static_depends ${prl_strings})
+            string(REGEX REPLACE \"\\\\$\\\\$\\\\[QT_INSTALL_LIBS\\\\]\" \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/lib\" static_depends \"${static_depends}\")
+            string(REPLACE \"-framework;\" \"-framework \" static_depends \"${static_depends}\")
+            if (_Qt5$${CMAKE_MODULE_NAME}_STATIC_${CONFIGURATION}_LIB_DEPENDENCIES)
+                set(_list_sep \";\")
+            endif()
+            set(_Qt5$${CMAKE_MODULE_NAME}_STATIC_${CONFIGURATION}_LIB_DEPENDENCIES \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${CONFIGURATION}_LIB_DEPENDENCIES}${_list_sep}${static_depends}\")
+        endif()
+    endmacro()
+
+    macro(_process_plugin_prl_file PRL_FILE_LOCATION CONFIGURATION LIB_DIRECTORY LIB_LOCATION)
+        # First add the (static) plugin itself ...
+        if (_Qt5$${CMAKE_MODULE_NAME}_STATIC_${CONFIGURATION}_LIB_DEPENDENCIES)
+            set(_list_sep \";\")
+        endif()
+        set(_Qt5$${CMAKE_MODULE_NAME}_STATIC_${CONFIGURATION}_LIB_DEPENDENCIES \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${CONFIGURATION}_LIB_DEPENDENCIES}${_list_sep}${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/${LIB_DIRECTORY}/${LIB_LOCATION}\")
+        # .. then its dependencies.
+        _process_prl_file(${PRL_FILE_LOCATION} ${CONFIGURATION})
+    endmacro()
+
+!!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
+    _process_prl_file(\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_PRL_FILE_LOCATION_DEBUG}\" DEBUG)
 !!ELSE
+    _process_prl_file(\"$${CMAKE_LIB_DIR}$${CMAKE_PRL_FILE_LOCATION_DEBUG}\" DEBUG)
+!!ENDIF
+!!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
+    _process_prl_file(\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_PRL_FILE_LOCATION_RELEASE}\" RELEASE)
+!!ELSE
+    _process_prl_file(\"$${CMAKE_LIB_DIR}$${CMAKE_PRL_FILE_LOCATION_RELEASE}\" RELEASE)
+!!ENDIF
+
+!!ELSE // !isEmpty(CMAKE_STATIC_TYPE)
 !!IF equals(TEMPLATE, aux)
     add_library(Qt5::$${CMAKE_MODULE_NAME} INTERFACE IMPORTED)
 !!ELSE
     add_library(Qt5::$${CMAKE_MODULE_NAME} SHARED IMPORTED)
 !!ENDIF
-!!ENDIF
+!!ENDIF // !isEmpty(CMAKE_STATIC_TYPE)
+
 !!IF !equals(TEMPLATE, aux)
 !!IF !isEmpty(CMAKE_BUILD_IS_FRAMEWORK)
     set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY FRAMEWORK 1)
@@ -245,6 +297,56 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
     set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY
       INTERFACE_COMPILE_DEFINITIONS $${MODULE_DEFINE})
 
+    # Find plugin targets
+    file(GLOB pluginTargetsMaybe \"${CMAKE_CURRENT_LIST_DIR}/*Qt5$${CMAKE_MODULE_NAME}_*.cmake\")
+    unset(pluginTargets)
+    if(pluginTargetsMaybe)
+        foreach(pluginTarget ${pluginTargetsMaybe})
+            file(STRINGS ${pluginTarget} matched REGEX Qt5$${CMAKE_MODULE_NAME}_PLUGINS)
+            if(matched)
+                list(APPEND pluginTargets ${pluginTarget})
+            endif()
+        endforeach()
+    endif()
+
+    macro(_populate_$${CMAKE_MODULE_NAME}_plugin_properties TARGET_NAME PLUGIN_TARGET_NAME PLUGIN_NAME CONFIG PLUGIN_LOCATION)
+        set_property(TARGET ${PLUGIN_TARGET_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${CONFIG})
+
+!!IF isEmpty(CMAKE_PLUGIN_DIR_IS_ABSOLUTE)
+        set(imported_location \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_PLUGIN_DIR}${PLUGIN_LOCATION}\")
+!!ELSE
+        set(imported_location \"$${CMAKE_PLUGIN_DIR}${PLUGIN_LOCATION}\")
+!!ENDIF
+        _qt5_$${CMAKE_MODULE_NAME}_check_file_exists(${imported_location})
+        set_target_properties(${PLUGIN_TARGET_NAME} PROPERTIES
+            \"IMPORTED_LOCATION_${CONFIG}\" ${imported_location}
+        )
+!!IF !isEmpty(CMAKE_STATIC_TYPE)
+            set_property(TARGET ${TARGET_NAME} APPEND PROPERTY STATIC_PLUGINS ${PLUGIN_NAME})
+            get_filename_component(_PLUGIN_DIR ${PLUGIN_LOCATION} PATH)
+            get_filename_component(_PLUGIN_DIR_NAME ${_PLUGIN_DIR} NAME)
+            get_filename_component(_PLUGIN_NAME ${PLUGIN_LOCATION} NAME)
+            string(REGEX REPLACE \"^lib(.*)\\\\.a\" \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/lib/qt/plugins/${_PLUGIN_DIR_NAME}/\\\\1.prl\" PLUGIN_PRL_FILE_LOCATION ${_PLUGIN_NAME})
+            if(NOT EXISTS ${PLUGIN_PRL_FILE_LOCATION})
+                string(REGEX REPLACE \"^lib(.*)\\\\.a\" \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/lib/qt/plugins/${_PLUGIN_DIR_NAME}/\\\\1.static.prl\" PLUGIN_PRL_FILE_LOCATION ${_PLUGIN_NAME})
+            endif()
+            if(NOT EXISTS ${PLUGIN_PRL_FILE_LOCATION})
+                string(REGEX REPLACE \"^lib(.*)\\\\.a\" \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/lib/qt/plugins/${_PLUGIN_DIR_NAME}/lib\\\\1.prl\" PLUGIN_PRL_FILE_LOCATION ${_PLUGIN_NAME})
+            endif()
+            if(NOT EXISTS ${PLUGIN_PRL_FILE_LOCATION})
+                message(FATAL_ERROR "The prl file containing dependencies of static plugin ${PLUGIN_TARGET_NAME} of ${TARGET_NAME} could not be found.")
+            endif()
+            _process_plugin_prl_file(${PLUGIN_PRL_FILE_LOCATION} ${CONFIG} \"lib/qt/plugins\" ${PLUGIN_LOCATION})
+!!ENDIF
+
+    endmacro()
+
+    if(pluginTargets)
+        foreach(pluginTarget ${pluginTargets})
+            include(${pluginTarget})
+        endforeach()
+    endif()
+
     set(_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIRS_EXIST TRUE)
     foreach (_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIR ${Qt5$${CMAKE_MODULE_NAME}_OWN_PRIVATE_INCLUDE_DIRS})
         if (NOT EXISTS ${_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIR})
@@ -336,9 +438,11 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
 !!ELSE
         \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" )
 !!ENDIF
-        _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_LIB_FILE_LOCATION_RELEASE}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" )
-!!ENDIF // CMAKE_STATIC_WINDOWS_BUILD
+        _populate_$${CMAKE_MODULE_NAME}_target_properties(Qt5::$${CMAKE_MODULE_NAME} RELEASE \"$${CMAKE_LIB_FILE_LOCATION_RELEASE}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" )
     endif()
+!!ENDIF // CMAKE_STATIC_TYPE
+
+
 !!ENDIF // CMAKE_RELEASE_TYPE
 !!ENDIF // CMAKE_FIND_OTHER_LIBRARY_BUILD
 
@@ -349,29 +453,6 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
     )
 !!ENDIF // TEMPLATE != aux
 
-    file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\")
-
-    macro(_populate_$${CMAKE_MODULE_NAME}_plugin_properties Plugin Configuration PLUGIN_LOCATION)
-        set_property(TARGET Qt5::${Plugin} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${Configuration})
-
-!!IF isEmpty(CMAKE_PLUGIN_DIR_IS_ABSOLUTE)
-        set(imported_location \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_PLUGIN_DIR}${PLUGIN_LOCATION}\")
-!!ELSE
-        set(imported_location \"$${CMAKE_PLUGIN_DIR}${PLUGIN_LOCATION}\")
-!!ENDIF
-        _qt5_$${CMAKE_MODULE_NAME}_check_file_exists(${imported_location})
-        set_target_properties(Qt5::${Plugin} PROPERTIES
-            \"IMPORTED_LOCATION_${Configuration}\" ${imported_location}
-        )
-    endmacro()
-
-    if (pluginTargets)
-        foreach(pluginTarget ${pluginTargets})
-            include(${pluginTarget})
-        endforeach()
-    endif()
-
-
 !!IF !isEmpty(CMAKE_MODULE_EXTRAS)
     include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}ConfigExtras.cmake\")
 !!ENDIF
diff --git a/mkspecs/features/data/cmake/Qt5PluginTarget.cmake.in b/mkspecs/features/data/cmake/Qt5PluginTarget.cmake.in
index 5baf0fdb10..ec5f3cc437 100644
--- a/mkspecs/features/data/cmake/Qt5PluginTarget.cmake.in
+++ b/mkspecs/features/data/cmake/Qt5PluginTarget.cmake.in
@@ -1,11 +1,14 @@
-
-add_library(Qt5::$$CMAKE_PLUGIN_NAME MODULE IMPORTED)
+# Some Qt modules also load plugin target in extra config, so check whether the target already exists
+if(NOT TARGET Qt5::$$CMAKE_PLUGIN_NAME)
+    add_library(Qt5::$$CMAKE_PLUGIN_NAME MODULE IMPORTED)
 
 !!IF !isEmpty(CMAKE_RELEASE_TYPE)
-_populate_$${CMAKE_MODULE_NAME}_plugin_properties($$CMAKE_PLUGIN_NAME RELEASE \"$${CMAKE_PLUGIN_LOCATION_RELEASE}\")
+    _populate_$${CMAKE_MODULE_NAME}_plugin_properties(Qt5::$$CMAKE_MODULE_NAME Qt5::$$CMAKE_PLUGIN_NAME $$CMAKE_PLUGIN_NAME RELEASE \"$${CMAKE_PLUGIN_LOCATION_RELEASE}\")
 !!ENDIF
 !!IF !isEmpty(CMAKE_DEBUG_TYPE)
-_populate_$${CMAKE_MODULE_NAME}_plugin_properties($$CMAKE_PLUGIN_NAME DEBUG \"$${CMAKE_PLUGIN_LOCATION_DEBUG}\")
+    _populate_$${CMAKE_MODULE_NAME}_plugin_properties(Qt5::$$CMAKE_MODULE_NAME Qt5::$$CMAKE_PLUGIN_NAME $$CMAKE_PLUGIN_NAME DEBUG \"$${CMAKE_PLUGIN_LOCATION_DEBUG}\")
 !!ENDIF
 
 list(APPEND Qt5$${CMAKE_MODULE_NAME}_PLUGINS Qt5::$$CMAKE_PLUGIN_NAME)
+
+endif()
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 56f0a3b703..40af76cc84 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -998,6 +998,13 @@ MakefileGenerator::writePrlFile(QTextStream &t)
         for (ProStringList::Iterator it = libs.begin(); it != libs.end(); ++it)
             t << qv(project->values((*it).toKey()));
         t << endl;
+        t << "QMAKE_PRL_LIBS_FOR_CMAKE = ";
+        QString sep;
+        for (ProStringList::Iterator it = libs.begin(); it != libs.end(); ++it) {
+            t << sep << project->values((*it).toKey()).join(';').replace('\\', "\\\\");
+            sep = ';';
+        }
+        t << endl;
     }
 }
 
-- 
2.13.4

