Repository: conan-io/conan-center-index

Issue:
[package] qt/5.15.2: qtmain library missing; problems with asserts


### Package and Environment Details (include every applicable attribute)
  * Package Name/Version: **qt/5.15.20**
  * Operating System+version: **Windows 10**
  * Compiler+version: **VS 17**
  * Conan version: **conan 1.45.0**
  * Python version: **Python 3.10.0**


### Conan profile (output of `conan profile show default` or `conan profile show <profile>` if custom profile is in use)
```
[settings]
os=Windows
arch=x86_64
compiler=Visual Studio
compiler.version=17
build_type=Release
[options]
[conf]
[build_requires]
[env]
```


### Steps to reproduce (Include if Applicable)

For now Qt recipe adds these flags for MSVC builds:

https://github.com/conan-io/conan-center-index/blob/c4c5a76149b9892ad588d2e02f379316757defb0/recipes/qt/5.x.x/conanfile.py#L918

And this is OK for console applications and even somehow works for GUI applications but this prevents the ability to ignore asserts (skip them) and continue program execution (which is very convenient).

Also https://doc.qt.io/qt-5/qtmain.html library is missing. There is widely used CMake policy https://cmake.org/cmake/help/latest/policy/CMP0020.html which enables automatic linking of qtmain to executables and I assume users expect it to work



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
@@ -728,8 +728,8 @@ def _getenvpath(var):
                         self.run(self._make_program(), run_environment=True)
 
     @property
-    def _cmake_executables_file(self):
-        return os.path.join("lib", "cmake", "Qt5Core", "conan_qt_executables_variables.cmake")
+    def _cmake_core_extras_file(self):
+        return os.path.join("lib", "cmake", "Qt5Core", "conan_qt_core_extras.cmake")
 
     def _cmake_qt5_private_file(self, module):
         return os.path.join("lib", "cmake", "Qt5{0}".format(module), "conan_qt_qt5_{0}private.cmake".format(module.lower()))
@@ -803,7 +803,26 @@ def package(self):
                     endif()
                     """.format(target=target, ext=extension, namespace=namespace, uppercase_target=target.upper()))
 
-        tools.save(os.path.join(self.package_folder, self._cmake_executables_file), filecontents)
+        if self.settings.os == "Windows":
+            filecontents += textwrap.dedent("""\
+                set(Qt5Core_QTMAIN_LIBRARIES Qt5::WinMain)
+                if (NOT Qt5_NO_LINK_QTMAIN)
+                    set(_isExe $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>)
+                    set(_isWin32 $<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>)
+                    set(_isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:Qt5_NO_LINK_QTMAIN>>>)
+                    set(_isPolicyNEW $<TARGET_POLICY:CMP0020>)
+                    set_property(TARGET Qt5::Core APPEND PROPERTY
+                        INTERFACE_LINK_LIBRARIES
+                            $<$<AND:${_isExe},${_isWin32},${_isNotExcluded},${_isPolicyNEW}>:Qt5::WinMain>
+                    )
+                    unset(_isExe)
+                    unset(_isWin32)
+                    unset(_isNotExcluded)
+                    unset(_isPolicyNEW)
+                endif()
+                """)
+
+        tools.save(os.path.join(self.package_folder, self._cmake_core_extras_file), filecontents)
 
         def _create_private_module(module, dependencies=[]):
             if "Core" not in dependencies:
@@ -914,8 +933,15 @@ def _create_plugin(pluginname, libname, type, requires):
             core_reqs.append("glib::glib-2.0")
 
         _create_module("Core", core_reqs)
-        if self._is_msvc:
-            self.cpp_info.components["qtCore"].exelinkflags.append("-ENTRY:mainCRTStartup")
+        if self.settings.os == "Windows":
+            module = "WinMain"
+            componentname = "qt%s" % module
+            self.cpp_info.components[componentname].set_property("cmake_target_name", "Qt5::{}".format(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 = ["qtmain%s" % libsuffix]
+            self.cpp_info.components[componentname].includedirs = []
+            self.cpp_info.components[componentname].defines = []
 
         if self.options.gui:
             gui_reqs = []
@@ -1230,9 +1256,9 @@ def _create_plugin(pluginname, libname, type, requires):
                 self.cpp_info.components["qtNetwork"].frameworks.append("GSS")
 
         self.cpp_info.components["qtCore"].builddirs.append(os.path.join("bin","archdatadir","bin"))
-        build_modules.append(self._cmake_executables_file)
-        self.cpp_info.components["qtCore"].build_modules["cmake_find_package"].append(self._cmake_executables_file)
-        self.cpp_info.components["qtCore"].build_modules["cmake_find_package_multi"].append(self._cmake_executables_file)
+        build_modules.append(self._cmake_core_extras_file)
+        self.cpp_info.components["qtCore"].build_modules["cmake_find_package"].append(self._cmake_core_extras_file)
+        self.cpp_info.components["qtCore"].build_modules["cmake_find_package_multi"].append(self._cmake_core_extras_file)
         build_modules.append(self._cmake_qt5_private_file("Core"))
         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"))


Test patch:
diff --git a/recipes/qt/5.x.x/test_package/CMakeLists.txt b/recipes/qt/5.x.x/test_package/CMakeLists.txt
--- a/recipes/qt/5.x.x/test_package/CMakeLists.txt
+++ b/recipes/qt/5.x.x/test_package/CMakeLists.txt
@@ -4,6 +4,8 @@ set(CMAKE_CXX_STANDARD 11)
 
 project(test_package)
 
+cmake_policy(SET CMP0020 NEW)
+
 include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
 conan_set_vs_runtime()
 conan_set_libcxx()