Repository: conan-io/conan-center-index

Issue:
[package] qt5: error building for Android with NDK 24 due to missing ranlib
### Description

Qt 5 tries to use `aarch64-linux-android-ranlib` but NDK 24 doesn't have it. Only `toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib` exists which is a symlink to `llvm-ar`.

Qt 5 has been tested only against NDK 20b and 21, but would be good to fix it for more modern toolchains too.

### Package and Environment Details

* Package Name/Version: **qt/5.15.8**
* Operating System+version: **macOS 12.6.2**
* Compiler+version: **clang 14**
* Conan version: **conan 1.57.0**
* Python version: **Python 3.10.9**

### Conan profile

Configuration (profile_host):
[settings]
arch=armv8
build_type=Release
compiler=clang
compiler.libcxx=c++_shared
compiler.version=14
os=Android
os.api_level=21
[options]
with_ffmpeg=False
[build_requires]
*: android-ndk/r24
[env]
[conf]
tools.cmake.cmaketoolchain:generator=Ninja
tools.cmake.cmaketoolchain:system_processor=aarch64

Configuration (profile_build):
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=apple-clang
compiler.libcxx=libc++
compiler.version=14
os=Macos
os_build=Macos
[options]
[build_requires]
[env]
[conf]
tools.cmake.cmaketoolchain:generator=Ninja

### Steps to reproduce

```
conan install qt/5.15.8@ \
  -o 'qt/*:openssl=True' \
  -o 'qt/*:opengl=es2' \
  -o 'qt/*:config=-android-sdk <path to SDK>' \
  -o 'qt/*:with_mysql=False' \
  -o 'qt/*:with_md4c=False' \
  -o 'qt/*:with_odbc=False' \
  -o 'qt/*:with_openal=False' \
  -o 'qt/*:with_pq=False'
```

### Logs

<details><summary>Click to expand log</summary>

```
make[3]: /Users/kambala/dev/vcmi/conan-deps-android-64/.conan/data/android-ndk/r24/_/_/package/06d313f2ce6737a31e5d7ccd4d516d2ac742276a/bin/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ranlib: No such file or directory
make[3]: *** [../../lib/libQt5OpenGLExtensions_arm64-v8a.a] Error 1
make[2]: *** [sub-openglextensions-make_first] Error 2

make[4]: /Users/kambala/dev/vcmi/conan-deps-android-64/.conan/data/android-ndk/r24/_/_/package/06d313f2ce6737a31e5d7ccd4d516d2ac742276a/bin/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ranlib: No such file or directory
make[4]: *** [../../../lib/libQt5EdidSupport_arm64-v8a.a] Error 1
make[3]: *** [sub-edid-make_first] Error 2

make[4]: /Users/kambala/dev/vcmi/conan-deps-android-64/.conan/data/android-ndk/r24/_/_/package/06d313f2ce6737a31e5d7ccd4d516d2ac742276a/bin/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ranlib: No such file or directory
make[4]: *** [../../../lib/libQt5DeviceDiscoverySupport_arm64-v8a.a] Error 1
make[3]: *** [sub-devicediscovery-make_first] Error 2

make[4]: /Users/kambala/dev/vcmi/conan-deps-android-64/.conan/data/android-ndk/r24/_/_/package/06d313f2ce6737a31e5d7ccd4d516d2ac742276a/bin/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ranlib: No such file or directory
make[4]: *** [../../../lib/libQt5EventDispatcherSupport_arm64-v8a.a] Error 1
make[3]: *** [sub-eventdispatchers-make_first] Error 2

make[4]: /Users/kambala/dev/vcmi/conan-deps-android-64/.conan/data/android-ndk/r24/_/_/package/06d313f2ce6737a31e5d7ccd4d516d2ac742276a/bin/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ranlib: No such file or directory
make[4]: *** [../../../lib/libQt5ThemeSupport_arm64-v8a.a] Error 1
make[3]: *** [sub-themes-make_first] Error 2

make[4]: /Users/kambala/dev/vcmi/conan-deps-android-64/.conan/data/android-ndk/r24/_/_/package/06d313f2ce6737a31e5d7ccd4d516d2ac742276a/bin/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ranlib: No such file or directory
make[4]: *** [../../../lib/libQt5FbSupport_arm64-v8a.a] Error 1
make[3]: *** [sub-fbconvenience-make_first] Error 2
make[2]: *** [sub-platformsupport-make_first] Error 2
```

</details>



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
@@ -1,5 +1,6 @@
 from conan import ConanFile
 from conan.errors import ConanInvalidConfiguration
+from conan.tools.android import android_abi
 from conan.tools.apple import is_apple_os
 from conan.tools.build import build_jobs, check_min_cppstd, cross_building
 from conan.tools.env import Environment, VirtualBuildEnv, VirtualRunEnv
@@ -14,7 +15,7 @@
 import textwrap
 import shutil
 
-required_conan_version = ">=1.52.0"
+required_conan_version = ">=1.59.0"
 
 
 class QtConan(ConanFile):
@@ -69,6 +70,7 @@ class QtConan(ConanFile):
         "gui": [True, False],
         "widgets": [True, False],
 
+        "android_sdk": [None, "ANY"],
         "device": [None, "ANY"],
         "cross_compile": [None, "ANY"],
         "sysroot": [None, "ANY"],
