20
20
import json
21
21
import glob
22
22
import shutil
23
- import fnmatch
24
23
import re
24
+ import imp
25
+ import contextlib
26
+ import logging
25
27
from functools import wraps
26
28
from datetime import datetime
27
29
from distutils .spawn import find_executable
31
33
from urllib import FancyURLopener
32
34
33
35
import argparse
34
-
35
36
from appdirs import user_data_dir
37
+ import sh
38
+ from colorama import Style , Fore
36
39
37
40
curdir = dirname (__file__ )
38
41
sys .path .insert (0 , join (curdir , "tools" , "external" ))
39
42
40
- import sh
41
- import logging
42
- import contextlib
43
- import imp
44
-
45
- from colorama import Style , Fore
46
43
47
44
DEFAULT_ANDROID_API = 14
48
45
49
46
50
47
logger = logging .getLogger ('p4a' )
51
- # logger.setLevel(logging.DEBUG)
52
48
if not hasattr (logger , 'touched' ): # Necessary as importlib reloads
53
49
# this, which would add a second
54
50
# handler and reset the level
59
55
Style .BRIGHT , Style .RESET_ALL ))
60
56
ch .setFormatter (formatter )
61
57
logger .addHandler (ch )
62
- # logger.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
63
58
info = logger .info
64
59
debug = logger .debug
65
60
warning = logger .warning
66
61
67
62
68
63
IS_PY3 = sys .version_info [0 ] >= 3
69
64
70
- info (Style .BRIGHT + Fore .RED + 'This python-for-android revamp is an experimental alpha release!' + Style .RESET_ALL )
71
- info (Fore .RED + 'It should work (mostly), but you may experience missing features or bugs.' + Style .RESET_ALL )
72
- info (Fore .RED + 'See http://inclem.net/files/p4a_revamp_doc/index.html for the current (WIP) documentation.' + Style .RESET_ALL )
65
+ info ('' .join ([Style .BRIGHT , Fore .RED ,
66
+ 'This python-for-android revamp is an experimental alpha release!' ,
67
+ Style .RESET_ALL ]))
68
+ info ('' .join ([Fore .RED ,
69
+ ('It should work (mostly), but you may experience '
70
+ 'missing features or bugs.' ),
71
+ Style .RESET_ALL ]))
72
+ info ('' .join ([Fore .RED ,
73
+ ('See http://inclem.net/files/p4a_revamp_doc/index.html '
74
+ 'for the current (WIP) documentation.' ),
75
+ Style .RESET_ALL ]))
73
76
74
77
75
78
def info_main (* args ):
76
79
logger .info ('' .join ([Style .BRIGHT , Fore .GREEN ] + list (args ) +
77
80
[Style .RESET_ALL , Fore .RESET ]))
78
81
79
82
def shprint (command , * args , ** kwargs ):
83
+ '''Runs the command (which should be an sh.Command instance), while
84
+ logging the output.'''
80
85
kwargs ["_iter" ] = True
81
86
kwargs ["_out_bufsize" ] = 1
82
87
kwargs ["_err_to_out" ] = True
83
88
if len (logger .handlers ) > 1 :
84
89
logger .removeHandler (logger .handlers [1 ])
85
90
command_path = str (command ).split ('/' )
86
91
command_string = command_path [- 1 ]
87
- # if len(command_path) > 1:
88
- # command_string = '.../' + command_string
89
92
string = ' ' .join (['running' , command_string ] + list (args ))
90
93
91
94
# If logging is not in DEBUG mode, trim the command if necessary
@@ -96,7 +99,7 @@ def shprint(command, *args, **kwargs):
96
99
logger .info (short_string + Style .RESET_ALL )
97
100
else :
98
101
logger .debug (string + Style .RESET_ALL )
99
-
102
+
100
103
output = command (* args , ** kwargs )
101
104
need_closing_newline = False
102
105
for line in output :
@@ -144,6 +147,8 @@ def wrapper_func(self, args):
144
147
145
148
146
149
def get_directory (filename ):
150
+ '''If the filename ends with a recognised file extension, return the
151
+ filename without this extension.'''
147
152
if filename .endswith ('.tar.gz' ):
148
153
return basename (filename [:- 7 ])
149
154
elif filename .endswith ('.tgz' ):
@@ -158,6 +163,7 @@ def get_directory(filename):
158
163
exit (1 )
159
164
160
165
def which (program , path_env ):
166
+ '''Locate an executable in the system.'''
161
167
import os
162
168
def is_exe (fpath ):
163
169
return os .path .isfile (fpath ) and os .access (fpath , os .X_OK )
@@ -432,25 +438,22 @@ def find_order(self):
432
438
class Context (object ):
433
439
'''A build context. If anything will be built, an instance this class
434
440
will be instantiated and used to hold all the build state.'''
435
-
441
+
436
442
env = environ .copy ()
437
443
root_dir = None # the filepath of toolchain.py
438
444
storage_dir = None # the root dir where builds and dists will be stored
439
445
build_dir = None # in which bootstraps are copied for building and recipes are built
440
446
dist_dir = None # the Android project folder where everything ends up
441
- libs_dir = None
447
+ libs_dir = None # where Android libs are cached after build but
448
+ # before being placed in dists
442
449
javaclass_dir = None
443
450
ccache = None # whether to use ccache
444
451
cython = None # the cython interpreter name
445
452
446
- sdk_dir = None # the directory of the android sdk
447
- ndk_dir = None # the directory of the android ndk
448
453
ndk_platform = None # the ndk platform directory
449
- ndk_ver = None # the ndk version, defaults to r9
450
- android_api = None # the android api target, defaults to 14
451
-
452
- dist_name = None
453
- bootstrap = None
454
+
455
+ dist_name = None # should be deprecated in favour of self.dist.dist_name
456
+ bootstrap = None
454
457
bootstrap_build_dir = None
455
458
456
459
recipe_build_order = None # Will hold the list of all built recipes
@@ -485,6 +488,7 @@ def setup_dirs(self):
485
488
486
489
@property
487
490
def android_api (self ):
491
+ '''The Android API being targeted.'''
488
492
if self ._android_api is None :
489
493
raise ValueError ('Tried to access android_api but it has not '
490
494
'been set - this should not happen, something '
@@ -497,6 +501,7 @@ def android_api(self, value):
497
501
498
502
@property
499
503
def ndk_ver (self ):
504
+ '''The version of the NDK being used for compilation.'''
500
505
if self ._ndk_ver is None :
501
506
raise ValueError ('Tried to access android_api but it has not '
502
507
'been set - this should not happen, something '
@@ -509,6 +514,7 @@ def ndk_ver(self, value):
509
514
510
515
@property
511
516
def sdk_dir (self ):
517
+ '''The path to the Android SDK.'''
512
518
if self ._sdk_dir is None :
513
519
raise ValueError ('Tried to access android_api but it has not '
514
520
'been set - this should not happen, something '
@@ -521,6 +527,7 @@ def sdk_dir(self, value):
521
527
522
528
@property
523
529
def ndk_dir (self ):
530
+ '''The path to the Android NDK.'''
524
531
if self ._ndk_dir is None :
525
532
raise ValueError ('Tried to access android_api but it has not '
526
533
'been set - this should not happen, something '
@@ -537,11 +544,14 @@ def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
537
544
for the Android SDK etc.
538
545
539
546
..warning:: This *must* be called before trying any build stuff
547
+
540
548
'''
541
549
542
550
if self ._build_env_prepared :
543
551
return
544
552
553
+ # AND: This needs revamping to carefully check each dependency
554
+ # in turn
545
555
ok = True
546
556
547
557
# Work out where the Android SDK is
@@ -579,12 +589,14 @@ def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
579
589
apis = [s for s in targets if re .match (r'^ *API level: ' , s )]
580
590
apis = [re .findall (r'[0-9]+' , s ) for s in apis ]
581
591
apis = [int (s [0 ]) for s in apis if s ]
582
- info ('Available Android APIs are ({})' .format (', ' .join (map (str , apis ))))
592
+ info ('Available Android APIs are ({})' .format (
593
+ ', ' .join (map (str , apis ))))
583
594
if android_api in apis :
584
- info ('Requested API target {} is available, continuing.' .format (android_api ))
595
+ info (('Requested API target {} is available, '
596
+ 'continuing.' ).format (android_api ))
585
597
else :
586
- warning ('Requested API target {} is not available, install '
587
- 'it with the SDK android tool.' .format (android_api ))
598
+ warning (( 'Requested API target {} is not available, install '
599
+ 'it with the SDK android tool.' ) .format (android_api ))
588
600
warning ('Exiting.' )
589
601
exit (1 )
590
602
# AND: If the android api target doesn't exist, we should
@@ -636,7 +648,8 @@ def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
636
648
else :
637
649
if ndk_ver is None :
638
650
ndk_ver = reported_ndk_ver
639
- info ('Got Android NDK version from the NDK dir: it is {}' .format (ndk_ver ))
651
+ info (('Got Android NDK version from the NDK dir: '
652
+ 'it is {}' ).format (ndk_ver ))
640
653
else :
641
654
if ndk_ver != reported_ndk_ver :
642
655
warning ('NDK version was set as {}, but checking '
@@ -677,7 +690,8 @@ def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
677
690
# path to some tools
678
691
self .ccache = sh .which ("ccache" )
679
692
if not self .ccache :
680
- info ("ccache is missing, the build will not be optimized in the future." )
693
+ info ('ccache is missing, the build will not be optimized in the '
694
+ 'future.' )
681
695
for cython_fn in ("cython2" , "cython-2.7" , "cython" ):
682
696
cython = sh .which (cython_fn )
683
697
if cython :
0 commit comments