|
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