fix cookiecutter project for python3

This commit is contained in:
Mathieu Virbel 2018-11-09 18:48:08 +01:00
parent 7c8a2c6c4b
commit 9ad9abf9b6
5 changed files with 84 additions and 23 deletions

1
.gitignore vendored
View file

@ -18,3 +18,4 @@ src/ios/iosbuild/
src/ios/ios.c
*.DS_Store*
*-ios/
__pycache__

View file

@ -106,10 +106,10 @@
fi
;;
hp*|HP*) DYNLOADFILE="dynload_hpux.o";;
+ # Disable dynamic loading on iOS
+ iOS/*) DYNLOADFILE="dynload_stub.o";;
+ tvOS/*) DYNLOADFILE="dynload_stub.o";;
+ watchOS/*) DYNLOADFILE="dynload_stub.o";;
+ # Dynamic loading on iOS
+ iOS/*) DYNLOADFILE="dynload_shlib.o";;
+ tvOS/*) DYNLOADFILE="dynload_shlib.o";;
+ watchOS/*) DYNLOADFILE="dynload_shlib.o";;
*)
# use dynload_shlib.c and dlopen() if we have it; otherwise stub
# out any dynamic loading

View file

@ -1096,6 +1096,15 @@ def ensure_dir(filename):
makedirs(filename)
def ensure_recipes_loaded(ctx):
for recipe in Recipe.list_recipes():
key = "{}.build_all".format(recipe)
if key not in ctx.state:
continue
recipe = Recipe.get_recipe(recipe, ctx)
recipe.init_with_ctx(ctx)
def update_pbxproj(filename):
# list all the compiled recipes
ctx = Context()
@ -1318,6 +1327,7 @@ Xcode:
from cookiecutter.main import cookiecutter
ctx = Context()
ensure_recipes_loaded(ctx)
template_dir = join(curdir, "tools", "templates")
context = {
"title": args.name,
@ -1327,6 +1337,8 @@ Xcode:
"project_dir": realpath(args.directory),
"version": "1.0.0",
"dist_dir": ctx.dist_dir,
"python_version": ctx.python_ver,
"python_major": ctx.python_major
}
cookiecutter(template_dir, no_input=True, extra_context=context)
filename = join(

View file

@ -5,7 +5,11 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#include "{{ cookiecutter.kivy_dir }}/dist/root/python/include/python2.7/Python.h"
{%- if cookiecutter.python_major == 2 %}
#include "{{ cookiecutter.kivy_dir }}/dist/root/python2/include/python2.7/Python.h"
{%- else %}
#include "{{ cookiecutter.kivy_dir }}/dist/root/python3/include/python3.7m/Python.h"
{%- endif %}
#include "{{ cookiecutter.kivy_dir }}/dist/include/common/sdl2/SDL_main.h"
#include <dlfcn.h>
@ -22,11 +26,12 @@ int main(int argc, char *argv[]) {
// Special environment to prefer .pyo, and don't write bytecode if .py are found
// because the process will not have a write attribute on the device.
putenv("PYTHONOPTIMIZE=2");
putenv("PYTHONDONTWRITEBYTECODE=1");
putenv("PYTHONNOUSERSITE=1");
putenv("PYTHONPATH=.");
putenv("PYTHONUNBUFFERED=1");
// putenv("PYTHONVERBOSE=1");
// putenv("PYOBJUS_DEBUG=1");
// Kivy environment to prefer some implementation on iOS platform
putenv("KIVY_BUILD=ios");
@ -44,12 +49,31 @@ int main(int argc, char *argv[]) {
export_orientation();
NSString * resourcePath = [[NSBundle mainBundle] resourcePath];
#if PY_MAJOR_VERSION == 2
NSLog(@"PythonHome is: %s", (char *)[resourcePath UTF8String]);
Py_SetPythonHome((char *)[resourcePath UTF8String]);
#else
NSString *python_home = [NSString stringWithFormat:@"PYTHONHOME=%@", resourcePath, nil];
putenv((char *)[python_home UTF8String]);
NSString *python_path = [NSString stringWithFormat:@"PYTHONPATH=%@:%@/lib/python3.7/:%@/lib/python3.7/site-packages", resourcePath, resourcePath, resourcePath, nil];
putenv((char *)[python_path UTF8String]);
NSString *tmp_path = [NSString stringWithFormat:@"TMP=%@/tmp", resourcePath, nil];
putenv((char *)[tmp_path UTF8String]);
#endif
NSLog(@"Initializing python");
Py_Initialize();
#if PY_MAJOR_VERSION == 2
PySys_SetArgv(argc, argv);
#else
wchar_t** python_argv = PyMem_RawMalloc(sizeof(wchar_t *) *argc);
for (int i = 0; i < argc; i++)
python_argv[i] = Py_DecodeLocale(argv[i], NULL);
PySys_SetArgv(argc, python_argv);
#endif
// If other modules are using the thread, we need to initialize them before.
PyEval_InitThreads();
@ -58,14 +82,20 @@ int main(int argc, char *argv[]) {
load_custom_builtin_importer();
// Search and start main.py
#if PY_MAJOR_VERSION == 2
#define MAIN_EXT @"pyo"
#else
#define MAIN_EXT @"pyc"
#endif
const char * prog = [
[[NSBundle mainBundle] pathForResource:@"YourApp/main" ofType:@"pyo"] cStringUsingEncoding:
[[NSBundle mainBundle] pathForResource:@"YourApp/main" ofType:MAIN_EXT] cStringUsingEncoding:
NSUTF8StringEncoding];
NSLog(@"Running main.pyo: %s", prog);
NSLog(@"Running main.py: %s", prog);
FILE* fd = fopen(prog, "r");
if ( fd == NULL ) {
ret = 1;
NSLog(@"Unable to open main.pyo, abort.");
NSLog(@"Unable to open main.py, abort.");
} else {
ret = PyRun_SimpleFileEx(fd, prog, 1);
if (ret != 0)
@ -117,9 +147,16 @@ void export_orientation() {
void load_custom_builtin_importer() {
static const char *custom_builtin_importer = \
"import sys, imp\n" \
"import sys, imp, types\n" \
"from os import environ\n" \
"from os.path import exists, join\n" \
"try:\n" \
" # python 3\n"
" import _imp\n" \
" EXTS = _imp.extension_suffixes()\n" \
" sys.modules['subprocess'] = types.ModuleType(name='subprocess')\n" \
"except ImportError:\n" \
" EXTS = ['.so']\n"
"# Fake redirection to supress console output\n" \
"if environ.get('KIVY_NO_CONSOLE', '0') == '1':\n" \
" class fakestd(object):\n" \
@ -130,12 +167,15 @@ void load_custom_builtin_importer() {
"# Custom builtin importer for precompiled modules\n" \
"class CustomBuiltinImporter(object):\n" \
" def find_module(self, fullname, mpath=None):\n" \
" # print(f'find_module() fullname={fullname} mpath={mpath}')\n" \
" if '.' not in fullname:\n" \
" return\n" \
" if not mpath:\n" \
" return\n" \
" part = fullname.rsplit('.')[-1]\n" \
" fn = join(mpath[0], '{}.so'.format(part))\n" \
" for ext in EXTS:\n" \
" fn = join(list(mpath)[0], '{}{}'.format(part, ext))\n" \
" # print('find_module() {}'.format(fn))\n" \
" if exists(fn):\n" \
" return self\n" \
" return\n" \
@ -143,16 +183,16 @@ void load_custom_builtin_importer() {
" f = fullname.replace('.', '_')\n" \
" mod = sys.modules.get(f)\n" \
" if mod is None:\n" \
" # print 'LOAD DYNAMIC', f, sys.modules.keys()\n" \
" # print('LOAD DYNAMIC', f, sys.modules.keys())\n" \
" try:\n" \
" mod = imp.load_dynamic(f, f)\n" \
" except ImportError:\n" \
" # import traceback; traceback.print_exc();\n" \
" # print 'LOAD DYNAMIC FALLBACK', fullname\n" \
" import traceback; traceback.print_exc();\n" \
" # print('LOAD DYNAMIC FALLBACK', fullname)\n" \
" mod = imp.load_dynamic(fullname, fullname)\n" \
" sys.modules[fullname] = mod\n" \
" return mod\n" \
" return mod\n" \
"sys.meta_path.append(CustomBuiltinImporter())";
"sys.meta_path.insert(0, CustomBuiltinImporter())";
PyRun_SimpleString(custom_builtin_importer);
}

View file

@ -33,7 +33,7 @@
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
2CB5F34517D5233A006187AB /* bridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bridge.h; sourceTree = SOURCE_ROOT; };
2CB5F34617D5233A006187AB /* bridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = bridge.m; sourceTree = SOURCE_ROOT; };
59738AB41A8BB5D8001B2C0C /* lib */ = {isa = PBXFileReference; lastKnownFileType = folder; name = lib; path = {{ cookiecutter.dist_dir }}/root/python/lib; sourceTree = "<group>"; };
59738AB41A8BB5D8001B2C0C /* lib */ = {isa = PBXFileReference; lastKnownFileType = folder; name = lib; path = {{ cookiecutter.dist_dir }}/root/python{{ cookiecutter.python_major }}/lib; sourceTree = "<group>"; };
59738AB61A8BB71F001B2C0C /* include */ = {isa = PBXFileReference; lastKnownFileType = folder; name = include; path = {{ cookiecutter.dist_dir }}/hostpython/include; sourceTree = "<group>"; };
59738ABA1A8E19AA001B2C0C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = {{ cookiecutter.project_name }}/Images.xcassets; sourceTree = "<group>"; };
59738AD01A8E62D6001B2C0C /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "LaunchImages/Default-568h@2x.png"; sourceTree = "<group>"; };
@ -234,7 +234,11 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/bash;
shellScript = "{{ cookiecutter.dist_dir }}/hostpython/bin/python -OO -m compileall \"$PROJECT_DIR\"/YourApp";
{%- if cookiecutter.python_major == 2 %}
shellScript = "{{ cookiecutter.dist_dir }}/hostpython2/bin/python -OO -m compileall \"$PROJECT_DIR\"/YourApp";
{%- else %}
shellScript = "{{ cookiecutter.dist_dir }}/hostpython3/bin/python -m compileall -f -b \"$PROJECT_DIR\"/YourApp";
{%- endif %}
};
/* End PBXShellScriptBuildPhase section */
@ -250,7 +254,11 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/bash;
shellScript = "find \"$PROJECT_DIR\"/YourApp/ -iname '*.py' -exec rm {} \\; -or -iname '*.pyc' -exec rm {} \\;";
{%- if cookiecutter.python_major == 2 %}
shellScript = "find \"$PROJECT_DIR\"/YourApp/ -regex '.*\\.py[c]*' -delete";
{%- else %}
shellScript = "find \"$PROJECT_DIR\"/YourApp/ -regex '.*\\.py' -delete";
{%- endif %}
};
/* End PBXShellScriptBuildPhase section */
@ -343,8 +351,8 @@
isa = XCBuildConfiguration;
buildSettings = {
DEAD_CODE_STRIPPING = NO;
ENABLE_BITCODE = NO;
USER_HEADER_SEARCH_PATHS = {{ cookiecutter.dist_dir }}/root/include/;
VALID_ARCHS = x86_64;
};
name = Debug;
};
@ -352,9 +360,9 @@
isa = XCBuildConfiguration;
buildSettings = {
DEAD_CODE_STRIPPING = NO;
ENABLE_BITCODE = NO;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
USER_HEADER_SEARCH_PATHS = {{ cookiecutter.dist_dir }}/root/include/;
VALID_ARCHS = x86_64;
};
name = Release;
};