12
12
from urllib .request import urlretrieve
13
13
from os import listdir , unlink , environ , curdir , walk
14
14
from sys import stdout
15
+ from multiprocessing import cpu_count
15
16
import time
16
17
try :
17
18
from urlparse import urlparse
@@ -517,7 +518,7 @@ def unpack(self, arch):
517
518
for entry in listdir (extraction_filename ):
518
519
# Previously we filtered out the .git folder, but during the build process for some recipes
519
520
# (e.g. when version is parsed by `setuptools_scm`) that may be needed.
520
- shprint (sh .cp , '-Rv ' ,
521
+ shprint (sh .cp , '-R ' ,
521
522
join (extraction_filename , entry ),
522
523
directory_name )
523
524
else :
@@ -830,6 +831,8 @@ def build_arch(self, arch, *extra_args):
830
831
shprint (
831
832
sh .Command (join (self .ctx .ndk_dir , "ndk-build" )),
832
833
'V=1' ,
834
+ "-j" ,
835
+ str (cpu_count ()),
833
836
'NDK_DEBUG=' + ("1" if self .ctx .build_as_debuggable else "0" ),
834
837
'APP_PLATFORM=android-' + str (self .ctx .ndk_api ),
835
838
'APP_ABI=' + arch .arch ,
@@ -878,6 +881,8 @@ class PythonRecipe(Recipe):
878
881
hostpython_prerequisites = []
879
882
'''List of hostpython packages required to build a recipe'''
880
883
884
+ _host_recipe = None
885
+
881
886
def __init__ (self , * args , ** kwargs ):
882
887
super ().__init__ (* args , ** kwargs )
883
888
if 'python3' not in self .depends :
@@ -890,6 +895,10 @@ def __init__(self, *args, **kwargs):
890
895
depends = list (set (depends ))
891
896
self .depends = depends
892
897
898
+ def prebuild_arch (self , arch ):
899
+ self ._host_recipe = Recipe .get_recipe ("hostpython3" , self .ctx )
900
+ return super ().prebuild_arch (arch )
901
+
893
902
def clean_build (self , arch = None ):
894
903
super ().clean_build (arch = arch )
895
904
name = self .folder_name
@@ -907,8 +916,7 @@ def clean_build(self, arch=None):
907
916
def real_hostpython_location (self ):
908
917
host_name = 'host{}' .format (self .ctx .python_recipe .name )
909
918
if host_name == 'hostpython3' :
910
- python_recipe = Recipe .get_recipe (host_name , self .ctx )
911
- return python_recipe .python_exe
919
+ return self ._host_recipe .python_exe
912
920
else :
913
921
python_recipe = self .ctx .python_recipe
914
922
return 'python{}' .format (python_recipe .version )
@@ -927,14 +935,44 @@ def folder_name(self):
927
935
name = self .name
928
936
return name
929
937
938
+ def patch_shebang (self , _file , original_bin ):
939
+ _file_des = open (_file , "r" )
940
+
941
+ try :
942
+ data = _file_des .readlines ()
943
+ except UnicodeDecodeError :
944
+ return
945
+
946
+ if "#!" in (line := data [0 ]):
947
+ if line .split ("#!" )[- 1 ].strip () == original_bin :
948
+ return
949
+
950
+ info (f"Fixing shebang for '{ _file } '" )
951
+ data .pop (0 )
952
+ data .insert (0 , "#!" + original_bin + "\n " )
953
+ _file_des .close ()
954
+ _file_des = open (_file , "w" )
955
+ _file_des .write ("" .join (data ))
956
+ _file_des .close ()
957
+
958
+ def patch_shebangs (self , path , original_bin ):
959
+ # set correct shebang
960
+ for file in listdir (path ):
961
+ _file = join (path , file )
962
+ self .patch_shebang (_file , original_bin )
963
+
930
964
def get_recipe_env (self , arch = None , with_flags_in_cc = True ):
965
+ if self ._host_recipe is None :
966
+ self ._host_recipe = Recipe .get_recipe ("hostpython3" , self .ctx )
967
+
931
968
env = super ().get_recipe_env (arch , with_flags_in_cc )
932
- env ['PYTHONNOUSERSITE' ] = '1'
933
969
# Set the LANG, this isn't usually important but is a better default
934
970
# as it occasionally matters how Python e.g. reads files
935
971
env ['LANG' ] = "en_GB.UTF-8"
936
972
# Binaries made by packages installed by pip
937
- env ["PATH" ] = join (self .hostpython_site_dir , "bin" ) + ":" + env ["PATH" ]
973
+ env ["PATH" ] = self ._host_recipe .site_bin + ":" + env ["PATH" ]
974
+ host_env = self .get_hostrecipe_env ()
975
+ env ['PYTHONPATH' ] = host_env ["PYTHONPATH" ]
938
976
939
977
if not self .call_hostpython_via_targetpython :
940
978
env ['CFLAGS' ] += ' -I{}' .format (
@@ -945,18 +983,6 @@ def get_recipe_env(self, arch=None, with_flags_in_cc=True):
945
983
self .ctx .python_recipe .link_version ,
946
984
)
947
985
948
- hppath = []
949
- hppath .append (join (dirname (self .hostpython_location ), 'Lib' ))
950
- hppath .append (join (hppath [0 ], 'site-packages' ))
951
- builddir = join (dirname (self .hostpython_location ), 'build' )
952
- if exists (builddir ):
953
- hppath += [join (builddir , d ) for d in listdir (builddir )
954
- if isdir (join (builddir , d ))]
955
- if len (hppath ) > 0 :
956
- if 'PYTHONPATH' in env :
957
- env ['PYTHONPATH' ] = ':' .join (hppath + [env ['PYTHONPATH' ]])
958
- else :
959
- env ['PYTHONPATH' ] = ':' .join (hppath )
960
986
return env
961
987
962
988
def should_build (self , arch ):
@@ -993,25 +1019,36 @@ def install_python_package(self, arch, name=None, env=None, is_dir=True):
993
1019
'--install-lib=.' ,
994
1020
_env = hpenv , * self .setup_extra_args )
995
1021
996
- # If asked, also install in the hostpython build dir
997
- if self .install_in_hostpython :
998
- self .install_hostpython_package (arch )
1022
+ if isfile ("setup.py" ):
1023
+ shprint (hostpython , 'setup.py' , 'install' , '-O2' ,
1024
+ '--root={}' .format (self .ctx .get_python_install_dir (arch .arch )),
1025
+ '--install-lib=.' ,
1026
+ _env = hpenv , * self .setup_extra_args )
1027
+
1028
+ # If asked, also install in the hostpython build dir
1029
+ if self .install_in_hostpython :
1030
+ self .install_hostpython_package (arch )
1031
+ else :
1032
+ warning ("`PythonRecipe.install_python_package` called without `setup.py` file!" )
999
1033
1000
- def get_hostrecipe_env (self , arch ):
1034
+ def get_hostrecipe_env (self ):
1001
1035
env = environ .copy ()
1002
- env ['PYTHONPATH' ] = self .hostpython_site_dir
1036
+ _python_path = self ._host_recipe .get_path_to_python ()
1037
+ env ['PYTHONPATH' ] = self ._host_recipe .site_dir + ":" + join (
1038
+ _python_path , "Modules" ) + ":" + glob .glob (join (_python_path , "build" , "lib*" ))[0 ]
1003
1039
return env
1004
1040
1005
1041
@property
1006
1042
def hostpython_site_dir (self ):
1007
1043
return join (dirname (self .real_hostpython_location ), 'Lib' , 'site-packages' )
1008
1044
1009
1045
def install_hostpython_package (self , arch ):
1010
- env = self .get_hostrecipe_env (arch )
1046
+ env = self .get_hostrecipe_env ()
1011
1047
real_hostpython = sh .Command (self .real_hostpython_location )
1012
1048
shprint (real_hostpython , 'setup.py' , 'install' , '-O2' ,
1013
1049
'--root={}' .format (dirname (self .real_hostpython_location )),
1014
1050
'--install-lib=Lib/site-packages' ,
1051
+ '--root={}' .format (self ._host_recipe .site_root ),
1015
1052
_env = env , * self .setup_extra_args )
1016
1053
1017
1054
@property
@@ -1029,15 +1066,17 @@ def install_hostpython_prerequisites(self, packages=None, force_upgrade=True):
1029
1066
pip_options = [
1030
1067
"install" ,
1031
1068
* packages ,
1032
- "--target" , self .hostpython_site_dir , "--python-version" ,
1069
+ "--target" , self ._host_recipe . site_dir , "--python-version" ,
1033
1070
self .ctx .python_recipe .version ,
1034
1071
# Don't use sources, instead wheels
1035
1072
"--only-binary=:all:" ,
1036
1073
]
1037
1074
if force_upgrade :
1038
1075
pip_options .append ("--upgrade" )
1039
1076
# Use system's pip
1040
- shprint (sh .pip , * pip_options )
1077
+ pip_env = self .get_hostrecipe_env ()
1078
+ pip_env ["HOME" ] = "/tmp"
1079
+ shprint (sh .Command (self .real_hostpython_location ), "-m" , "pip" , * pip_options , _env = pip_env )
1041
1080
1042
1081
def restore_hostpython_prerequisites (self , packages ):
1043
1082
_packages = []
@@ -1076,7 +1115,7 @@ def build_compiled_components(self, arch):
1076
1115
env ['STRIP' ], '{}' , ';' , _env = env )
1077
1116
1078
1117
def install_hostpython_package (self , arch ):
1079
- env = self .get_hostrecipe_env (arch )
1118
+ env = self .get_hostrecipe_env ()
1080
1119
self .rebuild_compiled_components (arch , env )
1081
1120
super ().install_hostpython_package (arch )
1082
1121
@@ -1231,7 +1270,7 @@ def get_recipe_env(self, arch, **kwargs):
1231
1270
return env
1232
1271
1233
1272
def get_wheel_platform_tag (self , arch ):
1234
- return "android_" + {
1273
+ return f "android_{ self . ctx . ndk_api } _ " + {
1235
1274
"armeabi-v7a" : "arm" ,
1236
1275
"arm64-v8a" : "aarch64" ,
1237
1276
"x86_64" : "x86_64" ,
@@ -1268,6 +1307,9 @@ def build_arch(self, arch):
1268
1307
self .install_hostpython_prerequisites (
1269
1308
packages = ["build[virtualenv]" , "pip" ] + self .hostpython_prerequisites
1270
1309
)
1310
+ python_bin_dir = join (self ._host_recipe .site_dir , "bin" )
1311
+ self .patch_shebangs (python_bin_dir , self .real_hostpython_location )
1312
+
1271
1313
build_dir = self .get_build_dir (arch .arch )
1272
1314
env = self .get_recipe_env (arch , with_flags_in_cc = True )
1273
1315
# make build dir separately
0 commit comments