Merge pull request #7757 from dcbaker/submit/curses-dependency

Extend the Curses dependency to use config tools and hand rolled search
pull/7801/head
Dylan Baker 5 years ago committed by GitHub
commit ce2d927a79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      azure-pipelines.yml
  2. 12
      docs/markdown/Dependencies.md
  3. 4
      docs/markdown/snippets/curses-dependency-improvements.md
  4. 2
      mesonbuild/dependencies/dev.py
  5. 95
      mesonbuild/dependencies/misc.py
  6. 6
      test cases/frameworks/31 curses/meson.build
  7. 6
      test cases/frameworks/31 curses/meson_options.txt
  8. 11
      test cases/frameworks/31 curses/test.json

@ -150,15 +150,18 @@ jobs:
gccx86ninja:
MSYSTEM: MINGW32
MSYS2_ARCH: i686
MSYS2_CURSES: ncurses
compiler: gcc
gccx64ninja:
MSYSTEM: MINGW64
MSYS2_ARCH: x86_64
MSYS2_CURSES: pdcurses
MESON_RSP_THRESHOLD: 0
compiler: gcc
clangx64ninja:
MSYSTEM: MINGW64
MSYS2_ARCH: x86_64
MSYS2_CURSES:
compiler: clang
variables:
MSYS2_ROOT: $(System.Workfolder)\msys64
@ -184,6 +187,7 @@ jobs:
mingw-w64-$(MSYS2_ARCH)-python3-setuptools ^
mingw-w64-$(MSYS2_ARCH)-python3-pip ^
%TOOLCHAIN%
if not "%MSYS2_CURSES%" == "" ( %MSYS2_ROOT%\usr\bin\pacman --noconfirm --needed -S mingw-w64-$(MSYS2_ARCH)-$(MSYS2_CURSES) )
%MSYS2_ROOT%\usr\bin\bash -lc "python3 -m pip --disable-pip-version-check install gcovr jsonschema pefile"
displayName: Install Dependencies
- script: |

@ -615,6 +615,18 @@ on these OSes to link with the bundled version.
*New in 0.54.0* the `system` method.
## Curses
*(Since 0.54.0)*
Curses (and ncurses) are a cross platform pain in the butt. Meson wraps up
these dependencies in the `curses` dependency. This covers both `ncurses`
(preferred) and other curses implementations.
`method` may be `auto`, `pkg-config`, `config-tool`, or `system`.
*New in 0.56.0* The `config-tool` and `system` methods.
<hr>
<a name="footnote1">1</a>: They may appear to be case-insensitive, if the
underlying file system happens to be case-insensitive.

@ -0,0 +1,4 @@
## Improvements for the builtin curses dependency
This method has been extended to use config-tools, and a fallback to
find_library for lookup as well as pkg-config.

@ -480,7 +480,7 @@ class ZlibSystemDependency(ExternalDependency):
for lib in libs:
l = self.clib_compiler.find_library(lib, environment, [])
h = self.clib_compiler.has_header('zlib.h', '', environment, dependencies=[self])
if l and h:
if l and h[0]:
self.is_found = True
self.link_args = l
break

