From 390f0b8b522a7c73880349a250400a2802927b66 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 29 Nov 2017 10:23:57 +0530 Subject: dependencies: Convert /c/foo/bar paths to C:/foo/bar MSVC cannot handle MinGW-esque /c/foo paths, convert them to C:/foo. We cannot resolve other paths starting with / like /home/foo so leave them as-is so the user gets an error/warning from the compiler/linker. These paths are commonly found in pkg-config files generated using Autotools inside MinGW/MSYS and MinGW/MSYS2 environments. Currently this is only done for PkgConfigDependency. --- mesonbuild/dependencies/base.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'mesonbuild') diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index a72023275..81b93c46c 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -22,6 +22,7 @@ import shlex import shutil import textwrap from enum import Enum +from pathlib import PurePath from .. import mlog from .. import mesonlib @@ -424,6 +425,20 @@ class PkgConfigDependency(ExternalDependency): self.link_args = [] libpaths = [] for lib in shlex.split(out): + # MSVC cannot handle MinGW-esque /c/foo paths, convert them to C:/foo. + # We cannot resolve other paths starting with / like /home/foo so leave + # them as-is so the user gets an error/warning from the compiler/linker. + if self.compiler.id == 'msvc': + # Library search path + if lib.startswith('-L/'): + pargs = PurePath(lib[2:]).parts + if len(pargs) > 1 and len(pargs[1]) == 1: + lib = '-L{}:/{}'.format(pargs[1], '/'.join(pargs[2:])) + # Full path to library or .la file + elif lib.startswith('/'): + pargs = PurePath(lib).parts + if len(pargs) > 1 and len(pargs[1]) == 1: + lib = '{}:/{}'.format(pargs[1], '/'.join(pargs[2:])) # If we want to use only static libraries, we have to look for the # file ourselves instead of depending on the compiler to find it # with -lfoo or foo.lib. However, we can only do this if we already -- cgit v1.2.3 From 45dbc0d30e2447faeb877469c54a47579e56837c Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 29 Nov 2017 10:44:41 +0530 Subject: find_library: Prefer .dll.a and .lib over .dll for shared We can't know if the .lib is a static or import library, but that's a problem in general too. The only way to figure out if a specific file is an import or a static library is to dump its symbols and check if it starts with __imp or not. Even then, some libs are hybrid import and static, i.e., they contain references to DLLs for some symbols and also provide implementations for other symbols so this is a difficult problem. Closes https://github.com/mesonbuild/meson/issues/2659 --- mesonbuild/compilers/c.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'mesonbuild') diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 317a4d738..2d123142e 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -727,10 +727,12 @@ class CCompiler(Compiler): if for_darwin(env.is_cross_build(), env): shlibext = ['dylib'] elif for_windows(env.is_cross_build(), env): + # FIXME: .lib files can be import or static so we should read the + # file, figure out which one it is, and reject the wrong kind. if self.id == 'msvc': shlibext = ['lib'] else: - shlibext = ['dll', 'dll.a', 'lib'] + shlibext = ['dll.a', 'lib', 'dll'] # Yep, static libraries can also be foo.lib stlibext += ['lib'] elif for_cygwin(env.is_cross_build(), env): -- cgit v1.2.3 From 133df3b045c8b70b2750fac5961dc85cea2e19b2 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Thu, 30 Nov 2017 12:40:20 +0530 Subject: dependencies: Pass language to PkgConfigDependency Also try harder to find a compiler that dependencies can use. This means that in C++-only projects we will use the C++ compiler for compiler checks, which can be important. --- mesonbuild/dependencies/base.py | 24 +++++++++++++++++------- mesonbuild/dependencies/misc.py | 2 +- mesonbuild/dependencies/ui.py | 6 ++++-- 3 files changed, 22 insertions(+), 10 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 81b93c46c..7249b0165 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -157,9 +157,6 @@ class ExternalDependency(Dependency): self.name = type_name # default self.is_found = False self.language = language - if language and language not in self.env.coredata.compilers: - m = self.name.capitalize() + ' requires a {} compiler' - raise DependencyException(m.format(language.capitalize())) self.version_reqs = kwargs.get('version', None) self.required = kwargs.get('required', True) self.silent = kwargs.get('silent', False) @@ -177,7 +174,20 @@ class ExternalDependency(Dependency): compilers = self.env.coredata.cross_compilers else: compilers = self.env.coredata.compilers - self.compiler = compilers.get(self.language or 'c', None) + # Set the compiler for this dependency if a language is specified, + # else try to pick something that looks usable. + if self.language: + if self.language not in compilers: + m = self.name.capitalize() + ' requires a {} compiler' + raise DependencyException(m.format(self.language.capitalize())) + self.compiler = compilers[self.language] + else: + # Try to find a compiler that this dependency can use for compiler + # checks. It's ok if we don't find one. + for lang in ('c', 'cpp', 'objc', 'objcpp', 'fortran', 'd'): + self.compiler = compilers.get(lang, None) + if self.compiler: + break def get_compiler(self): return self.compiler @@ -309,8 +319,8 @@ class PkgConfigDependency(ExternalDependency): # multiple times in the same Meson invocation. class_pkgbin = None - def __init__(self, name, environment, kwargs): - super().__init__('pkgconfig', environment, None, kwargs) + def __init__(self, name, environment, kwargs, language=None): + super().__init__('pkgconfig', environment, language, kwargs) self.name = name self.is_libtool = False # Store a copy of the pkg-config path on the object itself so it is @@ -428,7 +438,7 @@ class PkgConfigDependency(ExternalDependency): # MSVC cannot handle MinGW-esque /c/foo paths, convert them to C:/foo. # We cannot resolve other paths starting with / like /home/foo so leave # them as-is so the user gets an error/warning from the compiler/linker. - if self.compiler.id == 'msvc': + if self.compiler and self.compiler.id == 'msvc': # Library search path if lib.startswith('-L/'): pargs = PurePath(lib[2:]).parts diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 41666a357..5bd9d9305 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -408,7 +408,7 @@ class MPIDependency(ExternalDependency): for pkg in pkgconfig_files: try: - pkgdep = PkgConfigDependency(pkg, environment, kwargs) + pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language) if pkgdep.found(): self.compile_args = pkgdep.get_compile_args() self.link_args = pkgdep.get_link_args() diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index dd045800f..bf74029c5 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -218,7 +218,8 @@ class QtBaseDependency(ExternalDependency): kwargs['required'] = False modules = OrderedDict() for module in mods: - modules[module] = PkgConfigDependency(self.qtpkgname + module, self.env, kwargs) + modules[module] = PkgConfigDependency(self.qtpkgname + module, self.env, + kwargs, language=self.language) for m in modules.values(): if not m.found(): self.is_found = False @@ -232,7 +233,8 @@ class QtBaseDependency(ExternalDependency): core = modules['Core'] else: corekwargs = {'required': 'false', 'silent': 'true'} - core = PkgConfigDependency(self.qtpkgname + 'Core', self.env, corekwargs) + core = PkgConfigDependency(self.qtpkgname + 'Core', self.env, corekwargs, + language=self.language) # Used by self.compilers_detect() self.bindir = self.get_pkgconfig_host_bins(core) if not self.bindir: -- cgit v1.2.3 From 61d1e9596ac97983617be0ddcb20f2afacc731bb Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Fri, 1 Dec 2017 19:08:44 +0530 Subject: dependencies: Also convert MinGW compile args For the same reason as the library paths. --- mesonbuild/dependencies/base.py | 45 ++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 7249b0165..d347735ec 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -412,12 +412,39 @@ class PkgConfigDependency(ExternalDependency): p, out = Popen_safe([self.pkgbin] + args, env=env)[0:2] return p.returncode, out.strip() + def _convert_mingw_paths(self, args): + ''' + MSVC cannot handle MinGW-esque /c/foo paths, convert them to C:/foo. + We cannot resolve other paths starting with / like /home/foo so leave + them as-is so the user gets an error/warning from the compiler/linker. + ''' + if not self.compiler or self.compiler.id != 'msvc': + return args + converted = [] + for arg in args: + pargs = [] + # Library search path + if arg.startswith('-L/'): + pargs = PurePath(arg[2:]).parts + tmpl = '-L{}:/{}' + elif arg.startswith('-I/'): + pargs = PurePath(arg[2:]).parts + tmpl = '-I{}:/{}' + # Full path to library or .la file + elif arg.startswith('/'): + pargs = PurePath(arg).parts + tmpl = '{}:/{}' + if len(pargs) > 1 and len(pargs[1]) == 1: + arg = tmpl.format(pargs[1], '/'.join(pargs[2:])) + converted.append(arg) + return converted + def _set_cargs(self): ret, out = self._call_pkgbin(['--cflags', self.name]) if ret != 0: raise DependencyException('Could not generate cargs for %s:\n\n%s' % (self.name, out)) - self.compile_args = shlex.split(out) + self.compile_args = self._convert_mingw_paths(shlex.split(out)) def _set_libs(self): env = None @@ -434,21 +461,7 @@ class PkgConfigDependency(ExternalDependency): (self.name, out)) self.link_args = [] libpaths = [] - for lib in shlex.split(out): - # MSVC cannot handle MinGW-esque /c/foo paths, convert them to C:/foo. - # We cannot resolve other paths starting with / like /home/foo so leave - # them as-is so the user gets an error/warning from the compiler/linker. - if self.compiler and self.compiler.id == 'msvc': - # Library search path - if lib.startswith('-L/'): - pargs = PurePath(lib[2:]).parts - if len(pargs) > 1 and len(pargs[1]) == 1: - lib = '-L{}:/{}'.format(pargs[1], '/'.join(pargs[2:])) - # Full path to library or .la file - elif lib.startswith('/'): - pargs = PurePath(lib).parts - if len(pargs) > 1 and len(pargs[1]) == 1: - lib = '{}:/{}'.format(pargs[1], '/'.join(pargs[2:])) + for lib in self._convert_mingw_paths(shlex.split(out)): # If we want to use only static libraries, we have to look for the # file ourselves instead of depending on the compiler to find it # with -lfoo or foo.lib. However, we can only do this if we already -- cgit v1.2.3 From 387b5e67a03ad9ea2c17431417293cc3561badb6 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 2 Dec 2017 02:28:29 +0530 Subject: linkers: Return a Copy of VisualStudioLinker always_args Otherwise people will accidentally append to it. --- mesonbuild/linkers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index e0554e0d8..de788b7b6 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -40,10 +40,10 @@ class VisualStudioLinker(StaticLinker): return [] def get_always_args(self): - return VisualStudioLinker.always_args + return VisualStudioLinker.always_args[:] def get_linker_always_args(self): - return VisualStudioLinker.always_args + return VisualStudioLinker.always_args[:] def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] -- cgit v1.2.3 From 3851867a0634c5bd064f3e06ee796b6d17082975 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 2 Dec 2017 02:41:37 +0530 Subject: dependencies: Always convert MinGW paths to MSVC on Windows The MinGW toolchain can read MinGW paths, but Python cannot and we sometimes need to parse the libs and cflags manually (for static-only library searching, for instance). The MinGW toolchain can always read Windows paths with `/` as path separater, so just use that. --- mesonbuild/dependencies/base.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index d347735ec..cdeaf5edb 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -414,11 +414,12 @@ class PkgConfigDependency(ExternalDependency): def _convert_mingw_paths(self, args): ''' - MSVC cannot handle MinGW-esque /c/foo paths, convert them to C:/foo. - We cannot resolve other paths starting with / like /home/foo so leave - them as-is so the user gets an error/warning from the compiler/linker. + Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo + paths so convert them to C:/foo. We cannot resolve other paths starting + with / like /home/foo so leave them as-is so that the user gets an + error/warning from the compiler/linker. ''' - if not self.compiler or self.compiler.id != 'msvc': + if not mesonlib.is_windows(): return args converted = [] for arg in args: -- cgit v1.2.3