Skip to content

Commit f6d4ee2

Browse files
committed
Add bootstrap backend for Android Library project
1 parent 982469a commit f6d4ee2

27 files changed

+1993
-12
lines changed

pythonforandroid/bootstraps/common/build/build.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ def compile_dir(dfn, optimize_python=True):
274274
def make_package(args):
275275
# If no launcher is specified, require a main.py/main.pyo:
276276
if (get_bootstrap_name() != "sdl" or args.launcher is None) and \
277-
get_bootstrap_name() != "webview":
277+
get_bootstrap_name() not in ["webview", "library"]:
278278
# (webview doesn't need an entrypoint, apparently)
279279
if args.private is None or (
280280
not exists(join(realpath(args.private), 'main.py')) and
@@ -509,8 +509,9 @@ def make_package(args):
509509
aars=aars,
510510
jars=jars,
511511
android_api=android_api,
512-
build_tools_version=build_tools_version
513-
)
512+
build_tools_version=build_tools_version,
513+
is_library=get_bootstrap_name() == 'library',
514+
)
514515

515516
# ant build templates
516517
render(

pythonforandroid/bootstraps/common/build/templates/build.tmpl.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ allprojects {
1919
}
2020
}
2121

22+
{% if is_library %}
23+
apply plugin: 'com.android.library'
24+
{% else %}
2225
apply plugin: 'com.android.application'
26+
{% endif %}
2327

