Skip to content

Commit d22246d

Browse files
authored
Merge pull request #1601 from opacam/fix-compile-to-pyo
[WIP] Restores the ability to compile the python files into .pyo/.pyc (for both versions of python)
2 parents a31f9f1 + 6d8800d commit d22246d

File tree

8 files changed

+151
-34
lines changed

8 files changed

+151
-34
lines changed

pythonforandroid/bootstraps/common/build/build.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,28 @@
2323
import jinja2
2424

2525

26-
def get_bootstrap_name():
26+
def get_dist_info_for(key):
2727
try:
2828
with open(join(dirname(__file__), 'dist_info.json'), 'r') as fileh:
2929
info = json.load(fileh)
30-
bootstrap = str(info["bootstrap"])
30+
value = str(info[key])
3131
except (OSError, KeyError) as e:
32-
print("BUILD FAILURE: Couldn't extract bootstrap name " +
32+
print("BUILD FAILURE: Couldn't extract the key `" + key + "` " +
3333
"from dist_info.json: " + str(e))
3434
sys.exit(1)
35-
return bootstrap
35+
return value
36+
37+
38+
def get_hostpython():
39+
return get_dist_info_for('hostpython')
40+
41+
42+
def get_python_version():
43+
return get_dist_info_for('python_version')
44+
45+
46+
def get_bootstrap_name():
47+
return get_dist_info_for('bootstrap')
3648

3749

3850
if os.name == 'nt':
@@ -44,9 +56,9 @@ def get_bootstrap_name():
4456

4557
curdir = dirname(__file__)
4658

47-
# Try to find a host version of Python that matches our ARM version.
48-
PYTHON = join(curdir, 'python-install', 'bin', 'python.host')
49-
if not exists(PYTHON):
59+
PYTHON = get_hostpython()
60+
PYTHON_VERSION = get_python_version()
61+
if PYTHON is not None and not exists(PYTHON):
5062
PYTHON = None
5163

5264
BLACKLIST_PATTERNS = [
@@ -56,17 +68,18 @@ def get_bootstrap_name():
5668
'^*.bzr/*',
5769
'^*.svn/*',
5870

59-
# pyc/py
60-
'*.pyc',
61-
# '*.py',
62-
6371
# temp files
6472
'~',
6573
'*.bak',
6674
'*.swp',
6775
]
76+
# pyc/py
6877
if PYTHON is not None:
6978
BLACKLIST_PATTERNS.append('*.py')
79+
if PYTHON_VERSION and int(PYTHON_VERSION[0]) == 2:
80+
# we only blacklist `.pyc` for python2 because in python3 the compiled
81+
# extension is `.pyc` (.pyo files not exists for python >= 3.6)
82+
BLACKLIST_PATTERNS.append('*.pyc')
7083

7184
WHITELIST_PATTERNS = []
7285
if get_bootstrap_name() in ('sdl2', 'webview', 'service_only'):
@@ -237,14 +250,15 @@ def compile_dir(dfn, optimize_python=True):
237250
Compile *.py in directory `dfn` to *.pyo
238251
'''
239252

240-
if get_bootstrap_name() != "sdl2":
241-
# HISTORICALLY DISABLED for other than sdl2. NEEDS REVIEW! -JonasT
242-
return
243-
# -OO = strip docstrings
244253
if PYTHON is None:
245254
return
246-
args = [PYTHON, '-m', 'compileall', '-f', dfn]
255+
256+
if int(PYTHON_VERSION[0]) >= 3:
257+
args = [PYTHON, '-m', 'compileall', '-b', '-f', dfn]
258+
else:
259+
args = [PYTHON, '-m', 'compileall', '-f', dfn]
247260
if optimize_python:
261+
# -OO = strip docstrings
248262
args.insert(1, '-OO')
249263
subprocess.call(args)
250264

pythonforandroid/bootstraps/common/build/jni/application/src/start.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ int main(int argc, char *argv[]) {
305305
/* Get the entrypoint, search the .pyo then .py
306306
*/
307307
char *dot = strrchr(env_entrypoint, '.');
308+
#if PY_MAJOR_VERSION > 2
309+
char *ext = ".pyc";
310+
#else
311+
char *ext = ".pyo";
312+
#endif
308313
if (dot <= 0) {
309314
LOGP("Invalid entrypoint, abort.");
310315
return -1;
@@ -313,14 +318,14 @@ int main(int argc, char *argv[]) {
313318
LOGP("Entrypoint path is too long, try increasing ENTRYPOINT_MAXLEN.");
314319
return -1;
315320
}
316-
if (!strcmp(dot, ".pyo")) {
321+
if (!strcmp(dot, ext)) {
317322
if (!file_exists(env_entrypoint)) {
318323
/* fallback on .py */
319324
strcpy(entrypoint, env_entrypoint);
320325
entrypoint[strlen(env_entrypoint) - 1] = '\0';
321326
LOGP(entrypoint);
322327
if (!file_exists(entrypoint)) {
323-
LOGP("Entrypoint not found (.pyo, fallback on .py), abort");
328+
LOGP("Entrypoint not found (.pyc/.pyo, fallback on .py), abort");
324329
return -1;
325330
}
326331
} else {
@@ -330,7 +335,11 @@ int main(int argc, char *argv[]) {
330335
/* if .py is passed, check the pyo version first */
331336
strcpy(entrypoint, env_entrypoint);
332337
entrypoint[strlen(env_entrypoint) + 1] = '\0';
338+
#if PY_MAJOR_VERSION > 2
339+
entrypoint[strlen(env_entrypoint)] = 'c';
340+
#else
333341
entrypoint[strlen(env_entrypoint)] = 'o';
342+
#endif
334343
if (!file_exists(entrypoint)) {
335344
/* fallback on pure python version */
336345
if (!file_exists(env_entrypoint)) {
@@ -340,7 +349,7 @@ int main(int argc, char *argv[]) {
340349
strcpy(entrypoint, env_entrypoint);
341350
}
342351
} else {
343-
LOGP("Entrypoint have an invalid extension (must be .py or .pyo), abort.");
352+
LOGP("Entrypoint have an invalid extension (must be .py or .pyc/.pyo), abort.");
344353
return -1;
345354
}
346355
// LOGP("Entrypoint is:");

pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ protected void onPostExecute(String result) {
150150
File path = new File(getIntent().getData().getSchemeSpecificPart());
151151

152152
Project p = Project.scanDirectory(path);
153-
SDLActivity.nativeSetEnv("ANDROID_ENTRYPOINT", p.dir + "/main.py");
153+
String entry_point = getEntryPoint(p.dir);
154+
SDLActivity.nativeSetEnv("ANDROID_ENTRYPOINT", p.dir + "/" + entry_point);
154155
SDLActivity.nativeSetEnv("ANDROID_ARGUMENT", p.dir);
155156
SDLActivity.nativeSetEnv("ANDROID_APP_PATH", p.dir);
156157

@@ -171,7 +172,8 @@ protected void onPostExecute(String result) {
171172
// pass
172173
}
173174
} else {
174-
SDLActivity.nativeSetEnv("ANDROID_ENTRYPOINT", "main.pyo");
175+
String entry_point = getEntryPoint(app_root_dir);
176+
SDLActivity.nativeSetEnv("ANDROID_ENTRYPOINT", entry_point);
175177
SDLActivity.nativeSetEnv("ANDROID_ARGUMENT", app_root_dir);
176178
SDLActivity.nativeSetEnv("ANDROID_APP_PATH", app_root_dir);
177179
}
@@ -368,9 +370,10 @@ public static void start_service(String serviceTitle, String serviceDescription,
368370
String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath();
369371
String filesDirectory = argument;
370372
String app_root_dir = PythonActivity.mActivity.getAppRoot();
373+
String entry_point = PythonActivity.mActivity.getEntryPoint(app_root_dir + "/service");
371374
serviceIntent.putExtra("androidPrivate", argument);
372375
serviceIntent.putExtra("androidArgument", app_root_dir);
373-
serviceIntent.putExtra("serviceEntrypoint", "service/main.pyo");
376+
serviceIntent.putExtra("serviceEntrypoint", "service/" + entry_point);
374377
serviceIntent.putExtra("pythonName", "python");
375378
serviceIntent.putExtra("pythonHome", app_root_dir);
376379
serviceIntent.putExtra("pythonPath", app_root_dir + ":" + app_root_dir + "/lib");
@@ -463,6 +466,21 @@ public void run() {
463466
});
464467
}
465468

469+
public String getEntryPoint(String search_dir) {
470+
/* Get the main file (.pyc|.pyo|.py) depending on if we
471+
* have a compiled version or not.
472+
*/
473+
List<String> entryPoints = new ArrayList<String>();
474+
entryPoints.add("main.pyo"); // python 2 compiled files
475+
entryPoints.add("main.pyc"); // python 3 compiled files
476+
for (String value : entryPoints) {
477+
File mainFile = new File(search_dir + "/" + value);
478+
if (mainFile.exists()) {
479+
return value;
480+
}
481+
}
482+
return "main.py";
483+
}
466484

467485
protected void showLoadingScreen() {
468486
// load the bitmap

pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,22 @@ public String getAppRoot() {
7474
return app_root;
7575
}
7676

77+
public String getEntryPoint(String search_dir) {
78+
/* Get the main file (.pyc|.pyo|.py) depending on if we
79+
* have a compiled version or not.
80+
*/
81+
List<String> entryPoints = new ArrayList<String>();
82+
entryPoints.add("main.pyo"); // python 2 compiled files
83+
entryPoints.add("main.pyc"); // python 3 compiled files
84+
for (String value : entryPoints) {
85+
File mainFile = new File(search_dir + "/" + value);
86+
if (mainFile.exists()) {
87+
return value;
88+
}
89+
}
90+
return "main.py";
91+
}
92+
7793
public static void initialize() {
7894
// The static nature of the singleton and Android quirkiness force us to initialize everything here
7995
// Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
@@ -142,9 +158,10 @@ public void onClick(DialogInterface dialog,int id) {
142158
// Set up the Python environment
143159
String app_root_dir = getAppRoot();
144160
String mFilesDirectory = mActivity.getFilesDir().getAbsolutePath();
161+
String entry_point = getEntryPoint(app_root_dir);
145162

146163
Log.v(TAG, "Setting env vars for start.c and Python to use");
147-
PythonActivity.nativeSetEnv("ANDROID_ENTRYPOINT", "main.pyo");
164+
PythonActivity.nativeSetEnv("ANDROID_ENTRYPOINT", entry_point);
148165
PythonActivity.nativeSetEnv("ANDROID_ARGUMENT", app_root_dir);
149166
PythonActivity.nativeSetEnv("ANDROID_APP_PATH", app_root_dir);
150167
PythonActivity.nativeSetEnv("ANDROID_PRIVATE", mFilesDirectory);
@@ -368,9 +385,10 @@ public static void start_service(String serviceTitle, String serviceDescription,
368385
String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath();
369386
String filesDirectory = argument;
370387
String app_root_dir = PythonActivity.mActivity.getAppRoot();
388+
String entry_point = PythonActivity.mActivity.getEntryPoint(app_root_dir + "/service");
371389
serviceIntent.putExtra("androidPrivate", argument);
372390
serviceIntent.putExtra("androidArgument", app_root_dir);
373-
serviceIntent.putExtra("serviceEntrypoint", "service/main.pyo");
391+
serviceIntent.putExtra("serviceEntrypoint", "service/" + entry_point);
374392
serviceIntent.putExtra("pythonName", "python");
375393
serviceIntent.putExtra("pythonHome", app_root_dir);
376394
serviceIntent.putExtra("pythonPath", app_root_dir + ":" + app_root_dir + "/lib");

pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,22 @@ public String getAppRoot() {
8181
return app_root;
8282
}
8383

84+
public String getEntryPoint(String search_dir) {
85+
/* Get the main file (.pyc|.pyo|.py) depending on if we
86+
* have a compiled version or not.
87+
*/
88+
List<String> entryPoints = new ArrayList<String>();
89+
entryPoints.add("main.pyo"); // python 2 compiled files
90+
entryPoints.add("main.pyc"); // python 3 compiled files
91+
for (String value : entryPoints) {
92+
File mainFile = new File(search_dir + "/" + value);
93+
if (mainFile.exists()) {
94+
return value;
95+
}
96+
}
97+
return "main.py";
98+
}
99+
84100
public static void initialize() {
85101
// The static nature of the singleton and Android quirkyness force us to initialize everything here
86102
// Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
@@ -170,9 +186,10 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
170186
setContentView(mLayout);
171187

172188
String mFilesDirectory = mActivity.getFilesDir().getAbsolutePath();
189+
String entry_point = getEntryPoint(app_root_dir);
173190

174191
Log.v(TAG, "Setting env vars for start.c and Python to use");
175-
PythonActivity.nativeSetEnv("ANDROID_ENTRYPOINT", "main.pyo");
192+
PythonActivity.nativeSetEnv("ANDROID_ENTRYPOINT", entry_point);
176193
PythonActivity.nativeSetEnv("ANDROID_ARGUMENT", app_root_dir);
177194
PythonActivity.nativeSetEnv("ANDROID_APP_PATH", app_root_dir);
178195
PythonActivity.nativeSetEnv("ANDROID_PRIVATE", mFilesDirectory);
@@ -425,9 +442,10 @@ public static void start_service(String serviceTitle, String serviceDescription,
425442
String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath();
426443
String filesDirectory = argument;
427444
String app_root_dir = PythonActivity.mActivity.getAppRoot();
445+
String entry_point = PythonActivity.mActivity.getEntryPoint(app_root_dir + "/service");
428446
serviceIntent.putExtra("androidPrivate", argument);
429447
serviceIntent.putExtra("androidArgument", app_root_dir);
430-
serviceIntent.putExtra("serviceEntrypoint", "service/main.pyo");
448+
serviceIntent.putExtra("serviceEntrypoint", "service/" + entry_point);
431449
serviceIntent.putExtra("pythonName", "python");
432450
serviceIntent.putExtra("pythonHome", app_root_dir);
433451
serviceIntent.putExtra("pythonPath", app_root_dir + ":" + app_root_dir + "/lib");

pythonforandroid/distribution.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ def save_info(self, dirn):
216216
'bootstrap': self.ctx.bootstrap.name,
217217
'archs': [arch.arch for arch in self.ctx.archs],
218218
'ndk_api': self.ctx.ndk_api,
219-
'recipes': self.ctx.recipe_build_order + self.ctx.python_modules},
219+
'recipes': self.ctx.recipe_build_order + self.ctx.python_modules,
220+
'hostpython': self.ctx.hostpython,
221+
'python_version': self.ctx.python_recipe.major_minor_version_string},
220222
fileh)
221223

222224

0 commit comments

Comments
 (0)