qpython-android / qpython3-toolchain

qpython3-toolchain is a tools collection, helping you build QPython3's core from source code.
Do What The F*ck You Want To Public License
2 stars 3 forks source link

[QCT] Initial QPython3 Toolchain #9

Open riverfor opened 6 years ago

riverfor commented 6 years ago

Background

We need to release a new QPython3 toolchain, which allow other guys can build the QPython3 core by themselves.

Features

How to install

riverfor commented 6 years ago

Some notes when compiling Python

Fail to start for encoding issue

Fatal Python error: Py_Initialize: Unable to get the locale encoding zipimport.ZipImportError: can't decompress data; zlib not available

Solution

Failed to compile the python dynamic load modules, so I just check the compile options

Refers

Fatal Python error: PyThreadState_Get: no current thread

Refers

Can't locate symbal sigwaitinfo referenced by python3

Update the android api version from 21 to 23


sysroot/usr/include/signal.h

175 #if __ANDROID_API__ >= 23
176 int sigqueue(pid_t __pid, int __signal, const union sigval __value) __INTRODUCED_IN(23);
177 int sigtimedwait(const sigset_t* __set, siginfo_t* __info, const struct timespec* __timeout) __INTRODUCED_IN(23);
178 int sigwaitinfo(const sigset_t* __set, siginfo_t* __info) __INTRODUCED_IN(23);
179 #endif /* __ANDROID_API__ >= 23 */

Solution

Backward to android API 21

Refers

riverfor commented 6 years ago

Numpy failed to import

When using the newest crystak-ndk clang to compile the numpy

I encountered the issue:

cannot locate symbol "___tls_get_addr"

the clang in newest crystak-ndk clang doesn't support -femulated-tls parameter,

Refers

Solution

Try to compile it with android-ndk-16b's clang, add this option -femulated-tls, finally it worked.

cannot locate symbol ftello64

numpy reports that error.

sysroot/usr/include/stdio.h

182 #if __ANDROID_API__ >= 24
183 int fgetpos(FILE* __fp, fpos_t* __pos) __RENAME(fgetpos64) __INTRODUCED_IN(24);
184 int fsetpos(FILE* __fp, const fpos_t* __pos) __RENAME(fsetpos64) __INTRODUCED_IN(24);
185 int fseeko(FILE* __fp, off_t __offset, int __whence) __RENAME(fseeko64) __INTRODUCED_IN(24);
186 off_t ftello(FILE* __fp) __RENAME(ftello64) __INTRODUCED_IN(24);
187 #endif /* __ANDROID_API__ >= 24 */

Refers

Add patch file

https://github.com/qpython-android/qpython3-toolchain/blob/android-ndk-r16b/mk/numpy/0001-cross-compile.patch

See the following part

--- a/numpy/core/src/multiarray/common.c +++ b/numpy/core/src/multiarray/common.c

Cannot locate symbol __mulodi4 referenced by umath with clang

import numpy report missing __mulodi4

https://sourceware.org/bugzilla/show_bug.cgi?id=19976

Solution

switch to arm-linux-androideabi-gcc

riverfor commented 6 years ago

OpenBlas

libopenblas.so When using the clang to compile the openblas, I can build the libopenblas.so, but when it is used in numpy, it throw the following error " undefined reference to 'stdout' clang cross compile "

Checking the sysroot/usr/include/stdio.h

#if __ANDROID_API__ >= __ANDROID_API_M__

extern FILE* stdin __INTRODUCED_IN(23);

extern FILE* stdout __INTRODUCED_IN(23);

extern FILE* stderr __INTRODUCED_IN(23);

/* C99 and earlier plus current C++ standards say these must be macros. */

#define stdin stdin

#define stdout stdout

#define stderr stderr

#else

/* Before M the actual symbols for stdin and friends had different names. */

extern FILE __sF[] __REMOVED_IN(23);

#define stdin (&__sF[0])

#define stdout (&__sF[1])

