aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/compilers/c.py
diff options
context:
space:
mode:
authorBruce Richardson <bruce.richardson@intel.com>2018-09-27 21:09:56 +0000
committerJussi Pakkanen <jpakkane@gmail.com>2018-10-03 01:01:10 +0300
commit386e5b876fa1395ec2699c9895ac93e4eaf680ad (patch)
tree878e09fb9dcad6ab8540f87f4ff8557fee0ff647 /mesonbuild/compilers/c.py
parentc6eaf373f3aeeaf36fea8d71407f7e971c770cd8 (diff)
downloadmeson-386e5b876fa1395ec2699c9895ac93e4eaf680ad.zip
meson-386e5b876fa1395ec2699c9895ac93e4eaf680ad.tar.gz
meson-386e5b876fa1395ec2699c9895ac93e4eaf680ad.tar.bz2
Verify library directories as either 32-bit or 64-bit
In get_library_dirs() we are trusting the compiler to return a correct list of directories to search for libraries, based on whether or not we are compiling 64-bit or 32-bit. Unfortunately, this is often not the case, as 64-bit libraries often are returned when compiling with -m32 on a 64-bit OS. Since system directories do not contain a mix of libraries, the solution here is to check each directory, by picking a .so file in the directory and checking whether its 64-bit or 32-bit. If we can't determine if we want 32-bit or 64-bit, just skip the checks and assume the directory is good.
Diffstat (limited to 'mesonbuild/compilers/c.py')
-rw-r--r--mesonbuild/compilers/c.py51
1 files changed, 47 insertions, 4 deletions
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 72b9f24..73721e4 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -217,7 +217,7 @@ class CCompiler(Compiler):
paths = []
for p in pathstr.split(sep):
p = Path(p)
- if p.exists():
+ if p.exists() and p.resolve().as_posix() not in paths:
paths.append(p.resolve().as_posix())
return tuple(paths)
@@ -232,8 +232,34 @@ class CCompiler(Compiler):
return ()
@functools.lru_cache()
- def get_library_dirs(self, env):
- return self.get_compiler_dirs(env, 'libraries')
+ def get_library_dirs(self, env, elf_class = None):
+ dirs = self.get_compiler_dirs(env, 'libraries')
+ if elf_class is None or elf_class == 0:
+ return dirs
+
+ # if we do have an elf class for 32-bit or 64-bit, we want to check that
+ # the directory in question contains libraries of the appropriate class. Since
+ # system directories aren't mixed, we only need to check one file for each
+ # directory and go by that. If we can't check the file for some reason, assume
+ # the compiler knows what it's doing, and accept the directory anyway.
+ retval = []
+ for d in dirs:
+ files = [f for f in os.listdir(d) if f.endswith('.so') and os.path.isfile(os.path.join(d, f))]
+ # if no files, accept directory and move on
+ if len(files) == 0:
+ retval.append(d)
+ continue
+ file_to_check = os.path.join(d, files[0])
+ with open(file_to_check, 'rb') as fd:
+ header = fd.read(5)
+ # if file is not an ELF file, it's weird, but accept dir
+ # if it is elf, and the class matches, accept dir
+ if header[1:4] != b'ELF' or int(header[4]) == elf_class:
+ retval.append(d)
+ # at this point, it's an ELF file which doesn't match the
+ # appropriate elf_class, so skip this one
+ pass
+ return tuple(retval)
@functools.lru_cache()
def get_program_dirs(self, env):
@@ -935,6 +961,13 @@ class CCompiler(Compiler):
return f
return None
+ @functools.lru_cache()
+ def output_is_64bit(self, env):
+ '''
+ returns true if the output produced is 64-bit, false if 32-bit
+ '''
+ return self.sizeof('void *', '', env) == 8
+
def find_library_real(self, libname, env, extra_dirs, code, libtype):
# First try if we can just add the library as -l.
# Gcc + co seem to prefer builtin lib dirs to -L dirs.
@@ -950,8 +983,18 @@ class CCompiler(Compiler):
# Not found or we want to use a specific libtype? Try to find the
# library file itself.
patterns = self.get_library_naming(env, libtype)
+ # try to detect if we are 64-bit or 32-bit. If we can't
+ # detect, we will just skip path validity checks done in
+ # get_library_dirs() call
+ try:
+ if self.output_is_64bit(env):
+ elf_class = 2
+ else:
+ elf_class = 1
+ except:
+ elf_class = 0
# Search in the specified dirs, and then in the system libraries
- for d in itertools.chain(extra_dirs, self.get_library_dirs(env)):
+ for d in itertools.chain(extra_dirs, self.get_library_dirs(env, elf_class)):
for p in patterns:
trial = self._get_trials_from_pattern(p, d, libname)
if not trial: