Repository: conan-io/conan-center-index

Issue:
[package] qt/5.x.x: unresolved external symbols when using QWizard on Windows
### Package and Environment Details (include every applicable attribute)
  * Package Name/Version: **qt/5.15.2**
  * Operating System+version: **Windows 21H1**
  * Compiler+version: **VS 16.11**
  * Conan version: **conan 1.40.3**
  * Python version: **Python 3.9.2**


### Conan profile (output of `conan profile show default` or `conan profile show <profile>` if custom profile is in use)
```
[settings]
os=Windows
os_build=Windows
arch=x86_64
arch_build=x86_64
compiler=Visual Studio
compiler.version=16
build_type=Release
[options]
qt5:shared=False
[conf]
[build_requires]
[env]
```

### Steps to reproduce (Include if Applicable)

1. Be on Windows
2. Use static Qt
3. ```#include <QtWidgets/QWizard>```
4. ```QWizard w;``` somewhere
5. Get unresolved external symbols

QWizard uses [uxtheme](https://github.com/qt/qtbase/blob/5.15.2/src/widgets/dialogs/qwizard_win.cpp#L57) and [dwmapi](https://github.com/qt/qtbase/blob/5.15.2/src/widgets/dialogs/qwizard_win.cpp#L59) system libs

### Logs (Include/Attach if Applicable)
<details><summary>Click to expand log</summary>

```
error LNK2019: unresolved external symbol __imp_OpenThemeData referenced in function "public: virtual void __cdecl QVistaBackButton::paintEvent(class QPaintEvent *)" (?paintEvent@QVistaBackButton@@UEAAXPEAVQPaintEvent@@@Z)
error LNK2019: unresolved external symbol __imp_DrawThemeBackground referenced in function "public: virtual void __cdecl QVistaBackButton::paintEvent(class QPaintEvent *)" (?paintEvent@QVistaBackButton@@UEAAXPEAVQPaintEvent@@@Z)
error LNK2019: unresolved external symbol __imp_GetThemeColor referenced in function "public: class QColor __cdecl QVistaHelper::basicWindowFrameColor(void)" (?basicWindowFrameColor@QVistaHelper@@QEAA?AVQColor@@XZ)
error LNK2019: unresolved external symbol __imp_GetThemeSysFont referenced in function "struct tagLOGFONTW __cdecl getCaptionLogFont(void *)" (?getCaptionLogFont@@YA?AUtagLOGFONTW@@PEAX@Z)
error LNK2019: unresolved external symbol __imp_IsThemeActive referenced in function "private: static bool __cdecl QVistaHelper::isThemeActive(void)" (?isThemeActive@QVistaHelper@@CA_NXZ)
error LNK2019: unresolved external symbol __imp_SetWindowThemeAttribute referenced in function "public: void __cdecl QVistaHelper::setTitleBarIconAndCaptionVisible(bool)" (?setTitleBarIconAndCaptionVisible@QVistaHelper@@QEAAX_N@Z)
error LNK2019: unresolved external symbol __imp_DrawThemeTextEx referenced in function "private: bool __cdecl QVistaHelper::drawTitleText(class QPainter *,class QString const &,class QRect const &,struct HDC__ *)" (?drawTitleText@QVistaHelper@@AEAA_NPEAVQPainter@@AEBVQString@@AEBVQRect@@PEAUHDC__@@@Z)
error LNK2019: unresolved external symbol __imp_DwmDefWindowProc referenced in function "private: bool __cdecl QVistaHelper::winEvent(struct tagMSG *,long *)" (?winEvent@QVistaHelper@@AEAA_NPEAUtagMSG@@PEAJ@Z)
error LNK2019: unresolved external symbol __imp_DwmExtendFrameIntoClientArea referenced in function "public: bool __cdecl QVistaHelper::setDWMTitleBar(enum QVistaHelper::TitleBarChangeType)" (?setDWMTitleBar@QVistaHelper@@QEAA_NW4TitleBarChangeType@1@@Z)
error LNK2019: unresolved external symbol __imp_DwmIsCompositionEnabled referenced in function "private: static bool __cdecl QVistaHelper::isCompositionEnabled(void)" (?isCompositionEnabled@QVistaHelper@@CA_NXZ)
```

</details>

[package] qt/5.x.x: Qt5::WidgetsPrivate target is missing
### Package and Environment Details (include every applicable attribute)
  * Package Name/Version: **qt/5.15.2**
  * Operating System+version: **Windows 21H1**
  * Compiler+version: **VS 16.11**
  * Conan version: **conan 1.40.3**
  * Python version: **Python 3.9.2**


### Conan profile (output of `conan profile show default` or `conan profile show <profile>` if custom profile is in use)
```
[settings]
os=Windows
os_build=Windows
arch=x86_64
arch_build=x86_64
compiler=Visual Studio
compiler.version=16
build_type=Release
[options]
[conf]
[build_requires]
[env]
```

I think we should have WidgetsPrivate target as it sometimes used by thirdparty libraries. e.g. I'm developing private package for QtitanRibbon library and it uses QtWidgets private headers.



Discussion:

Resolving patch:
diff --git a/recipes/qt/5.x.x/conanfile.py b/recipes/qt/5.x.x/conanfile.py
--- a/recipes/qt/5.x.x/conanfile.py
+++ b/recipes/qt/5.x.x/conanfile.py
@@ -774,6 +774,8 @@ def package(self):
         tools.save(os.path.join(self.package_folder, self._cmake_executables_file), filecontents)
 
         def _create_private_module(module, dependencies=[]):
+            if "Core" not in dependencies:
+                dependencies.append("Core")
             dependencies_string = ';'.join('Qt5::%s' % dependency for dependency in dependencies)
             contents = textwrap.dedent("""\
             if(NOT TARGET Qt5::{0}Private)
@@ -792,11 +794,14 @@ def _create_private_module(module, dependencies=[]):
 
             tools.save(os.path.join(self.package_folder, self._cmake_qt5_private_file(module)), contents)
 
-        _create_private_module("Core", ["Core"])
+        _create_private_module("Core")
 
         if self.options.gui:
             _create_private_module("Gui", ["CorePrivate", "Gui"])
 
+        if self.options.widgets:
+            _create_private_module("Widgets", ["CorePrivate", "Gui", "GuiPrivate"])
+
         if self.options.qtdeclarative:
             _create_private_module("Qml", ["CorePrivate", "Qml"])
 
@@ -898,6 +903,8 @@ def _create_plugin(pluginname, libname, type, requires):
             if self.options.with_libjpeg == "libjpeg":
                 gui_reqs.append("libjpeg::libjpeg")
             _create_module("Gui", gui_reqs)
+            self.cpp_info.components["qtGui"].build_modules["cmake_find_package"].append(self._cmake_qt5_private_file("Gui"))
+            self.cpp_info.components["qtGui"].build_modules["cmake_find_package_multi"].append(self._cmake_qt5_private_file("Gui"))
 
             if self.settings.os == "Windows":
                 _create_plugin("QWindowsIntegrationPlugin", "qwindows", "platforms", ["Core", "Gui"])
@@ -939,6 +946,8 @@ def _create_plugin(pluginname, libname, type, requires):
         _create_module("Test")
         if self.options.widgets:
             _create_module("Widgets", ["Gui"])
+            self.cpp_info.components["qtWidgets"].build_modules["cmake_find_package"].append(self._cmake_qt5_private_file("Widgets"))
+            self.cpp_info.components["qtWidgets"].build_modules["cmake_find_package_multi"].append(self._cmake_qt5_private_file("Widgets"))
         if self.options.gui and self.options.widgets:
             _create_module("PrintSupport", ["Gui", "Widgets"])
         if self.options.get_safe("opengl", "no") != "no" and self.options.gui:
@@ -1161,6 +1170,9 @@ def _create_plugin(pluginname, libname, type, requires):
                 self.cpp_info.components["qtCore"].system_libs.append("ws2_32")  # qtcore requires "WSAStartup " which is in "Ws2_32.Lib" library
                 self.cpp_info.components["qtNetwork"].system_libs.append("dnsapi")  # qtnetwork from qtbase requires "DnsFree" which is in "Dnsapi.lib" library
                 self.cpp_info.components["qtNetwork"].system_libs.append("iphlpapi")
+                if self.options.widgets:
+                    self.cpp_info.components["qtWidgets"].system_libs.append("UxTheme")
+                    self.cpp_info.components["qtWidgets"].system_libs.append("dwmapi")
                 if self.options.qtwinextras:
                     self.cpp_info.components["qtWinExtras"].system_libs.append("dwmapi")  # qtwinextras requires "DwmGetColorizationColor" which is in "dwmapi.lib" library
 
@@ -1178,9 +1190,6 @@ def _create_plugin(pluginname, libname, type, requires):
         self.cpp_info.components["qtCore"].build_modules["cmake_find_package"].append(self._cmake_qt5_private_file("Core"))
         self.cpp_info.components["qtCore"].build_modules["cmake_find_package_multi"].append(self._cmake_qt5_private_file("Core"))
 
-        self.cpp_info.components["qtGui"].build_modules["cmake_find_package"].append(self._cmake_qt5_private_file("Gui"))
-        self.cpp_info.components["qtGui"].build_modules["cmake_find_package_multi"].append(self._cmake_qt5_private_file("Gui"))
-
         for m in os.listdir(os.path.join("lib", "cmake")):
             module = os.path.join("lib", "cmake", m, "%sMacros.cmake" % m)
             component_name = m.replace("Qt5", "qt")


Test patch: