TODO: build: fix issue with standard libpaths introduced by cups-config and friends
authorMichael Adam <obnox@samba.org>
Wed, 11 Jun 2014 13:49:33 +0000 (15:49 +0200)
committerMichael Adam <obnox@samba.org>
Mon, 22 Dec 2014 08:51:45 +0000 (09:51 +0100)
Problem:

Some tools like cups-config and python-config list system standard library
paths with -L in the ldflags.

Since these flags are in treated as flags required by libraries
and not as standard flags, this can lead to situations where
configure correctly detects a version of a library (e.g. talloc)
as installed into a special location, but the link process fails
because the unsupported old version of the library is found first
in the library path reported by foo-config.

See e.g.:

BUG: https://bugzilla.samba.org/show_bug.cgi?id=10515

Solution:

The solution of this patch is to filter out the standard
library paths. The difficulty here is that the list of standard
paths varies between the systems. This patch calls "${CC} -print-search-dirs"
to get this list, which is supported at least by gcc and clang.

TODOS:
- is_standard_libpath() : correct place in ccroot.py ??
- can/should we do it in wafsamba only?

buildtools/wafadmin/Tools/ccroot.py
buildtools/wafadmin/Tools/config_c.py
buildtools/wafadmin/Tools/python.py
buildtools/wafsamba/wscript

index 264bdc7f0f6350db145fcdcba22aff27a94b306a..e68961bf4e2f2cd3db42db950be166831455be90 100644 (file)
@@ -20,6 +20,12 @@ import config_c # <- necessary for the configuration, do not touch
 
 USE_TOP_LEVEL = False
 
+def is_standard_libpath(env, path):
+       for _path in env.STANDARD_LIBPATH:
+               if _path == os.path.normpath(path):
+                       return True
+       return False
+
 def get_cc_version(conf, cc, gcc=False, icc=False):
 
        cmd = cc + ['-dM', '-E', '-']
@@ -467,10 +473,14 @@ def apply_obj_vars(self):
                v.append_value('LINKFLAGS', v['FULLSTATIC_MARKER'])
 
        for i in v['RPATH']:
+               if is_standard_libpath(v, i):
+                       continue
                if i and rpath_st:
                        app('LINKFLAGS', rpath_st % i)
 
        for i in v['LIBPATH']:
+               if is_standard_libpath(v, i):
+                       continue
                app('LINKFLAGS', libpath_st % i)
                app('LINKFLAGS', staticlibpath_st % i)
 
index d0bc61773625576cec1d0b1eec2635086d04c2e7..dedcfa841d24b28f81eb2cc2f7830184ce25a431 100644 (file)
@@ -11,6 +11,7 @@ from Utils import md5
 import Build, Utils, Configure, Task, Options, Logs, TaskGen
 from Constants import *
 from Configure import conf, conftest
+import ccroot
 
 cfg_ver = {
        'atleast-version': '>=',
@@ -60,7 +61,8 @@ def parse_flags(line, uselib, env):
                        app('LIB_' + uselib, ot)
                elif st == '-L':
                        if not ot: ot = lst.pop(0)
-                       app('LIBPATH_' + uselib, ot)
+                       if not ccroot.is_standard_libpath(env, ot):
+                               app('LIBPATH_' + uselib, ot)
                elif x == '-pthread' or x.startswith('+'):
                        app('CCFLAGS_' + uselib, x)
                        app('CXXFLAGS_' + uselib, x)
@@ -83,9 +85,11 @@ def parse_flags(line, uselib, env):
                # in too old versions of our internal libs.
                #
                elif x.startswith('-Wl,-R'):
-                       app('RPATH_' + uselib, x[6:])
+                       if not ccroot.is_standard_libpath(env,x[6:]):
+                               app('RPATH_' + uselib, x[6:])
                elif x.startswith('-Wl,-rpath,'):
-                       app('RPATH_' + uselib, x[11:])
+                       if not ccroot.is_standard_libpath(env, x[11:]):
+                               app('RPATH_' + uselib, x[11:])
                elif x.startswith('-Wl'):
                        app('LINKFLAGS_' + uselib, x)
                elif x.startswith('-m') or x.startswith('-f'):
index 35c61c24664ecac5522b937c33c75e3d14038660..d5ee841dbed6b5d10b1df9b1cc6d4276c74ca2bf 100644 (file)
@@ -11,6 +11,7 @@ from Logs import debug, warn, info
 from TaskGen import extension, before, after, feature
 from Configure import conf
 from config_c import parse_flags
+import ccroot
 
 EXT_PY = ['.py']
 FRAG_2 = '''
@@ -249,7 +250,8 @@ MACOSX_DEPLOYMENT_TARGET = %r
                result = conf.check(lib=name, uselib='PYEMBED', libpath=path)
 
        if result:
-               env['LIBPATH_PYEMBED'] = path
+               if not ccroot.is_standard_libpath(env, path[0]):
+                       env['LIBPATH_PYEMBED'] = path
                env.append_value('LIB_PYEMBED', name)
        else:
                conf.log.write("\n\n### LIB NOT FOUND\n")
index 1a30d2fa9366ab00b09182de6aa9884f245ff6e6..cd71be56e6ec0a1cf3e50563cbf17aedc470626b 100755 (executable)
@@ -192,6 +192,33 @@ def set_options(opt):
                    help='tag release in git at the same time',
                    type='string', action='store', dest='TAG_RELEASE')
 
+#
+# Determine the standard libpath for the used compiler,
+# so we can later use that to filter out these standard
+# library paths when some tools like cups-config or
+# python-config report standard lib paths with their
+# ldflags (-L...)
+#
+def get_cc_std_libpath(cc):
+    # at least gcc and clang support this:
+    try:
+        cmd = cc + ['-print-search-dirs']
+        out = Utils.cmd_output(cmd).split('\n')
+    except ValueError:
+        # option not supported by compiler - use a standard list of directories
+        dirlist = [ '/usr/lib', '/usr/lib64' ]
+    except:
+        raise Utils.WafError('Unexpected error running "%s"' % (cmd,))
+    else:
+        dirlist = []
+        for line in out:
+            line = line.strip()
+            if line.startswith("libraries: ="):
+                dirliststr = line[len("libraries: ="):]
+                dirlist = [ os.path.normpath(x) for x in dirliststr.split(':') ]
+                break
+
+    return dirlist
 
 @wafsamba.runonce
 def configure(conf):
@@ -211,6 +238,8 @@ def configure(conf):
 
     conf.check_tool('compiler_cc')
 
+    conf.env.STANDARD_LIBPATH = get_cc_std_libpath(conf.env.CC)
+
     # we need git for 'waf dist'
     conf.find_program('git', var='GIT')