@ -32,7 +32,7 @@ from .base import (
if T.TYPE_CHECKING:
from ..environment import Environment, MachineChoice
from .base import DependencyType # noqa: F401
from .base import DependencyType, Dependency # noqa: F401
@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE})
@ -404,16 +404,101 @@ class ShadercDependency(ExternalDependency):
return [DependencyMethods.SYSTEM, DependencyMethods.PKGCONFIG]
@factory_methods({DependencyMethods.PKGCONFIG})
class CursesConfigToolDependency(ConfigToolDependency):
"""Use the curses config tools."""
tool = 'curses-config'
# ncurses5.4-config is for macOS Catalina
tools = ['ncursesw6-config', 'ncursesw5-config', 'ncurses6-config', 'ncurses5-config', 'ncurses5.4-config']
def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
super().__init__(name, env, kwargs, language)
if not self.is_found:
return
self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
self.link_args = self.get_config_value(['--libs'], 'link_args')
class CursesSystemDependency(ExternalDependency):
"""Curses dependency the hard way.
This replaces hand rolled find_library() and has_header() calls. We
provide this for portability reasons, there are a large number of curses
implementations, and the differences between them can be very annoying.
"""
def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
super().__init__(name, env, kwargs)
candidates = [
('pdcurses', ['pdcurses/curses.h']),
('ncursesw', ['ncursesw/ncurses.h', 'ncurses.h']),
('ncurses', ['ncurses/ncurses.h', 'ncurses/curses.h', 'ncurses.h']),
('curses', ['curses.h']),
]
# Not sure how else to elegently break out of both loops
for lib, headers in candidates:
l = self.clib_compiler.find_library(lib, env, [])
if l:
for header in headers:
h = self.clib_compiler.has_header(header, '', env)
if h[0]:
self.is_found = True
self.link_args = l
# Not sure how to find version for non-ncurses curses
# implementations. The one in illumos/OpenIndiana
# doesn't seem to have a version defined in the header.
if lib.startswith('ncurses'):
v, _ = self.clib_compiler.get_define('NCURSES_VERSION', '#include <{}>'.format(header), env, [], [self])
self.version = v.strip('"')
if lib.startswith('pdcurses'):
v_major, _ = self.clib_compiler.get_define('PDC_VER_MAJOR', '#include <{}>'.format(header), env, [], [self])
v_minor, _ = self.clib_compiler.get_define('PDC_VER_MINOR', '#include <{}>'.format(header), env, [], [self])
self.version = '{}.{}'.format(v_major, v_minor)
# Check the version if possible, emit a wraning if we can't
req = kwargs.get('version')
if req:
if self.version:
self.is_found = mesonlib.version_compare(self.version, req)
else:
mlog.warning('Cannot determine version of curses to compare against.')
if self.is_found:
mlog.debug('Curses library:', l)
mlog.debug('Curses header:', header)
break
if self.is_found:
break
@staticmethod
def get_methods() -> T.List[DependencyMethods]:
return [DependencyMethods.SYSTEM]
@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM})
def curses_factory(env: 'Environment', for_machine: 'MachineChoice',
kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyType']:
candidates = [] # type: T.List['DependencyType']
kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List[T.Callable[[], 'Dependency']]:
candidates = [] # type: T.List[T.Callable[[], Dependency]]
if DependencyMethods.PKGCONFIG in methods:
pkgconfig_files = ['ncurses', 'ncursesw']
pkgconfig_files = ['pdcurses', 'ncursesw', 'ncurses', 'curses']
for pkg in pkgconfig_files:
candidates.append(functools.partial(PkgConfigDependency, pkg, env, kwargs))
# There are path handling problems with these methods on msys, and they
# don't apply to windows otherwise (cygwin is handled seperately from
# windows)
if not env.machines[for_machine].is_windows():
if DependencyMethods.CONFIG_TOOL in methods:
candidates.append(functools.partial(CursesConfigToolDependency, 'curses', env, kwargs))
if DependencyMethods.SYSTEM in methods:
candidates.append(functools.partial(CursesSystemDependency, 'curses', env, kwargs))
return candidates

@ -1,9 +1,13 @@
project('curses', 'c')
curses = dependency('curses', required: false)
curses = dependency('curses', required: false, method : get_option('method'), version : '>= 0')
if not curses.found()
error('MESON_SKIP_TEST: Curses library not found')
endif
exec = executable('basic', 'main.c', dependencies: curses)
# didn't run the test because in general graphics fail on CI
# this should fail
not_found = dependency('curses', required: false, method : get_option('method'), version : '> 1000000')
assert(not_found.found() == false)

@ -0,0 +1,6 @@
option(
'method',
type : 'combo',
choices : ['pkg-config', 'config-tool', 'system'],
value : 'pkg-config',
)

@ -0,0 +1,11 @@
{
"matrix": {
"options": {
"method": [
{ "val": "pkg-config" },
{ "val": "config-tool" },
{ "val": "system" }
]
}
}
}
Loading…
Cancel
Save