Opened 6 years ago
Closed 6 years ago
#2087 closed defect (fixed)
Problem with distutils-generated loader flags
| Reported by: | Owned by: | Conrad Huang | |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | Tool Shed | Version: | |
| Keywords: | Cc: | ||
| Blocked By: | Blocking: | ||
| Notify when closed: | Platform: | all | |
| Project: | ChimeraX |
Description
The following bug report has been submitted:
Platform: Linux-3.10.0-957.12.2.el7.x86_64-x86_64-with-centos-7.6.1810-Core
ChimeraX Version: 0.9 (2019-06-06)
Description
This is perhaps more of a DistUtils bug than a ChimeraX one, but I run into it afresh whenever I try to install into ChimeraX any package that requires compiling and linking. If you look in ChimeraX/lib/python3.7/distutils/unixccompiler.py, at line 212 you'll find the following method:
{{{
def runtime_library_dir_option(self, dir):
# XXX Hackish, at the very least. See Python bug #445902:
# http://sourceforge.net/tracker/index.php
# ?func=detail&aid=445902&group_id=5470&atid=105470
# Linkers on different platforms need different options to
# specify that directories need to be added to the list of
# directories searched for dependencies when a dynamic library
# is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to
# be told to pass the -R option through to the linker, whereas
# other compilers and gcc on other systems just know this.
# Other compilers may need something slightly different. At
# this time, there's no way to determine this information from
# the configuration data stored in the Python installation, so
# we use this hack.
compiler = os.path.basename(sysconfig.get_config_var("CC"))
if sys.platform[:6] == "darwin":
# MacOSX's linker doesn't understand the -R flag at all
return "-L" + dir
elif sys.platform[:7] == "freebsd":
return "-Wl,-rpath=" + dir
elif sys.platform[:5] == "hp-ux":
if self._is_gcc(compiler):
return ["-Wl,+s", "-L" + dir]
return ["+s", "-L" + dir]
else:
if self._is_gcc(compiler):
# gcc on non-GNU systems does not need -Wl, but can
# use it anyway. Since distutils has always passed in
# -Wl whenever gcc was used in the past it is probably
# safest to keep doing so.
if sysconfig.get_config_var("GNULD") == "yes":
# GNU ld needs an extra option to get a RUNPATH
# instead of just an RPATH.
return "-Wl,--enable-new-dtags,-R" + dir
else:
return "-Wl,-R" + dir
else:
# No idea how --enable-new-dtags would be passed on to
# ld if this system was using GNU ld. Don't know if a
# system like this even exists.
return "-R" + dir
}}}
The problem here is that if I run `sysconfig.get_config_var('CC')` from within ChimeraX, I get:
'gcc -pipe -fPIC -std=gnu99 -fdebug-prefix-map=/tmp/chx-v0.9.pFsGzN/build=. -fstack-protector-strong -I/tmp/chx-v0.9.pFsGzN/build/include -L/tmp/chx-v0.9.pFsGzN/build/lib -DUSE_DYLD_GLOBAL_NAMESPACE -pthread'
... which the call to os.path.basename makes a mess of parsing, so the compiler variable ends up with the value:
'lib -DUSE_DYLD_GLOBAL_NAMESPACE -pthread'
... causing the method to default to the final "No idea how..." option and return "-R" + dir, which in turn causes GCC to crash at the linking stage.
At the moment I just work around it by replacing that branch with the correct return string for my system (-Wl,--enable-new-dtags,-R).
Same bug is discussed at https://github.com/ContinuumIO/anaconda-issues/issues/6340. Seems if you can strip the -fdebug-prefix-map, -I and -L arguments out (which shouldn't be a problem - looks like these are only relevant to your original build) then it should be fine - it's only the arguments with a "/" in them that confuse basename().
Log:
UCSF ChimeraX version: 0.9 (2019-06-06)
© 2016-2019 Regents of the University of California. All rights reserved.
How to cite UCSF ChimeraX
> toolshed show Shell
/opt/UCSF/ChimeraX/lib/python3.7/site-packages/IPython/core/history.py:226:
UserWarning: IPython History requires SQLite, your history will not be saved
warn("IPython History requires SQLite, your history will not be saved")
OpenGL version: 3.3.0 NVIDIA 415.27
OpenGL renderer: TITAN Xp/PCIe/SSE2
OpenGL vendor: NVIDIA Corporation
Change History (13)
comment:1 by , 6 years ago
| Component: | Unassigned → Tool Shed |
|---|---|
| Owner: | set to |
| Platform: | → all |
| Project: | → ChimeraX |
| Status: | new → assigned |
| Summary: | ChimeraX bug report submission → Problem with distutils-generated loader flags |
comment:2 by , 6 years ago
| Status: | assigned → feedback |
|---|
follow-up: 3 comment:3 by , 6 years ago
I'm planning on waiting another week or so before catching up to the daily builds. Partly in case there's some disaster in the ISOLDE release requiring an urgent patch (fingers crossed!), partly because I have a few other things I need to focus on for a while. Will make sure to test this once I'm caught up. On 2019-06-20 03:02, ChimeraX wrote:
comment:4 by , 6 years ago
In case it might help, here's the one-chunk hack I added to src/apps/ChimeraX:
diff --git a/src/apps/ChimeraX/ChimeraX_main.py b/src/apps/ChimeraX/ChimeraX_main.py
index 4b48f745c..ed9788dd8 100644
--- a/src/apps/ChimeraX/ChimeraX_main.py
+++ b/src/apps/ChimeraX/ChimeraX_main.py
@@ -471,6 +471,23 @@ def init(argv, event_loop=True):
from distutils import sysconfig
site.USER_SITE = sysconfig.get_python_lib()
+ # Hack Linux CC to remove compiler arguments inserted for building
+ # Python. These args contain '/', which confuses
+ # sysconfig.get_config_var() when used by bundle_builder
+ if sys.platform.startswith("linux"):
+ def _clean(cc):
+ parts = cc.split()
+ def ignore(arg):
+ return (arg.startswith("-fdebug-prefix-map") or
+ arg.startswith("-I") or
+ arg.startswith("-L"))
+ keep = [arg for arg in parts if not ignore(arg)]
+ return ' '.join(keep)
+ import sysconfig
+ cvars = sysconfig.get_config_vars()
+ cvars["CC"] = _clean(cvars["CC"])
+ del cvars
+
# Find the location of "share" directory so that we can inform
# the C++ layer. Assume it's a sibling of the directory that
# the executable is in.
comment:5 by , 6 years ago
TODO: The "right" way to solve this is to run a Python script after Python is built (on Linux and Mac) to strip the flags from CC in lib/python*/config*/Makefile. Then no hack would be required at run time. And the additional script is appropriate since it is only associated with the build environment for Python.
comment:6 by , 6 years ago
Should be fixed in 73e6661. Waiting for a successful daily build before closing ticket.
comment:7 by , 6 years ago
Still not working, I'm afraid. From within the Jupyter shell, sysconfig reports the right result:
import sysconfig
sysconfig.get_config_var('CC')
'gcc -pipe -fPIC -std=gnu99 -fstack-protector-strong -DUSE_DYLD_GLOBAL_NAMESPACE -pthread'
... but somehow distutils still sees the problematic flags. If I hack distutils.unixccompiler.UnixCCompiler.runtime_library_dir_option() to report the result of sysconfig.get_config_var('CC'):
from distutils.unixccompiler import UnixCCompiler
ucc = UnixCCompiler()
ucc.runtime_library_dir_option('test')
gcc -pipe -fPIC -std=gnu99 -fdebug-prefix-map=/tmp/chx-develop.3kdcy2/build=. -fstack-protector-strong -I/tmp/chx-develop.3kdcy2/build/include -L/tmp/chx-develop.3kdcy2/build/lib -DUSE_DYLD_GLOBAL_NAMESPACE -pthread
'-Rtest'
comment:8 by , 6 years ago
This should be fixed by cleaning the Makefile when the app is built. Unfortunately, the daily build failed due to my other change, so it's not ready for testing yet. Hopefully tomorrow.
comment:9 by , 6 years ago
comment:10 by , 6 years ago
Still broken. Doing a bit of digging, the sysconfig variables for distutils are set in distutils.sysconfig._init_posix(), which (in the CentOS build of ChimeraX) loads them from /opt/UCSF/ChimeraX-daily/lib/python3.7/_sysconfigdata_m_linux_x86_64-linux-gnu.py. Next question would be to work out what writes that file (or you could simply strip the problem parts from there).
comment:11 by , 6 years ago
Confirmed that editing out directory arguments from 'CC' and 'CONFIG_ARGS' (not sure if the latter is required) in /opt/UCSF/ChimeraX-daily/lib/python3.7/_sysconfigdata_m_linux_x86_64-linux-gnu.py leads to successful compilation.
comment:12 by , 6 years ago
The previous fix cleaned up Makefile but not the generated module. eed5c3b should do that. The rebuilt Python sysconfig returns a CC without the offending flags. Hopefully, this is the right fix.
comment:13 by , 6 years ago
| Resolution: | → fixed |
|---|---|
| Status: | feedback → closed |
I've added a hack (5cc957203) to remove -fdebug-map-prefix, -I and -L from CC on Linux. Can you give that a try? Does the same need to be done for MacOS? I know it is not needed for Windows.