mirror of https://github.com/kivy/pyjnius.git
299 lines
8.8 KiB
Python
299 lines
8.8 KiB
Python
'''
|
|
Setup.py for creating a binary distribution.
|
|
'''
|
|
|
|
from __future__ import print_function
|
|
try:
|
|
from setuptools import setup, Extension
|
|
except ImportError:
|
|
from distutils.core import setup, Extension
|
|
try:
|
|
import subprocess32 as subprocess
|
|
except ImportError:
|
|
import subprocess
|
|
import os
|
|
from os import environ
|
|
from os.path import dirname, join, exists, realpath
|
|
import re
|
|
import sys
|
|
from platform import machine
|
|
from setup_sdist import SETUP_KWARGS
|
|
|
|
PY2 = sys.version_info < (3, 0, 0)
|
|
|
|
|
|
def getenv(key):
|
|
'''Get value from environment and decode it.'''
|
|
val = environ.get(key)
|
|
if val is not None:
|
|
if not PY2:
|
|
try:
|
|
return val.decode()
|
|
except AttributeError:
|
|
return val
|
|
return val
|
|
|
|
|
|
FILES = [
|
|
'jni.pxi',
|
|
'jnius_compat.pxi',
|
|
'jnius_conversion.pxi',
|
|
'jnius_export_class.pxi',
|
|
'jnius_export_func.pxi',
|
|
'jnius_jvm_android.pxi',
|
|
'jnius_jvm_desktop.pxi',
|
|
'jnius_jvm_dlopen.pxi',
|
|
'jnius_localref.pxi',
|
|
'jnius.pyx',
|
|
'jnius_utils.pxi',
|
|
]
|
|
|
|
LIBRARIES = []
|
|
LIBRARY_DIRS = []
|
|
LIB_LOCATION = None
|
|
EXTRA_LINK_ARGS = []
|
|
INCLUDE_DIRS = []
|
|
INSTALL_REQUIRES = ['six>=1.7.0']
|
|
SETUP_REQUIRES = []
|
|
|
|
# detect Python for android
|
|
PLATFORM = sys.platform
|
|
NDKPLATFORM = getenv('NDKPLATFORM')
|
|
if NDKPLATFORM is not None and getenv('LIBLINK'):
|
|
PLATFORM = 'android'
|
|
|
|
# detect cython
|
|
try:
|
|
from Cython.Distutils import build_ext
|
|
INSTALL_REQUIRES.append('cython')
|
|
except ImportError:
|
|
# pylint: disable=ungrouped-imports
|
|
try:
|
|
from setuptools.command.build_ext import build_ext
|
|
except ImportError:
|
|
from distutils.command.build_ext import build_ext
|
|
if PLATFORM != 'android':
|
|
SETUP_REQUIRES.append('cython')
|
|
INSTALL_REQUIRES.append('cython')
|
|
else:
|
|
# On Android we expect to see 'c' files lying about.
|
|
# and we go ahead with the 'desktop' file? Odd.
|
|
FILES = [fn[:-3] + 'c' for fn in FILES if fn.endswith('pyx')]
|
|
|
|
|
|
def find_javac(possible_homes):
|
|
'''Find javac in all possible locations.'''
|
|
name = "javac.exe" if sys.platform == "win32" else "javac"
|
|
for home in possible_homes:
|
|
for javac in [join(home, name), join(home, 'bin', name)]:
|
|
if exists(javac):
|
|
if sys.platform == "win32" and not PY2: # Avoid path space execution error
|
|
return '"%s"' % javac
|
|
return javac
|
|
return name # Fall back to "hope it's on the path"
|
|
|
|
|
|
def compile_native_invocation_handler(*possible_homes):
|
|
'''Find javac and compile NativeInvocationHandler.java.'''
|
|
javac = find_javac(possible_homes)
|
|
source_level = '1.7'
|
|
try:
|
|
subprocess.check_call([
|
|
javac, '-target', source_level, '-source', source_level,
|
|
join('jnius', 'src', 'org', 'jnius', 'NativeInvocationHandler.java')
|
|
])
|
|
except FileNotFoundError:
|
|
subprocess.check_call([
|
|
javac.replace('"', ''), '-target', source_level, '-source', source_level,
|
|
join('jnius', 'src', 'org', 'jnius', 'NativeInvocationHandler.java')
|
|
])
|
|
|
|
if PLATFORM == 'android':
|
|
# for android, we use SDL...
|
|
LIBRARIES = ['sdl', 'log']
|
|
LIBRARY_DIRS = ['libs/' + getenv('ARCH')]
|
|
|
|
elif PLATFORM == 'darwin':
|
|
|
|
FRAMEWORK = subprocess.Popen(
|
|
'/usr/libexec/java_home',
|
|
stdout=subprocess.PIPE, shell=True).communicate()[0]
|
|
|
|
if not PY2:
|
|
FRAMEWORK = FRAMEWORK.decode('utf-8')
|
|
|
|
FRAMEWORK = FRAMEWORK.strip()
|
|
|
|
if not FRAMEWORK:
|
|
raise Exception('You must install Java on your Mac OS X distro')
|
|
|
|
if '1.6' in FRAMEWORK:
|
|
LIB_LOCATION = '../Libraries/libjvm.dylib'
|
|
INCLUDE_DIRS = [join(
|
|
FRAMEWORK, (
|
|
'System/Library/Frameworks/'
|
|
'JavaVM.framework/Versions/Current/Headers'
|
|
)
|
|
)]
|
|
else:
|
|
LIB_LOCATION = 'jre/lib/jli/libjli.dylib'
|
|
|
|
# We want to favor Java installation declaring JAVA_HOME
|
|
if getenv('JAVA_HOME'):
|
|
FRAMEWORK = getenv('JAVA_HOME')
|
|
|
|
FULL_LIB_LOCATION = join(FRAMEWORK, LIB_LOCATION)
|
|
|
|
if not exists(FULL_LIB_LOCATION):
|
|
# In that case, the Java version is very likely >=9.
|
|
# So we need to modify the `libjvm.so` path.
|
|
LIB_LOCATION = 'lib/jli/libjli.dylib'
|
|
FULL_LIB_LOCATION = join(FRAMEWORK, LIB_LOCATION)
|
|
|
|
if not exists(FULL_LIB_LOCATION):
|
|
# adoptopenjdk12 doesn't have the jli subfolder either
|
|
LIB_LOCATION = 'lib/libjli.dylib'
|
|
FULL_LIB_LOCATION = join(FRAMEWORK, LIB_LOCATION)
|
|
|
|
INCLUDE_DIRS = [
|
|
'{0}/include'.format(FRAMEWORK),
|
|
'{0}/include/darwin'.format(FRAMEWORK)
|
|
]
|
|
|
|
print('JAVA_HOME: {0}\n'.format(FRAMEWORK))
|
|
|
|
compile_native_invocation_handler(FRAMEWORK)
|
|
|
|
else:
|
|
# Note: if on Windows, set ONLY JAVA_HOME
|
|
# not on android or osx, we need to search the JDK_HOME
|
|
|
|
JDK_HOME = getenv('JDK_HOME')
|
|
if not JDK_HOME:
|
|
|
|
if PLATFORM == 'win32':
|
|
TMP_JDK_HOME = getenv('JAVA_HOME')
|
|
print(TMP_JDK_HOME)
|
|
if not TMP_JDK_HOME:
|
|
raise Exception('Unable to find JAVA_HOME')
|
|
|
|
# Remove /bin if it's appended to JAVA_HOME
|
|
if TMP_JDK_HOME[-3:] == 'bin':
|
|
TMP_JDK_HOME = TMP_JDK_HOME[:-4]
|
|
|
|
# Check whether it's JDK
|
|
if exists(join(TMP_JDK_HOME, 'bin', 'javac.exe')):
|
|
JDK_HOME = TMP_JDK_HOME
|
|
|
|
else:
|
|
JDK_HOME = realpath(
|
|
subprocess.check_output(
|
|
['which', 'javac']
|
|
).decode('utf-8').strip()
|
|
).replace('bin/javac', '')
|
|
|
|
if not JDK_HOME or not exists(JDK_HOME):
|
|
raise Exception('Unable to determine JDK_HOME')
|
|
|
|
JRE_HOME = None
|
|
if exists(join(JDK_HOME, 'jre')):
|
|
JRE_HOME = join(JDK_HOME, 'jre')
|
|
|
|
if PLATFORM != 'win32' and not JRE_HOME:
|
|
JRE_HOME = realpath(
|
|
subprocess.check_output(
|
|
['which', 'java']
|
|
).decode('utf-8').strip()
|
|
).replace('bin/java', '')
|
|
|
|
# This dictionary converts values from platform.machine()
|
|
# to a "cpu" string. It is needed to set the correct lib path,
|
|
# found in the JRE_HOME, e.g.: <JRE_HOME>/lib/<cpu>/.
|
|
MACHINE2CPU = {
|
|
"i686": "i386",
|
|
"x86_64": "amd64",
|
|
"armv7l": "arm",
|
|
"sun4u": "sparcv9",
|
|
"sun4v": "sparcv9"
|
|
}
|
|
if machine() in MACHINE2CPU.keys():
|
|
CPU = MACHINE2CPU[machine()]
|
|
else:
|
|
print(
|
|
"WARNING: Not able to assign machine()"
|
|
" = %s to a cpu value!" % machine()
|
|
)
|
|
print(" Using cpu = 'i386' instead!")
|
|
CPU = 'i386'
|
|
|
|
if PLATFORM == 'win32':
|
|
INCL_DIR = join(JDK_HOME, 'include', 'win32')
|
|
LIBRARIES = ['jvm']
|
|
elif PLATFORM == 'sunos5':
|
|
INCL_DIR = join(JDK_HOME, 'include', 'solaris')
|
|
LIB_LOCATION = 'jre/lib/{}/server/libjvm.so'.format(CPU)
|
|
else:
|
|
INCL_DIR = join(JDK_HOME, 'include', 'linux')
|
|
LIB_LOCATION = 'jre/lib/{}/server/libjvm.so'.format(CPU)
|
|
|
|
if isinstance(JRE_HOME, bytes):
|
|
JAVA_HOME = dirname(JRE_HOME.decode())
|
|
else:
|
|
JAVA_HOME = dirname(JRE_HOME)
|
|
FULL_LIB_LOCATION = join(JAVA_HOME, LIB_LOCATION)
|
|
|
|
if not exists(FULL_LIB_LOCATION):
|
|
# In that case, the Java version is very likely >=9.
|
|
# So we need to modify the `libjvm.so` path.
|
|
LIB_LOCATION = 'lib/server/libjvm.so'
|
|
|
|
INCLUDE_DIRS = [
|
|
join(JDK_HOME, 'include'),
|
|
INCL_DIR
|
|
]
|
|
|
|
if PLATFORM == 'win32':
|
|
|
|
if isinstance(JRE_HOME, bytes):
|
|
JRE_HOME = JRE_HOME.decode('utf-8')
|
|
|
|
LIBRARY_DIRS = [
|
|
join(JDK_HOME, 'lib'),
|
|
join(JDK_HOME, 'bin', 'server')
|
|
]
|
|
|
|
print('JDK_HOME: {0}\n'.format(JDK_HOME))
|
|
print('JRE_HOME: {0}\n'.format(JRE_HOME))
|
|
|
|
compile_native_invocation_handler(JDK_HOME, JRE_HOME)
|
|
|
|
# generate the config.pxi
|
|
with open(join(dirname(__file__), 'jnius', 'config.pxi'), 'w') as fd:
|
|
fd.write('DEF JNIUS_PLATFORM = {0!r}\n\n'.format(PLATFORM))
|
|
if not PY2:
|
|
fd.write('DEF JNIUS_PYTHON3 = True\n\n')
|
|
else:
|
|
fd.write('DEF JNIUS_PYTHON3 = False\n\n')
|
|
if LIB_LOCATION is not None:
|
|
fd.write('DEF JNIUS_LIB_SUFFIX = {0!r}\n\n'.format(LIB_LOCATION))
|
|
|
|
# pop setup.py from included files in the installed package
|
|
SETUP_KWARGS['py_modules'].remove('setup')
|
|
|
|
# create the extension
|
|
setup(
|
|
cmdclass={'build_ext': build_ext},
|
|
install_requires=INSTALL_REQUIRES,
|
|
setup_requires=SETUP_REQUIRES,
|
|
ext_modules=[
|
|
Extension(
|
|
'jnius', [join('jnius', x) for x in FILES],
|
|
libraries=LIBRARIES,
|
|
library_dirs=LIBRARY_DIRS,
|
|
include_dirs=INCLUDE_DIRS,
|
|
extra_link_args=EXTRA_LINK_ARGS
|
|
)
|
|
],
|
|
**SETUP_KWARGS
|
|
)
|