Repository: conan-io/conan-center-index

Issue:
[package] qt/6.1.1: Platform plugins should not be linked unless Default_IF is true
with `cmake_find_multi`

on windows the following plugins are built (`QWindowsIntegrationPlugin` and `QWindowsDirect2DPlugin`)

both are platform plugins and duplicate symbols by default platform plugins are disabled but only enabled / added when the DEFAULT_IF argument is set to true (thus in this case since it's a windows platform only `QWindowsIntegrationPlugin` should be built/linked.



Discussion:
I don't understand what you are describing. qt recipe does not declare targets for  QWindowsIntegrationPlugin  nor QWindowsDirect2DPlugin currently, so they should not exist in the files generated by `cmake_find_package_multi`
Could you please give us more details so that we can try to reproduce the problem, and the full log ?
I think this is similar to https://codereview.qt-project.org/c/qt/qtbase/+/318857 and I think this might be an issue because we don't use the original Qt cmake files (not sure).

As an example both QWindowsIntegrationPlugin and QWindowsDirect2DPlugin contain:
```
lib/objects-Release/QWindowsIntegrationPlugin_resources_1/.rcc/qrc_openglblacklists.cpp.obj
lib/objects-Release/QWindowsDirect2DPlugin _resources_1/.rcc/qrc_openglblacklists.cpp.obj
```
which results in an redefinitions of symbols in those object files. You only encounter this when linking statically. Ref. the example log below.

```
[8/9] Linking CXX executable src\UI.exe
FAILED: src/UI.exe
cmd.exe /C "cd . && C:\Users\mjvk\.conan\data\cmake\3.20.4\_\_\package\0a420ff5c47119e668867cdb51baff0eca1fdb68\bin\cmake.exe -E vs_link_exe --intdir=src\CMakeFiles\UI.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100183~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100183~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MIB055~1\2019\BUILDT~1\VC\Tools\MSVC\1428~1.299\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\UI.rsp  /out:src\UI.exe /implib:src\UI.lib /pdb:src\UI.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console  && cd ."
LINK: command "C:\PROGRA~2\MIB055~1\2019\BUILDT~1\VC\Tools\MSVC\1428~1.299\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\UI.rsp /out:src\UI.exe /implib:src\UI.lib /pdb:src\UI.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console /MANIFEST /MANIFESTFILE:src\UI.exe.manifest" failed (exit code 1181) with the following output:
C:\.conan\10bb20\1\lib\objects-Release\Quick_resources_1\.rcc\qrc_scenegraph.cpp.obj : warning LNK4042: object specified more than once; extras ignored
C:\.conan\10bb20\1\lib\objects-Release\Gui_resources_1\.rcc\qrc_qpdf.cpp.obj : warning LNK4042: object specified more than once; extras ignored
qrc_openglblacklists.cpp.obj : error LNK2005: "int __cdecl qCleanupResources_openglblacklists(void)" (?qCleanupResources_openglblacklists@@YAHXZ) already defined in qrc_openglblacklists.cpp.obj
qrc_openglblacklists.cpp.obj : error LNK2005: "int __cdecl qInitResources_openglblacklists(void)" (?qInitResources_openglblacklists@@YAHXZ) already defined in qrc_openglblacklists.cpp.obj
qrc_cursors.cpp.obj : error LNK2005: "int __cdecl qCleanupResources_cursors(void)" (?qCleanupResources_cursors@@YAHXZ) already defined in qrc_cursors.cpp.obj
qrc_cursors.cpp.obj : error LNK2005: "int __cdecl qInitResources_cursors(void)" (?qInitResources_cursors@@YAHXZ) already defined in qrc_cursors.cpp.obj
```

Ref. https://bugreports.qt.io/browse/QTBUG-88080 for a similar issue.

Direct2d is enabled automatically if possible. I think it should just not be linked automatically.
```python
objects_dirs = glob.glob(os.path.join(self.package_folder, "lib", "objects-*/"))
for object_dir in objects_dirs:
            for m in os.listdir(object_dir):
                submodules_dir = os.path.join(object_dir, m)
                component = "qt" + m[:m.find("_")]
                for sub_dir in os.listdir(submodules_dir):
                    submodule_dir = os.path.join(submodules_dir, sub_dir)
                    obj_files = [os.path.join(submodule_dir, file) for file in os.listdir(submodule_dir)]
                    self.cpp_info.components[component].exelinkflags.extend(obj_files)
                    self.cpp_info.components[component].sharedlinkflags.extend(obj_files)
````

From the recipe, all the obj files under objects-* are added into linkflags include QWindowsIntegrationPlugin and QWindowsDirect2DPlugin.

In the generated conanbuildinfo.cmake, you could see:
```cmake
set(CONAN_SHARED_LINKER_FLAGS_QT_LIST "C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\PrintSupport_resources_1\\.rcc\\qrc_qprintdialog.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\PrintSupport_resources_2\\.rcc\\qrc_qprintdialog1.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\Widgets_resources_1\\.rcc\\qrc_qstyle.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\Widgets_resources_2\\.rcc\\qrc_qstyle1.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\Widgets_resources_3\\.rcc\\qrc_qmessagebox.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\Gui_resources_1\\.rcc\\qrc_qpdf.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\QWindowsDirect2DIntegrationPlugin_resources_1\\.rcc\\qrc_openglblacklists.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\QWindowsDirect2DIntegrationPlugin_resources_2\\.rcc\\qrc_cursors.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\QWindowsIntegrationPlugin_resources_1\\.rcc\\qrc_openglblacklists.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\QWindowsIntegrationPlugin_resources_2\\.rcc\\qrc_cursors.cpp.obj")
set(CONAN_EXE_LINKER_FLAGS_QT_LIST "C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\PrintSupport_resources_1\\.rcc\\qrc_qprintdialog.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\PrintSupport_resources_2\\.rcc\\qrc_qprintdialog1.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\Widgets_resources_1\\.rcc\\qrc_qstyle.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\Widgets_resources_2\\.rcc\\qrc_qstyle1.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\Widgets_resources_3\\.rcc\\qrc_qmessagebox.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\Gui_resources_1\\.rcc\\qrc_qpdf.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\QWindowsDirect2DIntegrationPlugin_resources_1\\.rcc\\qrc_openglblacklists.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\QWindowsDirect2DIntegrationPlugin_resources_2\\.rcc\\qrc_cursors.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\QWindowsIntegrationPlugin_resources_1\\.rcc\\qrc_openglblacklists.cpp.obj;C:\\.conan\\b1dddb\\1\\lib\\objects-Release\\QWindowsIntegrationPlugin_resources_2\\.rcc\\qrc_cursors.cpp.obj")
```
@QShen3 @mjvankampen @DhruvParanjape Would you have the opportunity to try https://github.com/conan-io/conan-center-index/pull/7152 to see if it fixes the problem, and is usable ?

Resolving patch:
diff --git a/recipes/qt/6.x.x/conanfile.py b/recipes/qt/6.x.x/conanfile.py
--- a/recipes/qt/6.x.x/conanfile.py
+++ b/recipes/qt/6.x.x/conanfile.py
@@ -693,7 +693,11 @@ def _create_module(module, requires=[]):
             assert componentname not in self.cpp_info.components, "Module %s already present in self.cpp_info.components" % module
             self.cpp_info.components[componentname].names["cmake_find_package"] = module
             self.cpp_info.components[componentname].names["cmake_find_package_multi"] = module
-            self.cpp_info.components[componentname].libs = ["Qt6%s%s" % (module, libsuffix)]
+            if module.endswith("Private"):
+                libname = module[:-7]
+            else:
+                libname = module
+            self.cpp_info.components[componentname].libs = ["Qt6%s%s" % (libname, libsuffix)]
             self.cpp_info.components[componentname].includedirs = ["include", os.path.join("include", "Qt%s" % module)]
             self.cpp_info.components[componentname].defines = ["QT_%s_LIB" % module.upper()]
             if module != "Core" and "Core" not in requires:
@@ -757,6 +761,30 @@ def _create_plugin(pluginname, libname, type, requires):
             if self.options.with_libjpeg == "libjpeg":
                 gui_reqs.append("libjpeg::libjpeg")
             _create_module("Gui", gui_reqs)
+
+            if self.settings.os == "Windows":
+                _create_plugin("QWindowsIntegrationPlugin", "qwindows", "platforms", ["Core", "Gui"])
+                self.cpp_info.components["qtQWindowsIntegrationPlugin"].system_libs = ["advapi32", "dwmapi", "gdi32", "imm32",
+                    "ole32", "oleaut32", "shell32", "shlwapi", "user32", "winmm", "winspool", "wtsapi32"]
+            elif self.settings.os == "Android":
+                _create_plugin("QAndroidIntegrationPlugin", "qtforandroid", "platforms", ["Core", "Gui"])
+                self.cpp_info.components["qtQAndroidIntegrationPlugin"].system_libs = ["android", "jnigraphics"]
+            elif self.settings.os == "Macos":
+                _create_plugin("QCocoaIntegrationPlugin", "qcocoa", "platforms", ["Core", "Gui"])
+                self.cpp_info.components["QCocoaIntegrationPlugin"].frameworks = ["AppKit", "Carbon", "CoreServices", "CoreVideo",
+                    "IOKit", "IOSurface", "Metal", "QuartzCore"]
+            elif self.settings.os in ["iOS", "tvOS"]:
+                _create_plugin("QIOSIntegrationPlugin", "qios", "platforms", [])
+                self.cpp_info.components["QIOSIntegrationPlugin"].frameworks = ["AudioToolbox", "Foundation", "Metal",
+                    "QuartzCore", "UIKit"]
+            elif self.settings.os == "watchOS":
+                _create_plugin("QMinimalIntegrationPlugin", "qminimal", "platforms", [])
+            elif self.settings.os == "Emscripten":
+                _create_plugin("QWasmIntegrationPlugin", "qwasm", "platforms", ["Core", "Gui"])
+            else:
+                _create_module("XcbQpaPrivate", ["xkbcommon::libxkbcommon-x11", "xorg::xorg"])
+                _create_plugin("QXcbIntegrationPlugin", "qxcb", "platforms", ["Core", "Gui", "XcbQpaPrivate"])
+
         if self.options.with_sqlite3:
             _create_plugin("QSQLiteDriverPlugin", "qsqlite", "sqldrivers", ["sqlite3::sqlite3"])
         if self.options.with_pq:
@@ -939,8 +967,10 @@ def _create_plugin(pluginname, libname, type, requires):
         objects_dirs = glob.glob(os.path.join(self.package_folder, "lib", "objects-*/"))
         for object_dir in objects_dirs:
             for m in os.listdir(object_dir):
-                submodules_dir = os.path.join(object_dir, m)
                 component = "qt" + m[:m.find("_")]
+                if component not in self.cpp_info.components:
+                    continue
+                submodules_dir = os.path.join(object_dir, m)
                 for sub_dir in os.listdir(submodules_dir):
                     submodule_dir = os.path.join(submodules_dir, sub_dir)
                     obj_files = [os.path.join(submodule_dir, file) for file in os.listdir(submodule_dir)]


Test patch: