|
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 |
0 commit comments