2929import ctypes
3030import ctypes .util
3131import logging
32+ import subprocess
3233
3334
3435__author__ = "Norman Fomferra, Brockmann Consult GmbH"
@@ -80,7 +81,8 @@ def _add_paths_if_exists(path_list, *paths):
8081 return path_list
8182
8283
83- def _get_module_path (name , fail = False ):
84+ def _get_module_path (name , fail = False , install_path = None ):
85+ """ Find the path to the jpy jni modules. """
8486 import imp
8587
8688 module = imp .find_module (name )
@@ -89,6 +91,10 @@ def _get_module_path(name, fail=False):
8991 path = module [1 ]
9092 if not path and fail :
9193 raise RuntimeError ("module '" + name + "' is missing a file path" )
94+
95+ if install_path :
96+ return os .path .join (install_path , os .path .split (path )[1 ])
97+
9298 return path
9399
94100
@@ -103,10 +109,10 @@ def _find_file(search_dirs, *filenames):
103109 return None
104110
105111
106- def _get_java_api_properties (fail = False ):
112+ def _get_java_api_properties (fail = False , path = None ):
107113 jpy_config = Properties ()
108- jpy_config .set_property ('jpy.jpyLib' , _get_module_path ('jpy' , fail = fail ))
109- jpy_config .set_property ('jpy.jdlLib' , _get_module_path ('jdl' , fail = fail ))
114+ jpy_config .set_property ('jpy.jpyLib' , _get_module_path ('jpy' , fail = fail , install_path = path ))
115+ jpy_config .set_property ('jpy.jdlLib' , _get_module_path ('jdl' , fail = fail , install_path = path ))
110116 jpy_config .set_property ('jpy.pythonLib' , _find_python_dll_file (fail = fail ))
111117 jpy_config .set_property ('jpy.pythonPrefix' , sys .prefix )
112118 jpy_config .set_property ('jpy.pythonExecutable' , sys .executable )
@@ -115,7 +121,8 @@ def _get_java_api_properties(fail=False):
115121
116122def find_jdk_home_dir ():
117123 """
118- Try to detect the JDK home directory from dedicated environment variables.
124+ Try to detect the JDK home directory from Maven, if available, or use
125+ dedicated environment variables.
119126 :return: pathname if found, else None
120127 """
121128 for name in JDK_HOME_VARS :
@@ -124,6 +131,22 @@ def find_jdk_home_dir():
124131 and os .path .exists (os .path .join (jdk_home_dir , 'include' )) \
125132 and os .path .exists (os .path .join (jdk_home_dir , 'lib' )):
126133 return jdk_home_dir
134+ logging .debug ('Checking Maven for JAVA_HOME...' )
135+ try :
136+ output = subprocess .check_output (['mvn' , '-v' ])
137+ if isinstance (output , bytes ) and not isinstance (output , str ):
138+ #PY3 related
139+ output = output .decode ('utf-8' )
140+ for part in output .split ('\n ' ):
141+ if part .startswith ('Java home:' ):
142+ path = part .split (':' )[1 ].strip ()
143+ if path .endswith ('jre' ):
144+ return path [0 :- 3 ]
145+
146+ except Exception :
147+ # maven probably isn't installed or not on PATH
148+ logging .debug ('Maven not found on PATH. No JAVA_HOME found.' )
149+
127150 return None
128151
129152
@@ -480,12 +503,12 @@ def load(self, path):
480503 raise ValueError ('illegal Java properties format ' + line )
481504
482505
483- def _execute_python_scripts (scripts ):
506+ def _execute_python_scripts (scripts , ** kwargs ):
484507 import subprocess
485508
486509 failures = 0
487510 for script in scripts :
488- exit_code = subprocess .call ([sys .executable , script ])
511+ exit_code = subprocess .call ([sys .executable , script ], ** kwargs )
489512 if exit_code :
490513 failures += 1
491514 return failures
@@ -494,6 +517,7 @@ def _execute_python_scripts(scripts):
494517def write_config_files (out_dir = '.' ,
495518 java_home_dir = None ,
496519 jvm_dll_file = None ,
520+ install_dir = None ,
497521 req_java_api_conf = True ,
498522 req_py_api_conf = True ):
499523 """
@@ -502,6 +526,7 @@ def write_config_files(out_dir='.',
502526 :param out_dir: output directory, must exist
503527 :param java_home_dir: optional home directory of the Java JRE or JDK installation
504528 :param jvm_dll_file: optional file to JVM shared library file
529+ :param install_dir: optional path to where to searfh for modules
505530 :param req_java_api_conf: whether to write the jpy configuration file 'jpyconfig.properties' for Java
506531 :param req_py_api_conf: whether to write the jpy configuration file 'jpyconfig.py' for Python
507532 :return: zero on success, otherwise an error code
@@ -543,7 +568,7 @@ def write_config_files(out_dir='.',
543568
544569 try :
545570 java_api_config_file = os .path .join (out_dir , java_api_config_basename )
546- java_api_properties = _get_java_api_properties (fail = req_java_api_conf )
571+ java_api_properties = _get_java_api_properties (fail = req_java_api_conf , path = install_dir )
547572 java_api_properties .store (java_api_config_file , comments = [
548573 "Created by '%s' tool on %s" % (tool_name , str (datetime .datetime .now ())),
549574 "This file is read by the jpy Java API (org.jpy.PyLib class) in order to find shared libraries" ])
@@ -578,6 +603,7 @@ def _main():
578603 help = "Require that Java API configuration succeeds." )
579604 parser .add_argument ("-p" , "--req_py" , action = 'store_true' , default = False ,
580605 help = "Require that Python API configuration succeeds." )
606+ parser .add_argument ("--install_dir" , action = 'store' , default = None , help = "Optional. Used during pip install of JPY" )
581607 args = parser .parse_args ()
582608
583609 log_level = getattr (logging , args .log_level .upper (), None )
@@ -596,7 +622,8 @@ def _main():
596622 java_home_dir = args .java_home ,
597623 jvm_dll_file = args .jvm_dll ,
598624 req_java_api_conf = args .req_java ,
599- req_py_api_conf = args .req_py )
625+ req_py_api_conf = args .req_py ,
626+ install_dir = args .install_dir )
600627 except :
601628 logging .exception ("Configuration failed" )
602629 retcode = 100
0 commit comments