diff options
author | Bruce Richardson <bruce.richardson@intel.com> | 2018-08-19 20:41:50 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2018-08-24 03:39:26 +0530 |
commit | 81b12a6ab90c3dc5d9e8c4dab9f469b671dbfff2 (patch) | |
tree | af77737940c0db0ae99713ba8bdf5d5b90f59ca0 | |
parent | 22cc463c1c618abec8e4612d49e9f74a66fc93f7 (diff) | |
download | meson-81b12a6ab90c3dc5d9e8c4dab9f469b671dbfff2.zip meson-81b12a6ab90c3dc5d9e8c4dab9f469b671dbfff2.tar.gz meson-81b12a6ab90c3dc5d9e8c4dab9f469b671dbfff2.tar.bz2 |
find_library: Use _build_wrapper to get library dirs
This means that we will take into account all the flags set in the
cross file when fetching the list of library dirs, which means we
won't incorrectly look for 64-bit libraries when building for 32-bit.
Signed-off-by: Nirbheek Chauhan <nirbheek@centricular.com>
Closes https://github.com/mesonbuild/meson/issues/3881
-rw-r--r-- | mesonbuild/backend/backends.py | 10 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 2 | ||||
-rw-r--r-- | mesonbuild/compilers/c.py | 84 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 24 | ||||
-rw-r--r-- | mesonbuild/compilers/fortran.py | 11 | ||||
-rw-r--r-- | mesonbuild/dependencies/boost.py | 2 |
6 files changed, 66 insertions, 67 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 0e2389d..87da90d 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -342,9 +342,9 @@ class Backend: return l, stdlib_args @staticmethod - def _libdir_is_system(libdir, compilers): + def _libdir_is_system(libdir, compilers, env): for cc in compilers.values(): - if libdir in cc.get_library_dirs(): + if libdir in cc.get_library_dirs(env): return True return False @@ -359,7 +359,7 @@ class Backend: # The only link argument is an absolute path to a library file. libpath = la[0] libdir = os.path.dirname(libpath) - if exclude_system and self._libdir_is_system(libdir, target.compilers): + if exclude_system and self._libdir_is_system(libdir, target.compilers, self.environment): # No point in adding system paths. continue # Windows doesn't support rpaths, but we use this function to @@ -597,8 +597,8 @@ class Backend: # Get program and library dirs from all target compilers if isinstance(target, build.BuildTarget): for cc in target.compilers.values(): - paths.update(cc.get_program_dirs()) - paths.update(cc.get_library_dirs()) + paths.update(cc.get_program_dirs(self.environment)) + paths.update(cc.get_library_dirs(self.environment)) return list(paths) def determine_windows_extra_paths(self, target, extra_bdeps, is_cross=False): diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index d602bc1..b9473ec 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2526,7 +2526,7 @@ rule FORTRAN_DEP_HACK%s guessed_dependencies = [] # TODO The get_library_naming requirement currently excludes link targets that use d or fortran as their main linker if hasattr(linker, 'get_library_naming'): - search_dirs = list(search_dirs) + linker.get_library_dirs() + search_dirs = list(search_dirs) + linker.get_library_dirs(self.environment) static_patterns = linker.get_library_naming(self.environment, 'static', strict=True) shared_patterns = linker.get_library_naming(self.environment, 'shared', strict=True) for libname in libs: diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 5056b30..0ca09d4 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -16,6 +16,8 @@ import re import glob import os.path import subprocess +import functools +import itertools from pathlib import Path from .. import mlog @@ -51,6 +53,7 @@ gnu_compiler_internal_libs = ('m', 'c', 'pthread', 'dl', 'rt') class CCompiler(Compiler): + # TODO: Replace this manual cache with functools.lru_cache library_dirs_cache = {} program_dirs_cache = {} find_library_cache = {} @@ -172,42 +175,47 @@ class CCompiler(Compiler): def get_std_shared_lib_link_args(self): return ['-shared'] - def get_library_dirs_real(self): - env = os.environ.copy() - env['LC_ALL'] = 'C' - stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[1] + @functools.lru_cache() + def _get_search_dirs(self, env): + extra_args = ['--print-search-dirs'] + stdo = None + with self._build_wrapper('', env, extra_args, None, 'compile', True) as p: + stdo = p.stdo + return stdo + + @staticmethod + def _split_fetch_real_dirs(pathstr, sep=':'): paths = [] - for line in stdo.split('\n'): - if line.startswith('libraries:'): - libstr = line.split('=', 1)[1] - paths = [os.path.realpath(p) for p in libstr.split(':')] + for p in pathstr.split(sep): + p = Path(p) + if p.exists(): + paths.append(p.resolve().as_posix()) return paths - def get_library_dirs(self): - key = tuple(self.exelist) + def get_compiler_dirs(self, env, name): + ''' + Get dirs from the compiler, either `libraries:` or `programs:` + ''' + stdo = self._get_search_dirs(env) + for line in stdo.split('\n'): + if line.startswith(name + ':'): + return CCompiler._split_fetch_real_dirs(line.split('=', 1)[1]) + return [] + + def get_library_dirs(self, env): + key = (tuple(self.exelist), env) if key not in self.library_dirs_cache: - self.library_dirs_cache[key] = self.get_library_dirs_real() + self.library_dirs_cache[key] = self.get_compiler_dirs(env, 'libraries') return self.library_dirs_cache[key][:] - def get_program_dirs_real(self): - env = os.environ.copy() - env['LC_ALL'] = 'C' - stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[1] - paths = [] - for line in stdo.split('\n'): - if line.startswith('programs:'): - libstr = line.split('=', 1)[1] - paths = [os.path.realpath(p) for p in libstr.split(':')] - return paths - - def get_program_dirs(self): + def get_program_dirs(self, env): ''' Programs used by the compiler. Also where toolchain DLLs such as libstdc++-6.dll are found with MinGW. ''' - key = tuple(self.exelist) + key = (tuple(self.exelist), env) if key not in self.program_dirs_cache: - self.program_dirs_cache[key] = self.get_program_dirs_real() + self.program_dirs_cache[key] = self.get_compiler_dirs(env, 'programs') return self.program_dirs_cache[key][:] def get_pic_args(self): @@ -916,35 +924,19 @@ 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) - for d in extra_dirs: + # Search in the specified dirs, and then in the system libraries + for d in itertools.chain(extra_dirs, self.get_library_dirs(env)): for p in patterns: trial = self._get_trials_from_pattern(p, d, libname) if not trial: continue + # We just check whether the library exists. We can't do a link + # check because the library might have unresolved symbols that + # require other libraries. trial = self._get_file_from_list(trial) if not trial: continue return [trial] - # Search in the system libraries too - for d in self.get_library_dirs(): - for p in patterns: - trial = self._get_trials_from_pattern(p, d, libname) - if not trial: - continue - trial = self._get_file_from_list(trial) - if not trial: - continue - # When searching the system paths used by the compiler, we - # need to check linking with link-whole, as static libs - # (.a) need to be checked to ensure they are the right - # architecture, e.g. 32bit or 64-bit. - # Just a normal test link won't work as the .a file doesn't - # seem to be checked by linker if there are no unresolved - # symbols from the main C file. - extra_link_args = self.get_link_whole_for([trial]) - extra_link_args = self.linker_to_compiler_args(extra_link_args) - if self.links(code, env, extra_args=extra_link_args): - return [trial] return None def find_library_impl(self, libname, env, extra_dirs, code, libtype): diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index d6e902d..d7b44f3 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -860,7 +860,7 @@ class Compiler: def find_library(self, *args, **kwargs): raise EnvironmentException('Language {} does not support library finding.'.format(self.get_display_language())) - def get_library_dirs(self): + def get_library_dirs(self, *args, **kwargs): return [] def has_multi_arguments(self, args, env): @@ -947,7 +947,9 @@ class Compiler: mlog.debug('Working directory: ', tmpdirname) mlog.debug('Command line: ', ' '.join(commands), '\n') mlog.debug('Code:\n', code) - p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname) + os_env = os.environ.copy() + os_env['LC_ALL'] = 'C' + p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname, env=os_env) mlog.debug('Compiler stdout:\n', p.stdo) mlog.debug('Compiler stderr:\n', p.stde) p.commands = commands @@ -1291,10 +1293,12 @@ class ElbrusCompiler(GnuCompiler): 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded'] - def get_library_dirs(self): - env = os.environ.copy() - env['LC_ALL'] = 'C' - stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[1] + # FIXME: use _build_wrapper to call this so that linker flags from the env + # get applied + def get_library_dirs(self, env): + os_env = os.environ.copy() + os_env['LC_ALL'] = 'C' + stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1] paths = [] for line in stdo.split('\n'): if line.startswith('libraries:'): @@ -1304,10 +1308,10 @@ class ElbrusCompiler(GnuCompiler): break return paths - def get_program_dirs(self): - env = os.environ.copy() - env['LC_ALL'] = 'C' - stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[1] + def get_program_dirs(self, env): + os_env = os.environ.copy() + os_env['LC_ALL'] = 'C' + stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1] paths = [] for line in stdo.split('\n'): if line.startswith('programs:'): diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index d6e41e3..a7e55e6 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -127,11 +127,14 @@ class FortranCompiler(Compiler): def get_std_shared_lib_link_args(self): return CCompiler.get_std_shared_lib_link_args(self) - def get_library_dirs_real(self): - return CCompiler.get_library_dirs_real(self) + def _get_search_dirs(self, *args, **kwargs): + return CCompiler._get_search_dirs(self, *args, **kwargs) - def get_library_dirs(self): - return CCompiler.get_library_dirs(self) + def get_compiler_dirs(self, *args, **kwargs): + return CCompiler.get_compiler_dirs(self, *args, **kwargs) + + def get_library_dirs(self, *args, **kwargs): + return CCompiler.get_library_dirs(self, *args, **kwargs) def get_pic_args(self): return CCompiler.get_pic_args(self) diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 7acde2d..a54a694 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -453,7 +453,7 @@ class BoostDependency(ExternalDependency): if self.libdir: libdirs = [self.libdir] elif self.boost_root is None: - libdirs = mesonlib.get_library_dirs() + libdirs = mesonlib.get_library_dirs(self.env) else: libdirs = [os.path.join(self.boost_root, 'lib')] for libdir in libdirs: |