Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-116622: Android sysconfig updates #118352

Merged
merged 4 commits into from May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions Android/android-env.sh
Expand Up @@ -61,6 +61,12 @@ done
export CFLAGS=""
export LDFLAGS="-Wl,--build-id=sha1 -Wl,--no-rosegment"

# Unlike Linux, Android does not implicitly use a dlopened library to resolve
# relocations in subsequently-loaded libraries, even if RTLD_GLOBAL is used
# (https://github.com/android/ndk/issues/1244). So any library that fails to
# build with this flag, would also fail to load at runtime.
LDFLAGS="$LDFLAGS -Wl,--no-undefined"

# Many packages get away with omitting -lm on Linux, but Android is stricter.
LDFLAGS="$LDFLAGS -lm"

Expand Down
20 changes: 16 additions & 4 deletions Lib/sysconfig/__init__.py
Expand Up @@ -601,10 +601,22 @@ def get_platform():
machine = machine.replace('/', '-')

if osname[:5] == "linux":
# At least on Linux/Intel, 'machine' is the processor --
# i386, etc.
# XXX what about Alpha, SPARC, etc?
return f"{osname}-{machine}"
if sys.platform == "android":
osname = "android"
release = get_config_var("ANDROID_API_LEVEL")

# Wheel tags use the ABI names from Android's own tools.
machine = {
"x86_64": "x86_64",
"i686": "x86",
"aarch64": "arm64_v8a",
"armv7l": "armeabi_v7a",
Comment on lines +610 to +613
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is in the PEP (sorry I didn't catch it) but let me ask -- more to bring this to your attention than anything else:
Is there a specific reason to use Android arch names, rather than ones from configure?

For reference: Fedora used their own arch names, and spent several years migrating to the configure ones when wheels became more universal.
Android wheels will probably always be separate, but it seems they might be compared to other Linux-y wheels more often than other Android apps. Also, maintaining this dict in CPython might not be worth it.

If CPython-style arch names would be better, this is the time to change them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using autoconf-style architecture names everywhere else, including in extension module filenames (see test_android_ext_suffix in test_sysconfig.py). This PR really only affects the platform tag in wheel filenames.

The main reason to use this format is for consistency with the existing Chaquopy wheel repository, which contains over a thousand wheels for Python 3.8-3.12. Having two formats in use would complicate package installers such as pip (which we intend to contribute Android and iOS support for in the near future), and higher-level app building tools such as Briefcase.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using autoconf-style architecture names everywhere else

Right, and this inconsistency is somewhat jarring.
If you'd be interested in setting up aliases in the Chaquopy repository, or adding aliases to packaging, let me know & I can help.

But, no reason for that to hold this PR back.

}[machine]
else:
# At least on Linux/Intel, 'machine' is the processor --
# i386, etc.
# XXX what about Alpha, SPARC, etc?
return f"{osname}-{machine}"
elif osname[:5] == "sunos":
if release[0] >= "5": # SunOS 5 == Solaris 2
osname = "solaris"
Expand Down
20 changes: 20 additions & 0 deletions Lib/test/test_sysconfig.py
Expand Up @@ -232,6 +232,11 @@ def test_get_config_vars(self):
self.assertTrue(cvars)

def test_get_platform(self):
# Check the actual platform returns something reasonable.
actual_platform = get_platform()
self.assertIsInstance(actual_platform, str)
self.assertTrue(actual_platform)

# windows XP, 32bits
os.name = 'nt'
sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
Expand Down Expand Up @@ -347,6 +352,21 @@ def test_get_platform(self):

self.assertEqual(get_platform(), 'linux-i686')

# Android
os.name = 'posix'
sys.platform = 'android'
get_config_vars()['ANDROID_API_LEVEL'] = 9
for machine, abi in {
'x86_64': 'x86_64',
'i686': 'x86',
'aarch64': 'arm64_v8a',
'armv7l': 'armeabi_v7a',
}.items():
with self.subTest(machine):
self._set_uname(('Linux', 'localhost', '3.18.91+',
'#1 Tue Jan 9 20:35:43 UTC 2018', machine))
self.assertEqual(get_platform(), f'android-9-{abi}')

# XXX more platforms to tests here

@unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")
Expand Down
@@ -0,0 +1,2 @@
On Android, :any:`sysconfig.get_platform` now returns the format specified
by :pep:`738`.
7 changes: 6 additions & 1 deletion configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions configure.ac
Expand Up @@ -1148,6 +1148,9 @@ AS_CASE([$host/$ac_cv_cc_name],
[x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64
[aarch64-apple-ios*-simulator/clang], [PY_SUPPORT_TIER=3], dnl iOS Simulator on arm64
[aarch64-apple-ios*/clang], [PY_SUPPORT_TIER=3], dnl iOS on ARM64
[aarch64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on ARM64
[x86_64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on AMD64

[PY_SUPPORT_TIER=0]
)

Expand Down