Skip to content

Commit 13177b1

Browse files
authored
Merge pull request #2615 from mzakharo/scipy
use LEGACY_NDK option to build lapack/scipy with a separate NDK
2 parents 61cc596 + 3c55699 commit 13177b1

File tree

5 files changed

+85
-22
lines changed

5 files changed

+85
-22
lines changed

pythonforandroid/recipes/lapack/__init__.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
from multiprocessing import cpu_count
1010
from os.path import join
1111
import sh
12+
from os import environ
13+
from pythonforandroid.util import build_platform
14+
15+
arch_to_sysroot = {'armeabi': 'arm', 'armeabi-v7a': 'arm', 'arm64-v8a': 'arm64'}
1216

1317

1418
class LapackRecipe(Recipe):
@@ -18,12 +22,20 @@ class LapackRecipe(Recipe):
1822
url = 'https://github.com/Reference-LAPACK/lapack/archive/{version}.tar.gz'
1923
libdir = 'build/install/lib'
2024
built_libraries = {'libblas.so': libdir, 'liblapack.so': libdir, 'libcblas.so': libdir}
21-
need_stl_shared = True
2225

2326
def get_recipe_env(self, arch):
2427
env = super().get_recipe_env(arch)
25-
sysroot = f"{self.ctx.ndk_dir}/platforms/{env['NDK_API']}/{arch.platform_dir}"
26-
FC = f"{env['TOOLCHAIN_PREFIX']}-gfortran" # FIXME
28+
29+
ndk_dir = environ.get("LEGACY_NDK")
30+
if ndk_dir is None:
31+
raise BuildInterruptingException("Please set the environment variable 'LEGACY_NDK' to point to a NDK location with gcc/gfortran support (last tested NDK version was 'r19c')")
32+
33+
GCC_VER = '4.9'
34+
HOST = build_platform
35+
36+
sysroot_suffix = arch_to_sysroot.get(arch.arch, arch.arch)
37+
sysroot = f"{ndk_dir}/platforms/{env['NDK_API']}/arch-{sysroot_suffix}"
38+
FC = f"{ndk_dir}/toolchains/{arch.command_prefix}-{GCC_VER}/prebuilt/{HOST}/bin/{arch.command_prefix}-gfortran"
2739
env['FC'] = f'{FC} --sysroot={sysroot}'
2840
if sh.which(FC) is None:
2941
raise BuildInterruptingException(f"{FC} not found. See https://github.com/mzakharo/android-gfortran")
@@ -37,12 +49,13 @@ def build_arch(self, arch):
3749
ensure_dir(build_target)
3850
with current_directory(build_target):
3951
env = self.get_recipe_env(arch)
52+
ndk_dir = environ["LEGACY_NDK"]
4053
shprint(sh.rm, '-rf', 'CMakeFiles/', 'CMakeCache.txt', _env=env)
4154
shprint(sh.cmake, source_dir,
4255
'-DCMAKE_SYSTEM_NAME=Android',
4356
'-DCMAKE_POSITION_INDEPENDENT_CODE=1',
4457
'-DCMAKE_ANDROID_ARCH_ABI={arch}'.format(arch=arch.arch),
45-
'-DCMAKE_ANDROID_NDK=' + self.ctx.ndk_dir,
58+
'-DCMAKE_ANDROID_NDK=' + ndk_dir,
4659
'-DCMAKE_BUILD_TYPE=Release',
4760
'-DCMAKE_INSTALL_PREFIX={}'.format(install_target),
4861
'-DANDROID_ABI={arch}'.format(arch=arch.arch),

pythonforandroid/recipes/numpy/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class NumpyRecipe(CompiledComponentsPythonRecipe):
1919
patches = [
2020
join("patches", "remove-default-paths.patch"),
2121
join("patches", "add_libm_explicitly_to_build.patch"),
22+
join("patches", "fix-missing-threads.h.patch"),
2223
]
2324

2425
def get_recipe_env(self, arch=None, with_flags_in_cc=True):
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
From: Mikhail Zakharov <mzakharo@gmail.com>
2+
Date: Sun, 5 Jun 2022 11:14:23 -0400
3+
Subject: [PATCH] fix missing threads.h
4+
5+
---
6+
numpy/f2py/cfuncs.py | 3 +--
7+
1 file changed, 1 insertion(+), 2 deletions(-)
8+
9+
10+
diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py
11+
index bdd27ad..39cb470 100644
12+
--- a/numpy/f2py/cfuncs.py
13+
+++ b/numpy/f2py/cfuncs.py
14+
@@ -586,8 +586,7 @@ cppmacros["F2PY_THREAD_LOCAL_DECL"] = """\
15+
so `!defined(__STDC_NO_THREADS__)` may give false positive for the existence
16+
of `threads.h` when using an older release of glibc 2.12
17+
See gh-19437 for details on OpenBSD */
18+
-#include <threads.h>
19+
-#define F2PY_THREAD_LOCAL_DECL thread_local
20+
+#define F2PY_THREAD_LOCAL_DECL __thread
21+
#elif defined(__GNUC__) \\
22+
&& (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4)))
23+
#define F2PY_THREAD_LOCAL_DECL __thread
24+
--
25+
2.25.1
26+

pythonforandroid/recipes/pybind11/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
from pythonforandroid.recipe import Recipe
1+
from pythonforandroid.recipe import PythonRecipe
22
from os.path import join
33

44

5-
class Pybind11Recipe(Recipe):
5+
class Pybind11Recipe(PythonRecipe):
66

77
version = '2.9.0'
88
url = 'https://github.com/pybind/pybind11/archive/refs/tags/v{version}.zip'
9+
depends = ['setuptools']
10+
call_hostpython_via_targetpython = False
11+
install_in_hostpython = True
912

1013
def get_include_dir(self, arch):
1114
return join(self.get_build_dir(arch.arch), 'include')

pythonforandroid/recipes/scipy/__init__.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
from pythonforandroid.recipe import CompiledComponentsPythonRecipe, Recipe
22
from multiprocessing import cpu_count
33
from os.path import join
4+
from os import environ
5+
from pythonforandroid.util import build_platform
6+
7+
arch_to_sysroot = {'armeabi': 'arm', 'armeabi-v7a': 'arm', 'arm64-v8a': 'arm64'}
48

59

610
class ScipyRecipe(CompiledComponentsPythonRecipe):
711

8-
version = '1.5.4'
12+
version = '1.8.1'
913
url = f'https://github.com/scipy/scipy/releases/download/v{version}/scipy-{version}.zip'
1014
site_packages_name = 'scipy'
11-
depends = ['setuptools', 'cython', 'numpy', 'lapack']
15+
depends = ['setuptools', 'cython', 'numpy', 'lapack', 'pybind11']
1216
call_hostpython_via_targetpython = False
17+
need_stl_shared = True
1318

1419
def build_compiled_components(self, arch):
1520
self.setup_extra_args = ['-j', str(cpu_count())]
@@ -24,27 +29,42 @@ def rebuild_compiled_components(self, arch, env):
2429
def get_recipe_env(self, arch):
2530
env = super().get_recipe_env(arch)
2631

32+
ndk_dir = environ["LEGACY_NDK"]
2733
GCC_VER = '4.9'
28-
HOST = 'linux-x86_64'
29-
LIB = 'lib64' if '64' in arch.arch else 'lib'
34+
HOST = build_platform
35+
suffix = '64' if '64' in arch.arch else ''
3036

31-
lapack_dir = join(Recipe.get_recipe('lapack', self.ctx).get_build_dir(arch.arch), 'build', 'install')
32-
sysroot = f"{self.ctx.ndk_dir}/platforms/{env['NDK_API']}/{arch.platform_dir}"
33-
sysroot_include = f'{self.ctx.ndk_dir}/toolchains/llvm/prebuilt/{HOST}/sysroot/usr/include'
34-
prefix = "" # FIXME
35-
libgfortran = f'{self.ctx.ndk_dir}/toolchains/{prefix}-{GCC_VER}/prebuilt/{HOST}/{prefix}/{LIB}'
36-
numpylib = self.ctx.get_python_install_dir(arch.arch) + '/numpy/core/lib'
37+
prefix = arch.command_prefix
38+
sysroot_suffix = arch_to_sysroot.get(arch.arch, arch.arch)
39+
sysroot = f"{ndk_dir}/platforms/{env['NDK_API']}/arch-{sysroot_suffix}"
40+
sysroot_include = f'{ndk_dir}/toolchains/llvm/prebuilt/{HOST}/sysroot/usr/include'
41+
CLANG_BIN = f'{ndk_dir}/toolchains/llvm/prebuilt/{HOST}/bin/'
42+
GCC = f'{ndk_dir}/toolchains/{prefix}-{GCC_VER}/prebuilt/{HOST}'
43+
libgfortran = f'{GCC}/{prefix}/lib{suffix}'
44+
45+
numpylib = self.ctx.get_python_install_dir(arch.arch) + '/numpy'
3746
LDSHARED_opts = env['LDSHARED'].split('clang')[1]
47+
arch_cflags = ' '.join(arch.arch_cflags)
3848

49+
# TODO: add pythran support
50+
env['SCIPY_USE_PYTHRAN'] = '0'
51+
52+
lapack_dir = join(Recipe.get_recipe('lapack', self.ctx).get_build_dir(arch.arch), 'build', 'install')
3953
env['LAPACK'] = f'{lapack_dir}/lib'
4054
env['BLAS'] = env['LAPACK']
41-
env['F90'] = f'{prefix}-gfortran'
42-
env['CXX'] += f' -Wl,-l{self.stl_lib_name} -Wl,-L{self.get_stl_lib_dir(arch)}'
43-
env['CPPFLAGS'] += f' --sysroot={sysroot} -I{sysroot_include}/c++/v1 -I{sysroot_include}'
44-
env['LDSHARED'] = 'clang'
45-
env['LDFLAGS'] += f' {LDSHARED_opts} --sysroot={sysroot} -L{libgfortran} -L{numpylib}'
46-
env['LDFLAGS'] += f' -L{self.ctx.ndk_dir}/sources/cxx-stl/llvm-libc++/libs/{arch.arch}/'
4755

56+
# compilers
57+
env['F77'] = f'{GCC}/bin/{prefix}-gfortran'
58+
env['F90'] = f'{GCC}/bin/{prefix}-gfortran'
59+
env['CC'] = f'{CLANG_BIN}/clang -target {arch.target} {arch_cflags}'
60+
env['CXX'] = f'{CLANG_BIN}/clang++ -target {arch.target} {arch_cflags}'
61+
env['LDSHARED'] = f'{CLANG_BIN}/clang'
62+
63+
# flags
64+
env['CPPFLAGS'] = f'-DANDROID -I{sysroot_include}/{prefix} --sysroot={sysroot} -I{sysroot_include}/c++/v1 -I{sysroot_include}'
65+
env['LDFLAGS'] += f' {LDSHARED_opts} --sysroot={sysroot} -L{libgfortran} -L{numpylib}/core/lib -L{numpylib}/random/lib'
66+
env['LDFLAGS'] += f' -l{self.stl_lib_name} '
67+
env['LDFLAGS'] += f' -L{ndk_dir}/sources/cxx-stl/llvm-libc++/libs/{arch.arch}/' # for arm32 - unwind
4868
return env
4969

5070

0 commit comments

Comments
 (0)