Merge pull request #7757 from dcbaker/submit/curses-dependency
Extend the Curses dependency to use config tools and hand rolled search
This commit is contained in:
commit
ce2d927a79
|
@ -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…
Reference in New Issue