Repository: ycm-core/ycmd

Issue:
build.py links to the wrong dynamic python library during installation
I recently forked this repository for my personal use and had to make an adjustment to the installation process. The final, working adjustment is [here](https://github.com/jmenashe/ycmd/commit/b15ffd00484402b6379d7e731b940ee9300515ad). A note made by @micbou on the [previous commit](https://github.com/jmenashe/ycmd/commit/c8be763ddc0e4a960ce68e96c0d06149041b9451) requested that I provide some details on the problem and my machine configuration.

My OS is Ubuntu 14.04 64-bit. I don't recall the exact python version that was found by the `build.py` script but essentially it found a debug version of the dynamic library `libpython2.7.so`. Since I use the release version of Python 2.7 as my interpreter, I needed the script to instead use the release version of `libpython2.7.so`. Linking against the wrong version would cause the YCM server to crash immediately upon launching vim without providing any logging output, as would be expected with a link error. The modification I made in [this commit](https://github.com/jmenashe/ycmd/commit/b15ffd00484402b6379d7e731b940ee9300515ad) enabled the build script to find the release version of the dynamic library in what I consider to be a reasonably robust manner.

I hope this information is helpful but let me know if I can provide more details. Thank you for putting together this wonderful library!



Discussion:
Thanks for reporting the issue. I tried the script on one of my machine with Ubuntu 14.04 LTS 64-bit installed and it found this Python library:

```
/usr/lib/x86_64-linux-gnu/libpython2.7.so
```

which is not the debug version of the Python library (at least on my machine).

I am rather surprised that it found the debug version on your machine because its name should be `libpython2.7_d.so` (with the `_d` suffix) and the script only search for `libpython2.7.so`.

Could you try the script without your change and give us the Python library path it found? This would be really helpful.

The file it linked to is `/usr/lib/debug/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0`. This is from the `python2.7-dbg` package. Removing that package fixes the problem for me.


Resolving patch:
diff --git a/build.py b/build.py
--- a/build.py
+++ b/build.py
@@ -150,12 +150,19 @@ def CheckOutput( *popen_args, **kwargs ):
   return output
 
 
+def GetPossiblePythonLibraryDirectories():
+  library_dir = p.dirname( sysconfig.get_python_lib( standard_lib = True ) )
+  if OnWindows():
+    return [ p.join( library_dir, 'libs' ) ]
+  # On pyenv, there is no Python dynamic library in the directory returned by
+  # the LIBPL variable. Such library is located in the parent folder of the
+  # standard Python library modules.
+  return [ sysconfig.get_config_var( 'LIBPL' ), library_dir ]
+
+
 def FindPythonLibraries():
   include_dir = sysconfig.get_python_inc()
-  # get_python_lib with the standard_lib parameter set to True returns the
-  # standard Python modules directory. Python libraries should always be in
-  # the parent directory or one of its subdirectories.
-  library_dir = p.dirname( sysconfig.get_python_lib( standard_lib = True ) )
+  library_dirs = GetPossiblePythonLibraryDirectories()
 
   # Since ycmd is compiled as a dynamic library, we can't link it to a Python
   # static library. If we try, the following error will occur on Mac:
@@ -183,17 +190,15 @@ def FindPythonLibraries():
     major = PY_MAJOR, minor = PY_MINOR ), re.X )
   static_libraries = []
 
-  # We search the Python libraries through the library directory and its
-  # subdirectories.
-  for root, dirs, files in os.walk( library_dir ):
+  for library_dir in library_dirs:
     # Files are sorted so that we found the non-versioned Python library before
     # the versioned one.
-    for filename in sorted( files ):
+    for filename in sorted( os.listdir( library_dir ) ):
       if dynamic_name.match( filename ):
-        return p.join( root, filename ), include_dir
+        return p.join( library_dir, filename ), include_dir
 
       if static_name.match( filename ):
-        static_libraries.append( p.join( root, filename ) )
+        static_libraries.append( p.join( library_dir, filename ) )
 
   if static_libraries and not OnWindows():
     dynamic_flag = ( '--enable-framework' if OnMac() else


Test patch: