@@ -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 ) ==> " 
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 ) ==> " 
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 ) ==> " 
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())"` 
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" 
121-                         println ("     " 
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