|
1 | 1 | from os.path import join, isdir, isfile
|
2 | 2 | import sh
|
3 |
| -from pythonforandroid.recipe import NDKRecipe |
4 |
| -from pythonforandroid.toolchain import ( |
5 |
| - current_directory, |
6 |
| - shprint, |
7 |
| -) |
| 3 | +from pythonforandroid.recipe import NDKRecipe, CythonRecipe, Recipe |
| 4 | +from pythonforandroid.toolchain import current_directory, shprint |
8 | 5 | from pythonforandroid.logger import info
|
9 | 6 | from multiprocessing import cpu_count
|
| 7 | +import glob |
10 | 8 |
|
11 | 9 |
|
12 |
| -class GRPCRecipe(NDKRecipe): |
13 |
| - version = 'v1.20.1' |
14 |
| - #url = 'https://github.com/grpc/grpc/archive/{version}.zip' |
| 10 | +class GRPCRecipe(CythonRecipe): |
| 11 | + name = "grpc" |
| 12 | + version = "v1.20.1" |
| 13 | + # url = 'https://github.com/grpc/grpc/archive/{version}.zip' |
15 | 14 | url = None
|
16 |
| - port_git = 'https://github.com/grpc/grpc.git' |
17 |
| - generated_libraries = [ |
18 |
| - 'libgrpc++_cronet.so', |
19 |
| - 'libgrpc_csharp_ext.so', |
20 |
| - 'libgrpc++_unsecure.so', |
21 |
| - 'libgrpc_plugin_support.so', |
22 |
| - 'libgrpc++.so', |
23 |
| - 'libgrpc_cronet.so', |
24 |
| - 'libgrpc_unsecure.so', |
25 |
| - 'libgrpc.so', |
26 |
| - 'libaddress_sorting.a', |
27 |
| - 'libbenchmark.a', |
28 |
| - 'libbenchmark_main.a', |
29 |
| - 'libcares.so', |
30 |
| - 'libcrypto.a', |
31 |
| - 'libgflags.a', |
32 |
| - 'libgflags_nothreads.a', |
33 |
| - 'libglog.a', |
34 |
| - 'libgpr.a', |
35 |
| - 'libgrpc.a', |
36 |
| - 'libgrpc++.a', |
37 |
| - 'libgrpc_cronet.a', |
38 |
| - 'libgrpc++_cronet.a', |
39 |
| - 'libgrpc_csharp_ext.so', |
40 |
| - 'libgrpc_plugin_support.a', |
41 |
| - 'libgrpc_unsecure.a', |
42 |
| - 'libgrpc++_unsecure.a', |
43 |
| - 'libprotobuf.a', |
44 |
| - 'libprotobuf-lite.a', |
45 |
| - 'libprotoc.a', |
46 |
| - 'libssl.a', |
47 |
| - 'libz.a', |
48 |
| - 'libz.so' |
49 |
| - ] |
50 |
| - |
51 |
| - def get_lib_dir(self, arch): |
52 |
| - return join(self.get_build_dir(arch.arch), 'build', 'lib', arch.arch) |
| 15 | + port_git = "https://github.com/grpc/grpc.git" |
| 16 | + depends = ["setuptools"] |
| 17 | + site_packages_name = "grpcio" |
| 18 | + cython_args = ["src/python/grpcio/grpc/_cython"] |
| 19 | + # patches = ["fix_cares.patch"] |
53 | 20 |
|
54 | 21 | def get_recipe_env(self, arch):
|
55 | 22 | env = super(GRPCRecipe, self).get_recipe_env(arch)
|
56 |
| - env['ANDROID_NDK'] = self.ctx.ndk_dir |
57 |
| - env['ANDROID_SDK'] = self.ctx.sdk_dir |
| 23 | + build_dir = self.get_build_dir(arch.arch) |
| 24 | + third_party_dir = join(build_dir, "third_party") |
| 25 | + boringssl_dir = join(third_party_dir, "boringssl") |
| 26 | + env["CC"] = "arm-linux-androideabi-gcc " |
| 27 | + # -fno-rtti avoids ImportError: dlopen failed: cannot locate symbol "_ZTVN10__cxxabiv117__class_type_infoE" referenced by "/data/data/com.admobilize.admp/files/app/_python_bundle/site-packages/grpc/_cython/cygrpc.so" |
| 28 | + # This overwrites the CFLAGS used by grpc |
| 29 | + env[ |
| 30 | + "GRPC_PYTHON_CFLAGS" |
| 31 | + ] = " -I{} -I/opt/android/android-ndk/sources/cxx-stl/gnu-libstdc++/4.9/include -I/opt/android/android-ndk/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -std=c++11 -std=c99 -fvisibility=hidden -fno-wrapv -fno-exceptions -fpermissive -fno-rtti -w ".format( |
| 32 | + join(boringssl_dir, "include") |
| 33 | + ) |
| 34 | + # -llog avoids ImportError: dlopen failed: cannot locate symbol "__android_log_print" referenced by "/data/data/com.admobilize.admp/files/app/_python_bundle/site-packages/grpc/_cython/cygrpc.so" |
| 35 | + # This overwrites the LDFLAGS used by grpc |
| 36 | + env["GRPC_PYTHON_LDFLAGS"] = " -Wl,-wrap,memcpy -static-libgcc -llog -ldl -lm" |
58 | 37 | return env
|
59 | 38 |
|
60 | 39 | def prebuild_arch(self, arch):
|
61 | 40 | build_dir = self.get_build_dir(arch.arch)
|
62 |
| - source_dir = join(build_dir, 'grpc') |
63 |
| - if not isfile(join(source_dir, 'setup.py')): |
| 41 | + source_dir = join(build_dir, "grpc") |
| 42 | + if not isfile(join(build_dir, "setup.py")) and not isfile( |
| 43 | + join(source_dir, "setup.py") |
| 44 | + ): |
64 | 45 | info("clone GRPC sources from {}".format(self.port_git))
|
65 |
| - shprint(sh.git, 'clone', '--recursive', self.port_git, source_dir, _tail=20, _critical=True) |
| 46 | + shprint( |
| 47 | + sh.git, |
| 48 | + "clone", |
| 49 | + "--branch", |
| 50 | + self.version, |
| 51 | + "--single-branch", |
| 52 | + "--recursive", |
| 53 | + self.port_git, |
| 54 | + source_dir, |
| 55 | + _tail=20, |
| 56 | + _critical=True, |
| 57 | + ) |
| 58 | + |
| 59 | + if isfile(join(source_dir, "setup.py")): |
| 60 | + shprint(sh.mv, *glob.glob(join(source_dir, "*")), build_dir) |
| 61 | + shprint(sh.rm, "-rf", source_dir) |
| 62 | + # TODO Fix this hardcoded path |
| 63 | + self.apply_patch( |
| 64 | + "/home/user/admp/p4a-recipes/grpcio/fix_cares.patch", arch.arch |
| 65 | + ) |
66 | 66 |
|
67 | 67 | def build_arch(self, arch):
|
68 |
| - build_dir = self.get_build_dir(arch.arch) |
69 |
| - source_dir = join(build_dir, 'grpc') |
70 |
| - build_dir = join(source_dir, 'build') |
71 |
| - shprint(sh.rm, '-rf', build_dir) |
72 |
| - shprint(sh.mkdir, '-p', build_dir) |
73 |
| - with current_directory(build_dir): |
74 |
| - env = self.get_recipe_env(arch) |
| 68 | + Recipe.build_arch(self, arch) |
75 | 69 |
|
76 |
| - python_major = self.ctx.python_recipe.version[0] |
77 |
| - python_include_root = self.ctx.python_recipe.include_root(arch.arch) |
78 |
| - python_site_packages = self.ctx.get_site_packages_dir() |
79 |
| - python_link_root = self.ctx.python_recipe.link_root(arch.arch) |
80 |
| - python_link_version = self.ctx.python_recipe.major_minor_version_string |
81 |
| - if 'python3' in self.ctx.python_recipe.name: |
82 |
| - python_link_version += 'm' |
83 |
| - python_library = join(python_link_root, |
84 |
| - 'libpython{}.so'.format(python_link_version)) |
85 |
| - python_include_numpy = join(python_site_packages, |
86 |
| - 'numpy', 'core', 'include') |
| 70 | + self.build_cython_components(arch) |
| 71 | + self.install_python_package(arch) # this is the same as in a PythonRecipe |
87 | 72 |
|
88 |
| - shprint(sh.cmake, |
89 |
| - '-DP4A=ON', |
90 |
| - '-DANDROID_ABI={}'.format(arch.arch), |
91 |
| - '-DANDROID_STANDALONE_TOOLCHAIN={}'.format(self.ctx.ndk_dir), |
92 |
| - '-DANDROID_NATIVE_API_LEVEL={}'.format(self.ctx.ndk_api), |
93 |
| - '-DANDROID_EXECUTABLE={}/tools/android'.format(env['ANDROID_SDK']), |
94 |
| - '-DCMAKE_TOOLCHAIN_FILE={}'.format( |
95 |
| - join(self.ctx.ndk_dir, 'build', 'cmake', |
96 |
| - 'android.toolchain.cmake')), |
97 |
| - '-DBUILD_WITH_STANDALONE_TOOLCHAIN=ON', |
98 |
| - '-DBUILD_SHARED_LIBS=ON', |
99 |
| - '-DBUILD_STATIC_LIBS=OFF', |
100 |
| - '-Dprotobuf_BUILD_PROTOC_BINARIES=OFF', |
101 |
| - '-DCMAKE_INSTALL_PREFIX="/opt/install"', |
102 |
| - '-DCMAKE_FIND_ROOT_PATH="/opt/install"', |
103 |
| - '-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH', |
104 |
| - '-DCMAKE_SHARED_LINKER_FLAGS="-llog"', |
105 |
| - '-DCMAKE_EXE_LINKER_FLAGS="-llog"', |
106 |
| - '-DProtobuf_PROTOC_EXECUTABLE=/usr/local/bin/protoc', |
<
1241
td data-grid-cell-id="diff-719e0aea3138b28f5657695bbd1fe8ee356a8008c12772a11db3160343cd2255-107-72-0" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-deletionNum-bgColor, var(--diffBlob-deletion-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">107
| - '-DProtobuf_LIBRARIES=/opt/install/lib/libprotobuf.a', |
108 |
| - '-DProtobuf_PROTOC_LIBRARY=/opt/install/lib/libprotoc.a', |
109 |
| - '-DProtobuf_INCLUDE_DIR=/opt/install/include', |
110 |
| - '-DHAVE_THREAD_SAFETY_ATTRIBUTES=ON', |
111 |
| - '-DHAVE_GNU_POSIX_REGEX=ON', |
112 |
| - '-DHAVE_STD_REGEX=ON', |
113 |
| - '-DRUN_HAVE_STD_REGEX=ON', |
114 |
| - '-DHAVE_POSIX_REGEX=1', |
115 |
| - '-DRUN_HAVE_POSIX_REGEX=ON', |
116 |
| - '-DHAVE_STEADY_CLOCK=ON', |
117 |
| - '-DgRPC_BUILD_TESTS=OFF', |
118 |
| - '-DCMAKE_CROSSCOMPILING=1', |
119 |
| - '-DOPENSSL_SSL_LIBRARY=/usr/local/lib/libssl.so', |
120 |
| - '-DOPENSSL_CRYPTO_LIBRARY=/usr/local/lib/libcrypto.so', |
121 |
| - '-DOPENSSL_INCLUDE_DIR=/usr/local/include', |
122 |
| - '-Dgflags_DIR=/opt/install/lib/cmake/gflags', |
123 |
| - '-DgRPC_PROTOBUF_PROVIDER=package', |
124 |
| - '-DgRPC_ZLIB_PROVIDER=package', |
125 |
| - '-DgRPC_CARES_PROVIDER=package', |
126 |
| - '-DgRPC_SSL_PROVIDER=package', |
127 |
| - '-DgRPC_GFLAGS_PROVIDER=package', |
128 |
| - '-DgRPC_BUILD_CODEGEN=OFF', |
| 73 | + def build_cython_components(self, arch): |
| 74 | + env = self.get_recipe_env(arch) |
| 75 | + build_dir = self.get_build_dir(arch.arch) |
| 76 | + with current_directory(build_dir): |
| 77 | + hostpython = sh.Command(self.ctx.hostpython) |
129 | 78 |
|
130 |
| - source_dir, |
131 |
| - _env=env) |
132 |
| - shprint(sh.make, '-j' + str(cpu_count())) |
133 |
| - # Copy third party shared libs that we need in our final apk |
134 |
| - #sh.cp('-a', sh.glob('./lib/{}/lib*.a'.format(arch.arch)), |
135 |
| - # self.ctx.get_libs_dir(arch.arch)) |
| 79 | + # We manually run cython from the user's system |
| 80 | + # note the --cplus flag, used to build cygrpc.cpp |
| 81 | + shprint( |
| 82 | + sh.find, |
| 83 | + join(build_dir, self.cython_args[0]), |
| 84 | + "-iname", |
| 85 | + "*.pyx", |
| 86 | + "-exec", |
| 87 | + self.ctx.cython, |
| 88 | + "--cplus", |
| 89 | + "{}", |
| 90 | + ";", |
| 91 | + _env=env, |
| 92 | + ) |
136 | 93 |
|
137 |
| - # copy static libs to libs collection |
138 |
| - for lib in sh.glob(join(build_dir, '*.a')): |
139 |
| - shprint(sh.cp, '-L', lib, self.ctx.libs_dir) |
| 94 | + # Now that cython has been run, the build works |
| 95 | + try: |
| 96 | + shprint(hostpython, "setup.py", "build_ext", "-v", _env=env) |
| 97 | + except sh.ErrorReturnCode as e: |
| 98 | + for line in str(e.stdout).split("\\n"): |
| 99 | + print(line) |
| 100 | + raise |
140 | 101 |
|
141 |
| - for lib in sh.glob(join(build_dir, '*.so')): |
142 |
| - shprint(sh.cp, '-L', lib, self.ctx.libs_dir) |
| 102 | + # stripping debug symbols lowers the file size a lot |
| 103 | + build_lib = glob.glob("./python_build/lib*") |
| 104 | + info("{}".format(build_lib)) |
| 105 | + shprint( |
| 106 | + sh.find, |
| 107 | + "./python_build/", |
| 108 | + "-name", |
| 109 | + "*.o", |
| 110 | + "-exec", |
| 111 | + env["STRIP"], |
| 112 | + "{}", |
| 113 | + ";", |
| 114 | + _env=env, |
| 115 | + ) |
143 | 116 |
|
144 | 117 |
|
145 | 118 | recipe = GRPCRecipe()
|
0 commit comments