Fix path splitting in get_compiler_dirs() with GCC/clang on Windows

It was using ':' as a path separator while GCC uses ';' resulting in bogus
paths being returned. Instead assume that the compiler uses the platform native
separator.

The previous splitting code still worked sometimes because splitting
"C:/foo;C:/bar" resulted in the last part "/bar" being valid if "<DriveOfCWD>:/bar"
existed.

The fix also exposes a clang Windows bug where it uses the wrong separator:
https://reviews.llvm.org/D61121 . Use a regex to fix those first.

This resulted in linker errors when statically linking against a library which
had an external dependency linking against system libs.

Fixes #5386
pull/5403/head
Christoph Reiter 5 years ago committed by Jussi Pakkanen
parent 61750494f5
commit 7ce9e56a4b
  1. 30
      mesonbuild/compilers/clike.py
  2. 8
      run_unittests.py

@ -170,10 +170,22 @@ class CLikeCompiler:
stdo = p.stdo
return stdo
@staticmethod
def _split_fetch_real_dirs(pathstr, sep=':'):
paths = []
for p in pathstr.split(sep):
def _split_fetch_real_dirs(self, pathstr):
# We need to use the path separator used by the compiler for printing
# lists of paths ("gcc --print-search-dirs"). By default
# we assume it uses the platform native separator.
pathsep = os.pathsep
# clang uses ':' instead of ';' on Windows https://reviews.llvm.org/D61121
# so we need to repair things like 'C:\foo:C:\bar'
if pathsep == ';':
pathstr = re.sub(r':([^/\\])', r';\1', pathstr)
# pathlib treats empty paths as '.', so filter those out
paths = [p for p in pathstr.split(pathsep) if p]
result = []
for p in paths:
# GCC returns paths like this:
# /usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/lib
# It would make sense to normalize them to get rid of the .. parts
@ -185,15 +197,15 @@ class CLikeCompiler:
pobj = Path(p)
unresolved = pobj.as_posix()
if pobj.exists():
if unresolved not in paths:
paths.append(unresolved)
if unresolved not in result:
result.append(unresolved)
try:
resolved = Path(p).resolve().as_posix()
if resolved not in paths:
paths.append(resolved)
if resolved not in result:
result.append(resolved)
except FileNotFoundError:
pass
return tuple(paths)
return tuple(result)
def get_compiler_dirs(self, env, name):
'''

@ -1587,6 +1587,14 @@ class AllPlatformTests(BasePlatformTests):
self.assertEqual(value, expected[args][name])
self.wipe()
def test_clike_get_library_dirs(self):
env = get_fake_env()
cc = env.detect_c_compiler(False)
for d in cc.get_library_dirs(env):
self.assertTrue(os.path.exists(d))
self.assertTrue(os.path.isdir(d))
self.assertTrue(os.path.isabs(d))
def test_static_library_overwrite(self):
'''
Tests that static libraries are never appended to, always overwritten.

Loading…
Cancel
Save