#define stderr (&__sF[2])

#endif

Refers

undefined link from libgfrortan

$CC -shared -o libgfortran.so

Solution

It occurred while in testing link, but when I remove the "-lm" flag, it's OK.

riverfor commented 6 years ago

Scipy

We need a cross compiler for scipy's fortran code

Refers

https://github.com/buffer51/android-gfortran

Solution

1 Switch to android-ndk-r13b-with-gfortran under ubuntu

2 install numpy: pip install numpy cython

3 mv /usr/lib/lapack{,.old} && mkdir /usr/lib/lapack.old/lib && mv /usr/lib/liblapack.* /usr/lib/lapack.old/lib

4 replace the numpy/distutils/unixcompiler.py and system_info.py as toolchain's patch of numpy.

Python hack

_sysconfigdata_m_linux_x86_64-linux-gnu.py

 33  'CONFIGURE_CPPFLAGS': '',
 34  #'CONFIGURE_CPPFLAGS': '-I/root/.pyenv/versions/3.6.4/include',
 35  'CONFIGURE_LDFLAGS': '-L/root/.pyenv/versions/3.6.4/lib',
 36  'CONFIG_ARGS': "'--prefix=/root/.pyenv/versions/3.6.4' "
 37                 "'--libdir=/root/.pyenv/versions/3.6.4/lib' "
 38                 "'LDFLAGS=-L/root/.pyenv/versions/3.6.4/lib ' "
 39                 "'CPPFLAGS=-I/root/.pyenv/versions/3.6.4/include '",
 40  'CONFINCLUDEDIR': '',
 41  #'CONFINCLUDEDIR': '/root/.pyenv/versions/3.6.4/include',
 42  'CONFINCLUDEPY': '',
 43  #'CONFINCLUDEPY': '/root/.pyenv/versions/3.6.4/include/python3.6m',

479  'HOST_GNU_TYPE': 'x86_64-pc-linux-gnu',
480  'INCLDIRSTOMAKE': '/root/.pyenv/versions/3.6.4/include '
481                    '/root/.pyenv/versions/3.6.4/include ',
482                    #'/root/.pyenv/versions/3.6.4/include/python3.6m '
483                    #'/root/.pyenv/versions/3.6.4/include/python3.6m',
484  'INCLUDEDIR': '/root/.pyenv/versions/3.6.4/include',
485  'INCLUDEPY': '',
486 # 'INCLUDEPY': '/root/.pyenv/versions/3.6.4/include/python3.6m',
487  'INSTALL': '/usr/bin/install -c',

Hack numpy's

"command/build_clib.py

230             #HACK FOR INSTALL SCIPY
231             log.error("numpy:build_c:compiling C sources b:"+str(include_dirs))
232             for item in include_dirs:
233                 if item != '/root/.pyenv/versions/3.6.4/include/python3.6m':
234                     _include_dirs.append(item)
235             include_dirs = _include_dirs
236             log.error("numpy:build_c:compiling C sources a:"+str(include_dirs))
riverfor commented 6 years ago

Scipy build script after above hack

ln gfortran ln -s which arm-linux-androideabi-gfortran /usr/local/bin/gfortran

python setup.py build_ext -I../../build/target/python/usr/include/python3.6m:../../build/target/openblas/usr/include -L../../build/target/python/usr/lib:../../build/target/openblas/usr/lib -lopenblas,python3.6m,m,gfortran

Error in compiling scipy

Remove -lm to resolve the following error message:

