@@ -47,91 +47,65 @@ pysys(python::AbstractString, var::AbstractString) = pyvar(python, "sys", var)
4747
4848const dlprefix = Compat. Sys. iswindows () ? " " : " lib"
4949
50- # return libpython name, libpython pointer
51- function find_libpython (python:: AbstractString )
52- # it is ridiculous that it is this hard to find the name of libpython
53- v = pyconfigvar (python," VERSION" ," " )
54- libs = [ dlprefix* " python" * v, dlprefix* " python" ]
55- lib = pyconfigvar (python, " LIBRARY" )
56- lib != " None" && pushfirst! (libs, splitext (lib)[1 ])
57- lib = pyconfigvar (python, " LDLIBRARY" )
58- lib != " None" && pushfirst! (pushfirst! (libs, basename (lib)), lib)
59- libs = unique (libs)
60-
61- # it is ridiculous that it is this hard to find the path of libpython
62- libpaths = [pyconfigvar (python, " LIBDIR" ),
63- (Compat. Sys. iswindows () ? dirname (pysys (python, " executable" )) : joinpath (dirname (dirname (pysys (python, " executable" ))), " lib" ))]
64- if Compat. Sys. isapple ()
65- push! (libpaths, pyconfigvar (python, " PYTHONFRAMEWORKPREFIX" ))
66- end
50+ # print out extra info to help with remote debugging
51+ const PYCALL_DEBUG_BUILD = " yes" == get (ENV , " PYCALL_DEBUG_BUILD" , " no" )
6752
68- # `prefix` and `exec_prefix` are the path prefixes where python should look for python only and compiled libraries, respectively.
69- # These are also changed when run in a virtualenv.
70- exec_prefix = pysys (python, " exec_prefix" )
71-
72- push! (libpaths, exec_prefix)
73- push! (libpaths, joinpath (exec_prefix, " lib" ))
53+ function exec_find_libpython (python:: AbstractString , options)
54+ cmd = ` $python $(joinpath (@__DIR__ , " find_libpython.py" )) $options `
55+ if PYCALL_DEBUG_BUILD
56+ cmd = ` $cmd --verbose`
57+ end
58+ return readlines (pythonenv (cmd))
59+ end
7460
75- error_strings = String[]
61+ function show_dlopen_error (e)
62+ if PYCALL_DEBUG_BUILD
63+ println (stderr , " dlopen($libpath_lib ) ==> " , e)
64+ # Using STDERR since find_libpython.py prints debugging
65+ # messages to STDERR too.
66+ end
67+ end
7668
77- # TODO : other paths? python-config output? pyconfigvar("LDFLAGS")?
69+ # return libpython name, libpython pointer
70+ function find_libpython (python:: AbstractString )
71+ dlopen_flags = Libdl. RTLD_LAZY| Libdl. RTLD_DEEPBIND| Libdl. RTLD_GLOBAL
7872
79- # find libpython (we hope):
80- for lib in libs
81- for libpath in libpaths
82- libpath_lib = joinpath (libpath, lib)
83- if isfile (libpath_lib* " ." * Libdl. dlext)
84- try
85- return (Libdl. dlopen (libpath_lib,
86- Libdl. RTLD_LAZY| Libdl. RTLD_DEEPBIND| Libdl. RTLD_GLOBAL),
87- libpath_lib)
88- catch e
89- push! (error_strings, string (" dlopen($libpath_lib ) ==> " , e))
90- end
91- end
73+ libpaths = exec_find_libpython (python, ` --list-all` )
74+ for lib in libpaths
75+ try
76+ return (Libdl. dlopen (lib, dlopen_flags), lib)
77+ catch e
78+ show_dlopen_error (e)
9279 end
9380 end
9481
82+ # Try all candidate libpython names and let Libdl find the path.
9583 # We do this *last* because the libpython in the system
9684 # library path might be the wrong one if multiple python
9785 # versions are installed (we prefer the one in LIBDIR):
86+ libs = exec_find_libpython (python, ` --candidate-names` )
9887 for lib in libs
9988 lib = splitext (lib)[1 ]
10089 try
101- return (Libdl. dlopen (lib, Libdl. RTLD_LAZY| Libdl. RTLD_DEEPBIND| Libdl. RTLD_GLOBAL),
102- lib)
90+ libpython = Libdl. dlopen (lib, dlopen_flags)
91+ # Store the fullpath to libpython in deps.jl. This makes
92+ # it easier for users to investigate Python setup
93+ # PyCall.jl trying to use. It also helps PyJulia to
94+ # compare libpython.
95+ return (libpython, Libdl. dlpath (libpython))
10396 catch e
104- push! (error_strings, string (" dlopen($lib ) ==> " , e))
105- end
106- end
107-
108- if " yes" == get (ENV , " PYCALL_DEBUG_BUILD" , " no" ) # print out extra info to help with remote debugging
109- println (stderr , " ------------------------------------- exceptions -----------------------------------------" )
110- for s in error_strings
111- print (s, " \n\n " )
112- end
113- println (stderr , " ---------------------------------- get_config_vars ---------------------------------------" )
114- print (stderr , read (` python -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_vars())"` , String))
115- println (stderr , " --------------------------------- directory contents -------------------------------------" )
116- for libpath in libpaths
117- if isdir (libpath)
118- print (libpath, " :\n " )
119- for file in readdir (libpath)
120- if occursin (" pyth" , file)
121- println (" " , file)
122- end
123- end
124- end
97+ show_dlopen_error (e)
12598 end
126- println (stderr , " ------------------------------------------------------------------------------------------" )
12799 end
128100
129101 error ("""
130102 Couldn't find libpython; check your PYTHON environment variable.
131103
132- The python executable we tried was $python (= version $v );
133- the library names we tried were $libs
134- and the library paths we tried were $libpaths """ )
104+ The python executable we tried was $python (= version $v ).
105+ Re-building with
106+ ENV["PYCALL_DEBUG_BUILD"] = "yes"
107+ may provide extra information for why it failed.
108+ """ )
135109end
136110
137111# ########################################################################
0 commit comments