Merge topic 'autogen-qt-version-from-dirprops'

91d98542d2 Merge branch 'autogen-qt-version-from-dirprops-release' into autogen-qt-version-from-dirprops-master
062d21c36a Autogen: Read the Qt version from directory properties as well
17ac7c4024 Tests: add cases for providing Qt5Core_VERSION manually
2df6d69014 AutoGen: query Qt5 version from directory properties
b598dfb65e Tests: add cases for providing Qt5Core_VERSION manually

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2883
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 1d7f6d1..caeed15 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -1370,7 +1370,7 @@
   this->Target->AddSource(filename, prepend);
 }
 
-static unsigned int CharPtrToInt(const char* const input)
+static unsigned int CharPtrToUInt(const char* const input)
 {
   unsigned long tmp = 0;
   if (input != nullptr && cmSystemTools::StringToULong(input, &tmp)) {
@@ -1379,36 +1379,43 @@
   return 0;
 }
 
-static unsigned int StringToInt(const std::string& input)
-{
-  return input.empty() ? 0 : CharPtrToInt(input.c_str());
-}
-
-static std::vector<cmQtAutoGenInitializer::IntegerVersion> GetKnownQtVersions(
+static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
   cmGeneratorTarget const* target)
 {
   cmMakefile* makefile = target->Target->GetMakefile();
-
-  std::vector<cmQtAutoGenInitializer::IntegerVersion> result;
-  for (const std::string& prefix :
-       std::vector<std::string>({ "Qt6Core", "Qt5Core", "QT" })) {
-    auto tmp = cmQtAutoGenInitializer::IntegerVersion(
-      StringToInt(makefile->GetSafeDefinition(prefix + "_VERSION_MAJOR")),
-      StringToInt(makefile->GetSafeDefinition(prefix + "_VERSION_MINOR")));
-    if (tmp.Major != 0) {
-      result.push_back(tmp);
+  std::vector<cmQtAutoGen::IntegerVersion> result;
+  // Adds a version to the result (nullptr safe)
+  auto addVersion = [&result](const char* major, const char* minor) {
+    cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major),
+                                    CharPtrToUInt(minor));
+    if (ver.Major != 0) {
+      result.emplace_back(ver);
     }
+  };
+  // Qt version variable prefixes
+  std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core", "QT" } };
+
+  // Read versions from variables
+  for (const std::string& prefix : prefixes) {
+    addVersion(makefile->GetDefinition(prefix + "_VERSION_MAJOR"),
+               makefile->GetDefinition(prefix + "_VERSION_MINOR"));
+  }
+
+  // Read versions from directory properties
+  for (const std::string& prefix : prefixes) {
+    addVersion(makefile->GetProperty(prefix + "_VERSION_MAJOR"),
+               makefile->GetProperty(prefix + "_VERSION_MINOR"));
   }
 
   return result;
 }
 
-std::pair<cmQtAutoGenInitializer::IntegerVersion, unsigned int>
+std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
 cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
 {
   std::pair<IntegerVersion, unsigned int> res(
     IntegerVersion(),
-    CharPtrToInt(target->GetLinkInterfaceDependentStringProperty(
+    CharPtrToUInt(target->GetLinkInterfaceDependentStringProperty(
       "QT_MAJOR_VERSION", "")));
 
   auto knownQtVersions = GetKnownQtVersions(target);
diff --git a/Tests/RunCMake/Autogen/QtInFunction.cmake b/Tests/RunCMake/Autogen/QtInFunction.cmake
new file mode 100644
index 0000000..a44bc5a
--- /dev/null
+++ b/Tests/RunCMake/Autogen/QtInFunction.cmake
@@ -0,0 +1,13 @@
+enable_language(CXX)
+
+function (use_autogen target)
+  find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
+  set(Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}" PARENT_SCOPE)
+  set(Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}" PARENT_SCOPE)
+  set_property(TARGET "${target}" PROPERTY AUTOMOC 1)
+  set_property(TARGET "${target}" PROPERTY AUTORCC 1)
+  set_property(TARGET "${target}" PROPERTY AUTOUIC 1)
+endfunction ()
+
+add_executable(main empty.cpp)
+use_autogen(main)
diff --git a/Tests/RunCMake/Autogen/QtInFunctionNested-stderr.txt b/Tests/RunCMake/Autogen/QtInFunctionNested-stderr.txt
new file mode 100644
index 0000000..1c6660a
--- /dev/null
+++ b/Tests/RunCMake/Autogen/QtInFunctionNested-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Warning \(dev\) in CMakeLists.txt:
+  AUTOGEN: No valid Qt version found for target main.  AUTOMOC, AUTOUIC and
+  AUTORCC disabled.  Consider adding:
+
+    find_package\(Qt<QTVERSION> COMPONENTS Widgets\)
+
+  to your CMakeLists.txt file.
+This warning is for project developers.  Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/Autogen/QtInFunctionNested.cmake b/Tests/RunCMake/Autogen/QtInFunctionNested.cmake
new file mode 100644
index 0000000..5421ba0
--- /dev/null
+++ b/Tests/RunCMake/Autogen/QtInFunctionNested.cmake
@@ -0,0 +1,17 @@
+enable_language(CXX)
+
+function (use_autogen target)
+  find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
+  set(Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}" PARENT_SCOPE)
+  set(Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}" PARENT_SCOPE)
+  set_property(TARGET "${target}" PROPERTY AUTOMOC 1)
+  set_property(TARGET "${target}" PROPERTY AUTORCC 1)
+  set_property(TARGET "${target}" PROPERTY AUTOUIC 1)
+endfunction ()
+
+function (wrap_autogen target)
+  use_autogen("${target}")
+endfunction ()
+
+add_executable(main empty.cpp)
+wrap_autogen(main)
diff --git a/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake b/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake
new file mode 100644
index 0000000..35f1cd1
--- /dev/null
+++ b/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake
@@ -0,0 +1,21 @@
+enable_language(CXX)
+
+function (use_autogen target)
+  find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
+  set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+    PROPERTY
+      Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}")
+  set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+    PROPERTY
+      Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}")
+  set_property(TARGET "${target}" PROPERTY AUTOMOC 1)
+  set_property(TARGET "${target}" PROPERTY AUTORCC 1)
+  set_property(TARGET "${target}" PROPERTY AUTOUIC 1)
+endfunction ()
+
+function (wrap_autogen target)
+  use_autogen("${target}")
+endfunction ()
+
+add_executable(main empty.cpp)
+wrap_autogen(main)
diff --git a/Tests/RunCMake/Autogen/RunCMakeTest.cmake b/Tests/RunCMake/Autogen/RunCMakeTest.cmake
index e52f28d..a31b67c 100644
--- a/Tests/RunCMake/Autogen/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Autogen/RunCMakeTest.cmake
@@ -1,3 +1,8 @@
 include(RunCMake)
 
 run_cmake(NoQt)
+if (with_qt5)
+  run_cmake(QtInFunction)
+  run_cmake(QtInFunctionNested)
+  run_cmake(QtInFunctionProperty)
+endif ()
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 2de90e7..1f3e5c3 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -150,7 +150,14 @@
 endif()
 
 add_RunCMake_test(AndroidTestUtilities)
-add_RunCMake_test(Autogen)
+set(autogen_with_qt5 FALSE)
+if(CMake_TEST_Qt5)
+  find_package(Qt5Widgets QUIET NO_MODULE)
+endif()
+if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND)
+  set(autogen_with_qt5 TRUE)
+endif ()
+add_RunCMake_test(Autogen -Dwith_qt5=${autogen_with_qt5})
 add_RunCMake_test(BuildDepends)
 if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
   add_RunCMake_test(Byproducts)