ld/target/python/usr/lib -L../../build/target/openblas/usr/lib -Lbuild/temp.linux-x86_64-3.6 -lopenblas -lopenblas -lopenblas -lpython3.6m -lm -lgfortran -o build/lib.linux-x86_64-3.6/scipy/cluster/_vq.cpython-36m.so
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to '_gfortran_concat_string'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'cabsf'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'csqrtf'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'cexpf'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'cabs'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'csqrt'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'cexp'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to '_gfortran_compare_string'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'csinf'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'csin'
Python/pytime.c:338: error: undefined reference to '__aeabi_ldivmod'
Python/pytime.c:338: error: undefined reference to '__aeabi_ldivmod'
Python/pytime.c:310: error: undefined reference to '__aeabi_d2lz'
Python/pytime.c:365: error: undefined reference to '__aeabi_ldivmod'
Python/pytime.c:373: error: undefined reference to '__aeabi_l2d'
Python/pytime.c:369: error: undefined reference to '__aeabi_ldivmod'
Python/pytime.c:370: error: undefined reference to '__aeabi_l2d'
./Modules/faulthandler.c:673: error: undefined reference to '__aeabi_d2lz'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to '_gfortran_concat_string'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'cabsf'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'csqrtf'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'cexpf'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'cabs'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'csqrt'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'cexp'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to '_gfortran_compare_string'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'csinf'
../../build/target/openblas/usr/lib/libopenblas.so: error: undefined reference to 'csin'
Python/pytime.c:338: error: undefined reference to '__aeabi_ldivmod'
Python/pytime.c:338: error: undefined reference to '__aeabi_ldivmod'
Python/pytime.c:310: error: undefined reference to '__aeabi_d2lz'
Python/pytime.c:365: error: undefined reference to '__aeabi_ldivmod'
Python/pytime.c:373: error: undefined reference to '__aeabi_l2d'
Python/pytime.c:369: error: undefined reference to '__aeabi_ldivmod'
Python/pytime.c:370: error: undefined reference to '__aeabi_l2d'
./Modules/faulthandler.c:673: error: undefined reference to '__aeabi_d2lz'
riverfor commented 6 years ago

Hack numpy's distribute to solve the gfortran issue

numpy/distutils/ccompiler.py

281     #HACK FOR COMPILE SCIPY
282     for item in pp_opts:
283         if item != '-I/root/.pyenv/versions/3.6.4/include/python3.6m':
284             _pp_opts.append(item)
285     pp_opts = _pp_opts
286     
287     cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
288     display = "compile options: '%s'" % (' '.join(cc_args))
numpy/distutils/fcompiler/gnu.py

266     compiler_aliases = ('gfortran', 'arm-linux-androideabi-gfortran')
267     description = 'GNU Fortran 95 compiler'
268 
269     def version_match(self, version_string):
270         v = self.gnu_version_match(version_string)
271         if not v or v[0] != 'gfortran':
272             return None
273         v = v[1]
274         if v >= '4.':
275             # gcc-4 series releases do not support -mno-cygwin option
276             pass
277         else:
278             # use -mno-cygwin flag for gfortran when Python is not
279             # Cygwin-Python
280             if sys.platform == 'win32':
281                 for key in [
282                         'version_cmd', 'compiler_f77', 'compiler_f90',
283                         'compiler_fix', 'linker_so', 'linker_exe'
284                 ]:
285                     self.executables[key].append('-mno-cygwin')
286         return v
287 
288     possible_executables = ['gfortran', 'f95','arm-linux-androideabi-gfortran']
289     executables = {
290         'version_cmd'  : ["<F90>", "-dumpversion"],
291         'compiler_f77' : [None, "-Wall", "-g", "-ffixed-form",
292                           "-fno-second-underscore"] + _EXTRAFLAGS,
293         'compiler_f90' : [None, "-Wall", "-g",
294                           "-fno-second-underscore"] + _EXTRAFLAGS,
295         'compiler_fix' : [None, "-Wall",  "-g","-ffixed-form",
296                           "-fno-second-underscore"] + _EXTRAFLAGS,
297         'linker_so'    : ["<F90>", "", "-g"],
298         'archiver'     : ["ar", "-cr"],
299         'ranlib'       : ["ranlib"],
300         'linker_exe'   : [None, "-Wall"]
301     }
riverfor commented 6 years ago

Updating android-ndk toolchain to fix some strange crash