Skip to content

Commit ffc654a

Browse files
authored
Make env.py publically accessible, without starting the JVM (#780)
* make env more public, and accessible before the jvm starts * no mentions of jnius.env anymore * fix import * added jnius.env
1 parent 8f584f3 commit ffc654a

File tree

8 files changed

+396
-385
lines changed

8 files changed

+396
-385
lines changed

jnius/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
__version__ = '1.7.0'
1111

12-
from .env import get_java_setup
12+
from jnius_config.env import get_java_setup
1313

1414
import os
1515
import sys

jnius/env.py

Lines changed: 3 additions & 378 deletions
Original file line numberDiff line numberDiff line change
@@ -1,378 +1,3 @@
1-
'''
2-
This module determine and expose various information about the java
3-
environment.
4-
'''
5-
6-
import sys
7-
from os.path import join, exists, dirname, realpath
8-
from os import getenv
9-
from platform import machine
10-
from subprocess import Popen, check_output, PIPE
11-
from shlex import split
12-
import logging
13-
from textwrap import dedent
14-
from shutil import which
15-
16-
log = logging.getLogger('kivy').getChild(__name__)
17-
18-
machine = machine() # not expected to change at runtime
19-
20-
# This dictionary converts values from platform.machine()
21-
# to a "cpu" string. It is needed to set the correct lib path,
22-
# found in the JRE_HOME, e.g.: <JRE_HOME>/lib/<cpu>/.
23-
MACHINE2CPU = {
24-
"i686": "i386",
25-
"x86_64": "amd64",
26-
"AMD64": "amd64",
27-
"armv7l": "arm",
28-
"aarch64": "aarch64",
29-
"sun4u": "sparcv9",
30-
"sun4v": "sparcv9"
31-
}
32-
33-
DEFAULT_PLATFORM = sys.platform
34-
35-
36-
def is_set(string):
37-
return string is not None and len(string) > 0
38-
39-
40-
def get_java_setup(platform=DEFAULT_PLATFORM):
41-
'''
42-
Returns an instance of JavaLocation.
43-
'''
44-
# prefer Env variables
45-
JAVA_HOME = getenv('JAVA_HOME')
46-
if not is_set(JAVA_HOME):
47-
JAVA_HOME = getenv('JDK_HOME')
48-
if not is_set(JAVA_HOME):
49-
JAVA_HOME = getenv('JRE_HOME')
50-
#TODO encodings
51-
52-
# Use java_home program on Mac
53-
if not is_set(JAVA_HOME) and platform == 'darwin':
54-
JAVA_HOME = get_osx_framework()
55-
if not is_set(JAVA_HOME):
56-
raise Exception('You must install Java for Mac OSX')
57-
58-
# go hunting for Javac and Java programs, in that order
59-
if not is_set(JAVA_HOME):
60-
JAVA_HOME = get_jdk_home(platform)
61-
62-
if not is_set(JAVA_HOME):
63-
JAVA_HOME = get_jre_home(platform)
64-
65-
if JAVA_HOME is None:
66-
raise RuntimeError("Could not find your Java installed. Please set the JAVA_HOME env var.")
67-
68-
if isinstance(JAVA_HOME, bytes):
69-
JAVA_HOME = JAVA_HOME.decode('utf-8')
70-
71-
log.debug("Identified Java at %s" % JAVA_HOME)
72-
73-
# Remove /bin if it's appended to JAVA_HOME
74-
if JAVA_HOME[-3:] == 'bin':
75-
JAVA_HOME = JAVA_HOME[:-4]
76-
77-
if platform == "android":
78-
return AndroidJavaLocation(platform, JAVA_HOME)
79-
if platform == "win32": #only this?
80-
return WindowsJavaLocation(platform, JAVA_HOME)
81-
if platform == "darwin": #only this?
82-
return MacOsXJavaLocation(platform, JAVA_HOME)
83-
if 'bsd' in platform:
84-
return BSDJavaLocation(platform, JAVA_HOME)
85-
if platform in ('linux', 'linux2', 'sunos5'): #only this?
86-
return UnixJavaLocation(platform, JAVA_HOME)
87-
log.warning("warning: unknown platform %s assuming linux or sunOS" % platform)
88-
return UnixJavaLocation(platform, JAVA_HOME)
89-
90-
91-
class JavaLocation:
92-
def __init__(self, platform, home):
93-
self.platform = platform
94-
self.home = home
95-
96-
def get_javahome(self):
97-
'''
98-
Returns the location of the identified JRE or JDK
99-
'''
100-
return self.home
101-
102-
103-
def is_jdk(self):
104-
'''
105-
Returns true if the location is a JDK, based on existing of javac
106-
'''
107-
javac = self.get_javac()
108-
return exists(javac)
109-
110-
def get_javac(self):
111-
'''
112-
Returns absolute path of the javac executable
113-
'''
114-
return join(self.home, "bin", "javac")
115-
116-
def get_include_dirs(self):
117-
'''
118-
Returns a list of absolute paths of JDK include directories, for compiling.
119-
Calls _get_platform_include_dir() internally.
120-
'''
121-
return [
122-
join(self.home, 'include'),
123-
self._get_platform_include_dir()
124-
]
125-
126-
def _get_platform_include_dir(self):
127-
'''
128-
Returns the platform-specific include directory, for setup.py
129-
'''
130-
pass
131-
132-
def get_library_dirs(self):
133-
'''
134-
Returns a list of absolute paths of JDK lib directories, for setup.py
135-
'''
136-
pass
137-
138-
def get_libraries(self):
139-
'''
140-
Returns the names of the libraries for this platform, for setup.py
141-
'''
142-
pass
143-
144-
def get_jnius_lib_location(self):
145-
'''
146-
Returns the full path of the Java library for runtime binding with.
147-
Can be overridden by using JVM_PATH env var to set absolute path of the Java library
148-
'''
149-
libjvm_override_path = getenv('JVM_PATH')
150-
if libjvm_override_path:
151-
log.info(
152-
dedent("""
153-
Using override env var JVM_PATH (%s) to load libjvm.
154-
Please report your system information (os version, java
155-
version, etc), and the path that works for you, to the
156-
PyJNIus project, at https://github.com/kivy/pyjnius/issues.
157-
so we can improve the automatic discovery.
158-
"""
159-
),
160-
libjvm_override_path
161-
)
162-
return libjvm_override_path
163-
164-
platform = self.platform
165-
log.debug("looking for libjvm to initiate pyjnius, platform is %s", platform)
166-
lib_locations = self._possible_lib_locations()
167-
for location in lib_locations:
168-
full_lib_location = join(self.home, location)
169-
if exists(full_lib_location):
170-
log.debug("found libjvm.so at %s", full_lib_location)
171-
return full_lib_location
172-
173-
raise RuntimeError(
174-
"""
175-
Unable to find libjvm.so, (tried %s)
176-
you can use the JVM_PATH env variable with the absolute path
177-
to libjvm.so to override this lookup, if you know
178-
where pyjnius should look for it.
179-
180-
e.g:
181-
export JAVA_HOME=/usr/lib/jvm/java-8-oracle/
182-
export JVM_PATH=/usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so
183-
# run your program
184-
"""
185-
% [join(self.home, loc) for loc in lib_locations]
186-
)
187-
188-
def _possible_lib_locations(self):
189-
'''
190-
Returns a list of relative possible locations for the Java library.
191-
Used by the default implementation of get_jnius_lib_location()
192-
'''
193-
pass
194-
195-
196-
class WindowsJavaLocation(JavaLocation):
197-
def get_javac(self):
198-
return super().get_javac() + ".exe"
199-
200-
def get_libraries(self):
201-
return ['jvm']
202-
203-
def get_library_dirs(self):
204-
suffices = ['lib', join('bin', 'server')]
205-
return [join(self.home, suffix) for suffix in suffices]
206-
207-
def _get_platform_include_dir(self):
208-
return join(self.home, 'include', 'win32')
209-
210-
211-
class UnixJavaLocation(JavaLocation):
212-
def _get_platform_include_dir(self):
213-
if self.platform == 'sunos5':
214-
return join(self.home, 'include', 'solaris')
215-
else:
216-
return join(self.home, 'include', 'linux')
217-
218-
def _possible_lib_locations(self):
219-
root = self.home
220-
if root.endswith('jre'):
221-
root = root[:-3]
222-
223-
cpu = get_cpu()
224-
log.debug(
225-
f"Platform {self.platform} may need cpu in path to find libjvm, which is: {cpu}"
226-
)
227-
228-
return [
229-
'lib/server/libjvm.so',
230-
'jre/lib/{}/default/libjvm.so'.format(cpu),
231-
'jre/lib/{}/server/libjvm.so'.format(cpu),
232-
]
233-
234-
235-
# NOTE: Build works on FreeBSD. Other BSD flavors may need tuning!
236-
class BSDJavaLocation(JavaLocation):
237-
def _get_platform_include_dir(self):
238-
os = self.platform.translate({ord(n): None for n in '0123456789'})
239-
return join(self.home, 'include', os)
240-
241-
def _possible_lib_locations(self):
242-
root = self.home
243-
if root.endswith('jre'):
244-
root = root[:-3]
245-
246-
cpu = get_cpu()
247-
log.debug(
248-
f"Platform {self.platform} may need cpu in path to find libjvm, which is: {cpu}"
249-
)
250-
251-
return [
252-
'lib/server/libjvm.so',
253-
'jre/lib/{}/default/libjvm.so'.format(cpu),
254-
'jre/lib/{}/server/libjvm.so'.format(cpu),
255-
]
256-
257-
258-
class MacOsXJavaLocation(UnixJavaLocation):
259-
def _get_platform_include_dir(self):
260-
return join(self.home, 'include', 'darwin')
261-
262-
def _possible_lib_locations(self):
263-
if '1.6' in self.home:
264-
return ['../Libraries/libjvm.dylib'] # TODO what should this be resolved to?
265-
266-
return [
267-
'jre/lib/jli/libjli.dylib',
268-
# In that case, the Java version >=9.
269-
'lib/jli/libjli.dylib',
270-
# adoptopenjdk12 doesn't have the jli subfolder either
271-
'lib/libjli.dylib',
272-
]
273-
274-
275-
276-
# this is overridden due to the specifalities of version 1.6
277-
def get_include_dirs(self):
278-
framework = self.home
279-
if '1.6' in framework:
280-
return [join(
281-
framework, (
282-
'System/Library/Frameworks/'
283-
'JavaVM.framework/Versions/Current/Headers'
284-
)
285-
)]
286-
return super().get_include_dirs()
287-
288-
289-
class AndroidJavaLocation(UnixJavaLocation):
290-
def get_libraries(self):
291-
return ['SDL2', 'log']
292-
293-
def get_include_dirs(self):
294-
# When cross-compiling for Android, we should not use the include dirs
295-
# exposed by the JDK. Instead, we should use the one exposed by the
296-
# Android NDK (which are already handled via python-for-android).
297-
return []
298-
299-
def get_library_dirs(self):
300-
return []
301-
302-
303-
def get_jre_home(platform):
304-
jre_home = None
305-
if JAVA_HOME and exists(join(JAVA_HOME, 'jre')):
306-
jre_home = join(JAVA_HOME, 'jre')
307-
308-
if platform != 'win32' and not jre_home:
309-
try:
310-
jre_home = realpath(
311-
which('java')
312-
).replace('bin/java', '')
313-
except TypeError:
314-
raise Exception('Unable to find java')
315-
316-
if is_set(jre_home):
317-
return jre_home
318-
319-
# didnt find java command on the path, we can
320-
# fallback to hunting in some default unix locations
321-
for loc in ["/usr/java/latest/", "/usr/java/default/", "/usr/lib/jvm/default-java/"]:
322-
if exists(loc + "bin/java"):
323-
jre_home = loc
324-
break
325-
326-
return jre_home
327-
328-
329-
def get_jdk_home(platform):
330-
jdk_home = getenv('JDK_HOME')
331-
if not jdk_home:
332-
if platform == 'win32':
333-
TMP_JDK_HOME = getenv('JAVA_HOME')
334-
if not TMP_JDK_HOME:
335-
raise Exception('Unable to find JAVA_HOME')
336-
337-
# Remove /bin if it's appended to JAVA_HOME
338-
if TMP_JDK_HOME[-3:] == 'bin':
339-
TMP_JDK_HOME = TMP_JDK_HOME[:-4]
340-
341-
# Check whether it's JDK
342-
if exists(join(TMP_JDK_HOME, 'bin', 'javac.exe')):
343-
jdk_home = TMP_JDK_HOME
344-
345-
else:
346-
try:
347-
jdk_home = realpath(
348-
which('javac')
349-
).replace('bin/javac', '')
350-
except TypeError:
351-
raise Exception('Unable to find javac')
352-
353-
if not jdk_home or not exists(jdk_home):
354-
return None
355-
356-
return jdk_home
357-
358-
359-
def get_osx_framework():
360-
framework = Popen(
361-
'/usr/libexec/java_home',
362-
stdout=PIPE, shell=True
363-
).communicate()[0]
364-
365-
framework = framework.decode('utf-8')
366-
return framework.strip()
367-
368-
369-
def get_cpu():
370-
try:
371-
return MACHINE2CPU[machine]
372-
except KeyError:
373-
print(
374-
"WARNING: Not able to assign machine()"
375-
" = %s to a cpu value!" % machine
376-
)
377-
print(f" Using cpu = '{machine}' instead!")
378-
return machine
1+
from jnius_config.env import get_java_setup, JavaLocation, WindowsJavaLocation, BSDJavaLocation, AndroidJavaLocation
2+
from jnius_config.env import get_jre_home, get_jdk_home
3+
# this file is just a shim - env has been moved to jnius_config.env

jnius/jnius_jvm_desktop.pxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import sys
22
import os
33
from os.path import join
4-
from jnius.env import get_java_setup
4+
from jnius_config.env import get_java_setup
55

66
# on desktop, we need to create an env :)
77
# example taken from http://www.inonit.com/cygwin/jni/invocationApi/c.html

0 commit comments

Comments
 (0)