2428
android {
2529
compileSdkVersion {{ android_api }}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import sh
2+
from os.path import join
3+
from pythonforandroid.toolchain import (
4+
current_directory, info, info_main, shprint)
5+
from pythonforandroid.util import ensure_dir
6+
from pythonforandroid.bootstraps.service_only import ServiceOnlyBootstrap
7+
8+
9+
class LibraryBootstrap(ServiceOnlyBootstrap):
10+
11+
name = 'library'
12+
13+
14+
bootstrap = LibraryBootstrap()
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# prevent user to include invalid extensions
2+
*.apk
3+
*.pxd
4+
5+
# eggs
6+
*.egg-info
7+
8+
# unit test
9+
unittest/*
10+
11+
# python config
12+
config/makesetup
13+
14+
# unused kivy files (platform specific)
15+
kivy/input/providers/wm_*
16+
kivy/input/providers/mactouch*
17+
kivy/input/providers/probesysfs*
18+
kivy/input/providers/mtdev*
19+
kivy/input/providers/hidinput*
20+
kivy/core/camera/camera_videocapture*
21+
kivy/core/spelling/*osx*
22+
kivy/core/video/video_pyglet*
23+
kivy/tools
24+
kivy/tests/*
25+
kivy/*/*.h
26+
kivy/*/*.pxi
27+
28+
# unused encodings
29+
lib-dynload/*codec*
30+
encodings/cp*.pyo
31+
encodings/tis*
32+
encodings/shift*
33+
encodings/bz2*
34+
encodings/iso*
35+
encodings/undefined*
36+
encodings/johab*
37+
encodings/p*
38+
encodings/m*
39+
encodings/euc*
40+
encodings/k*
41+
encodings/unicode_internal*
42+
encodings/quo*
43+
encodings/gb*
44+
encodings/big5*
45+
encodings/hp*
46+
encodings/hz*
47+
48+
# unused python modules
49+
bsddb/*
50+
wsgiref/*
51+
hotshot/*
52+
pydoc_data/*
53+
tty.pyo
54+
anydbm.pyo
55+
nturl2path.pyo
56+
LICENCE.txt
57+
macurl2path.pyo
58+
dummy_threading.pyo
59+
audiodev.pyo
60+
antigravity.pyo
61+
dumbdbm.pyo
62+
sndhdr.pyo
63+
__phello__.foo.pyo
64+
sunaudio.pyo
65+
os2emxpath.pyo
66+
multiprocessing/dummy*
67+
68+
# unused binaries python modules
69+
lib-dynload/termios.so
70+
lib-dynload/_lsprof.so
71+
lib-dynload/*audioop.so
72+
lib-dynload/_hotshot.so
73+
lib-dynload/_heapq.so
74+
lib-dynload/_json.so
75+
lib-dynload/grp.so
76+
lib-dynload/resource.so
77+
lib-dynload/pyexpat.so
78+
lib-dynload/_ctypes_test.so
79+
lib-dynload/_testcapi.so
80+
81+
# odd files
82+
plat-linux3/regen
83+
84+
#>sqlite3
85+
# conditionnal include depending if some recipes are included or not.
86+
sqlite3/*
87+
lib-dynload/_sqlite3.so
88+
#<sqlite3
89+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include $(call all-subdir-makefiles)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
# Uncomment this if you're using STL in your project
3+
# See CPLUSPLUS-SUPPORT.html in the NDK documentation for more information
4+
# APP_STL := stlport_static
5+
6+
# APP_ABI := armeabi armeabi-v7a x86
7+
APP_ABI := $(ARCH)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
LOCAL_PATH := $(call my-dir)
2+
3+
include $(CLEAR_VARS)
4+
5+
LOCAL_MODULE := main
6+
7+
# Add your application source files here...
8+
LOCAL_SRC_FILES := start.c pyjniusjni.c
9+
10+
LOCAL_CFLAGS += -I$(PYTHON_INCLUDE_ROOT) $(EXTRA_CFLAGS)
11+
12+
LOCAL_SHARED_LIBRARIES := python_shared
13+
14+
LOCAL_LDLIBS := -llog $(EXTRA_LDLIBS)
15+
16+
LOCAL_LDFLAGS += -L$(PYTHON_LINK_ROOT) $(APPLICATION_ADDITIONAL_LDFLAGS)
17+
18+
include $(BUILD_SHARED_LIBRARY)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
LOCAL_PATH := $(call my-dir)
2+
3+
include $(CLEAR_VARS)
4+
5+
LOCAL_MODULE := main
6+
7+
LOCAL_SRC_FILES := YourSourceHere.c
8+
9+
include $(BUILD_SHARED_LIBRARY)
10+
$(call import-module,SDL)LOCAL_PATH := $(call my-dir)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
#define BOOTSTRAP_NAME_LIBRARY
3+
#define BOOTSTRAP_USES_NO_SDL_HEADERS
4+
5+
const char bootstrap_name[] = "library";
6+
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
2+
#include <pthread.h>
3+
#include <jni.h>
4+
5+
#define LOGI(...) do {} while (0)
6+
#define LOGE(...) do {} while (0)
7+
8+
#include "android/log.h"
9+
10+
/* These JNI management functions are taken from SDL2, but modified to refer to pyjnius */
11+
12+
/* #define LOG(n, x) __android_log_write(ANDROID_LOG_INFO, (n), (x)) */
13+
/* #define LOGP(x) LOG("python", (x)) */
14+
#define LOG_TAG "Python_android"
15+
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
16+
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
17+
18+
19+
/* Function headers */
20+
JNIEnv* Android_JNI_GetEnv(void);
21+
static void Android_JNI_ThreadDestroyed(void*);
22+
23+
static pthread_key_t mThreadKey;
24+
static JavaVM* mJavaVM;
25+
26+
int Android_JNI_SetupThread(void)
27+
{
28+
Android_JNI_GetEnv();
29+
return 1;
30+
}
31+
32+
/* Library init */
33+
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
34+
{
35+
JNIEnv *env;
36+
mJavaVM = vm;
37+
LOGI("JNI_OnLoad called");
38+
if ((*mJavaVM)->GetEnv(mJavaVM, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
39+
LOGE("Failed to get the environment using GetEnv()");
40+
return -1;
41+
}
42+
/*
43+
* Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
44+
* Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
45+
*/
46+
if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed) != 0) {
47+
48+
__android_log_print(ANDROID_LOG_ERROR, "pyjniusjni", "Error initializing pthread key");
49+
}
50+
Android_JNI_SetupThread();
51+
52+
return JNI_VERSION_1_4;
53+
}
54+
55+
JNIEnv* Android_JNI_GetEnv(void)
56+
{
57+
/* From http://developer.android.com/guide/practices/jni.html
58+
* All threads are Linux threads, scheduled by the kernel.
59+
* They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then
60+
* attached to the JavaVM. For example, a thread started with pthread_create can be attached with the
61+
* JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv,
62+
* and cannot make JNI calls.
63+
* Attaching a natively-created thread causes a java.lang.Thread object to be constructed and added to the "main"
64+
* ThreadGroup, making it visible to the debugger. Calling AttachCurrentThread on an already-attached thread
65+
* is a no-op.
66+
* Note: You can call this function any number of times for the same thread, there's no harm in it
67+
*/
68+
69+
JNIEnv *env;
70+
int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env, NULL);
71+
if(status < 0) {
72+
LOGE("failed to attach current thread");
73+
return 0;
74+
}
75+
76+
/* From http://developer.android.com/guide/practices/jni.html
77+
* Threads attached through JNI must call DetachCurrentThread before they exit. If coding this directly is awkward,
78+
* in Android 2.0 (Eclair) and higher you can use pthread_key_create to define a destructor function that will be
79+
* called before the thread exits, and call DetachCurrentThread from there. (Use that key with pthread_setspecific
80+
* to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.)
81+
* Note: The destructor is not called unless the stored value is != NULL
82+
* Note: You can call this function any number of times for the same thread, there's no harm in it
83+
* (except for some lost CPU cycles)
84+
*/
85+
pthread_setspecific(mThreadKey, (void*) env);
86+
87+
return env;
88+
}
89+
90+
static void Android_JNI_ThreadDestroyed(void* value)
91+
{
92+
/* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
93+
JNIEnv *env = (JNIEnv*) value;
94+
if (env != NULL) {
95+
(*mJavaVM)->DetachCurrentThread(mJavaVM);
96+
pthread_setspecific(mThreadKey, NULL);
97+
}
98+
}
99+
100+
void *WebView_AndroidGetJNIEnv()
101+
{
102+
return Android_JNI_GetEnv();
103+
}

pythonforandroid/bootstraps/library/build/src/main/assets/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)