@@ -111,6 +113,7 @@ class QtConan(ConanFile):
         "gui": True,
         "widgets": True,
 
+        "android_sdk": None,
         "device": None,
         "cross_compile": None,
         "sysroot": None,
@@ -188,6 +191,9 @@ def config_options(self):
         if self.settings.os != "Macos":
             del self.options.qtmacextras
 
+        if self.settings.os != "Android":
+            del self.options.android_sdk
+
     def configure(self):
         # if self.settings.os != "Linux":
         #         self.options.with_libiconv = False # QTBUG-84708
@@ -276,8 +282,11 @@ def validate(self):
             if self.settings.compiler == "gcc" and Version(self.settings.compiler.version) < "5":
                 raise ConanInvalidConfiguration("Compiling Qt WebEngine with gcc < 5 is not supported")
 
-        if self.settings.os == "Android" and self.options.get_safe("opengl", "no") == "desktop":
-            raise ConanInvalidConfiguration("OpenGL desktop is not supported on Android. Consider using OpenGL es2")
+        if self.settings.os == "Android":
+            if self.options.get_safe("opengl", "no") == "desktop":
+                raise ConanInvalidConfiguration("OpenGL desktop is not supported on Android. Consider using OpenGL es2")
+            if not self.options.get_safe("android_sdk", ""):
+                raise ConanInvalidConfiguration("Path to Android SDK is required to build Qt")
 
         if self.settings.os != "Windows" and self.options.get_safe("opengl", "no") == "dynamic":
             raise ConanInvalidConfiguration("Dynamic OpenGL is supported only on Windows.")
@@ -312,7 +321,7 @@ def validate(self):
         if self.options.get_safe("qtwayland", False) and not self.dependencies.direct_host["xkbcommon"].options.with_wayland:
             raise ConanInvalidConfiguration("The 'with_wayland' option for the 'xkbcommon' package must be enabled when the 'qtwayland' option is enabled")
 
-        if cross_building(self) and self.options.cross_compile == "None" and not is_apple_os(self):
+        if cross_building(self) and self.options.cross_compile == "None" and not is_apple_os(self) and self.settings.os != "Android":
             raise ConanInvalidConfiguration("option cross_compile must be set for cross compilation "
                                             "cf https://doc.qt.io/qt-5/configure-options.html#cross-compilation-options")
 
@@ -726,16 +735,15 @@ def build(self):
                 args.append('QMAKE_APPLE_DEVICE_ARCHS="arm64"')
         elif self.settings.os == "Android":
             args += [f"-android-ndk-platform android-{self.settings.os.api_level}"]
-            args += ["-android-abis %s" % {"armv7": "armeabi-v7a",
-                                           "armv8": "arm64-v8a",
-                                           "x86": "x86",
-                                           "x86_64": "x86_64"}.get(str(self.settings.arch))]
+            args += [f"-android-abis {android_abi(self)}"]
 
         if self.settings.get_safe("compiler.libcxx") == "libstdc++":
             args += ["-D_GLIBCXX_USE_CXX11_ABI=0"]
         elif self.settings.get_safe("compiler.libcxx") == "libstdc++11":
             args += ["-D_GLIBCXX_USE_CXX11_ABI=1"]
 
+        if self.options.get_safe("android_sdk", ""):
+            args += [f"-android-sdk {self.options.android_sdk}"]
         if self.options.sysroot:
             args += [f"-sysroot {self.options.sysroot}"]
 
@@ -940,6 +948,8 @@ def package_id(self):
                     self.info.settings.compiler.runtime = "MT/MTd"
             else:
                 self.info.settings.compiler.runtime_type = "Release/Debug"
+        if self.settings.os == "Android":
+            del self.info.options.android_sdk
 
     def package_info(self):
         self.cpp_info.set_property("cmake_file_name", "Qt5")
@@ -957,6 +967,8 @@ def _add_build_module(component, module):
             self.cpp_info.components[component].build_modules["cmake_find_package_multi"].append(module)
 
         libsuffix = ""
+        if self.settings.os == "Android":
+            libsuffix = f"_{android_abi(self)}"
         if not self.options.multiconfiguration:
             if self.settings.build_type == "Debug":
                 if self.settings.os == "Windows" and is_msvc(self):
@@ -1429,8 +1441,9 @@ def _create_plugin(pluginname, libname, plugintype, requires):
                     self.cpp_info.components["qtNetwork"].frameworks.append("GSS")
                 if not self.options.openssl: # with SecureTransport
                     self.cpp_info.components["qtNetwork"].frameworks.append("Security")
-            if self.settings.os == "Macos":
+            if self.settings.os == "Macos" or (self.settings.os == "iOS" and Version(self.settings.compiler.version) >= "14.0"):
                 self.cpp_info.components["qtCore"].frameworks.append("IOKit")     # qtcore requires "_IORegistryEntryCreateCFProperty", "_IOServiceGetMatchingService" and much more which are in "IOKit" framework
+            if self.settings.os == "Macos":
                 self.cpp_info.components["qtCore"].frameworks.append("Cocoa")     # qtcore requires "_OBJC_CLASS_$_NSApplication" and more, which are in "Cocoa" framework
                 self.cpp_info.components["qtCore"].frameworks.append("Security")  # qtcore requires "_SecRequirementCreateWithString" and more, which are in "Security" framework
 


Test patch: