Skip to content

Commit

Permalink
add conan.tools.android.android_abi() (#12873)
Browse files Browse the repository at this point in the history
* add conan.tools.android.android_abi

* improve unit tests

* improt unit test again

* Dont fall back to settings if context settings are missing

* Fix tests

---------

Co-authored-by: Rubén Rincón Blanco <rubenrb@jfrog.com>
  • Loading branch information
SpaceIm and AbrilRBS authored Feb 14, 2023
1 parent 106dd31 commit ec2aa42
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 6 deletions.
1 change: 1 addition & 0 deletions conan/tools/android/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from conan.tools.android.utils import android_abi
31 changes: 31 additions & 0 deletions conan/tools/android/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from conan.errors import ConanException


def android_abi(conanfile, context="host"):
"""
Returns Android-NDK ABI
:param conanfile: ConanFile instance
:param context: either "host", "build" or "target"
:return: Android-NDK ABI
"""
if context not in ("host", "build", "target"):
raise ConanException(f"context argument must be either 'host', 'build' or 'target', was '{context}'")

try:
settings = getattr(conanfile, f"settings_{context}")
except AttributeError:
if context == "host":
settings = conanfile.settings
else:
raise ConanException(f"settings_{context} not declared in recipe")
arch = settings.get_safe("arch")
# https://cmake.org/cmake/help/latest/variable/CMAKE_ANDROID_ARCH_ABI.html
return {
"armv5el": "armeabi",
"armv5hf": "armeabi",
"armv5": "armeabi",
"armv6": "armeabi-v6",
"armv7": "armeabi-v7a",
"armv7hf": "armeabi-v7a",
"armv8": "arm64-v8a",
}.get(arch, arch)
8 changes: 2 additions & 6 deletions conan/tools/cmake/toolchain/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from jinja2 import Template

from conan.tools._compilers import architecture_flag, libcxx_flags
from conan.tools.android.utils import android_abi
from conan.tools.apple.apple import is_apple_os, to_apple_arch
from conan.tools.build import build_jobs
from conan.tools.build.cross_building import cross_building
Expand Down Expand Up @@ -301,11 +302,6 @@ def context(self):
if os_ != "Android":
return

android_abi = {"x86": "x86",
"x86_64": "x86_64",
"armv7": "armeabi-v7a",
"armv8": "arm64-v8a"}.get(str(self._conanfile.settings.arch))

# TODO: only 'c++_shared' y 'c++_static' supported?
# https://developer.android.com/ndk/guides/cpp-support
libcxx_str = self._conanfile.settings.get_safe("compiler.libcxx")
Expand All @@ -317,7 +313,7 @@ def context(self):

ctxt_toolchain = {
'android_platform': 'android-' + str(self._conanfile.settings.os.api_level),
'android_abi': android_abi,
'android_abi': android_abi(self._conanfile),
'android_stl': libcxx_str,
'android_ndk_path': android_ndk_path,
}
Expand Down
Empty file.
79 changes: 79 additions & 0 deletions conans/test/unittests/tools/android/test_android_tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from conans.test.utils.mocks import ConanFileMock, MockSettings
from conans.errors import ConanException
from conan.tools.android import android_abi

from pytest import raises

def test_tools_android_abi():
settings_linux = MockSettings({"os": "Linux", "arch": "foo"})

for (arch, expected) in [
("armv5el", "armeabi"),
("armv5hf", "armeabi"),
("armv5", "armeabi"),
("armv6", "armeabi-v6"),
("armv7", "armeabi-v7a"),
("armv7hf", "armeabi-v7a"),
("armv8", "arm64-v8a"),
("x86", "x86"),
("x86_64", "x86_64"),
("mips", "mips"),
("mips_64", "mips_64"),
]:
conanfile = ConanFileMock()
settings_android = MockSettings({"os": "Android", "arch": arch})

# 1 profile (legacy native build)
conanfile.settings = settings_android
assert android_abi(conanfile) == expected
assert android_abi(conanfile, context="host") == expected

with raises(ConanException):
assert android_abi(conanfile, context="build") == expected

with raises(ConanException):
assert android_abi(conanfile, context="target") == expected

# 2 profiles
## native build
conanfile.settings = settings_android
conanfile.settings_host = settings_android
conanfile.settings_build = settings_android
assert android_abi(conanfile) == expected
assert android_abi(conanfile, context="host") == expected
assert android_abi(conanfile, context="build") == expected

with raises(ConanException):
assert android_abi(conanfile, context="target") == expected

## cross-build from Android to Linux (quite hypothetical)
conanfile.settings = settings_linux
conanfile.settings_host = settings_linux
conanfile.settings_build = settings_android
assert android_abi(conanfile) != expected
assert android_abi(conanfile, context="host") != expected
assert android_abi(conanfile, context="build") == expected

with raises(ConanException):
assert android_abi(conanfile, context="target")

## cross-build a recipe from Linux to Android:
### test android_abi in recipe itself
conanfile.settings = settings_android
conanfile.settings_host = settings_android
conanfile.settings_build = settings_linux
assert android_abi(conanfile) == expected
assert android_abi(conanfile, context="host") == expected
assert android_abi(conanfile, context="build") != expected
with raises(ConanException):
android_abi(conanfile, context="target")

### test android_abi in "compiler recipe" (ie a android-ndk recipe in tool_requires of recipe being cross-build)
conanfile.settings = settings_linux
conanfile.settings_host = settings_linux
conanfile.settings_build = settings_linux
conanfile.settings_target = settings_android
assert android_abi(conanfile) != expected
assert android_abi(conanfile, context="host") != expected
assert android_abi(conanfile, context="build") != expected
assert android_abi(conanfile, context="target") == expected

0 comments on commit ec2aa42

Please sign in to comment.