aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2020-09-30 09:33:13 -0700
committerGitHub <noreply@github.com>2020-09-30 09:33:13 -0700
commitce2d927a7963caea26e858bead3123adc274606c (patch)
tree4759063f5127e8b80999705fa930ce1be7493b3e
parent137c3124e23f0f589c8855aafcd7897aa6d8c544 (diff)
parenta3106776a681201b166d019a3cf27cfe07f30a87 (diff)
downloadmeson-ce2d927a7963caea26e858bead3123adc274606c.zip
meson-ce2d927a7963caea26e858bead3123adc274606c.tar.gz
meson-ce2d927a7963caea26e858bead3123adc274606c.tar.bz2
Merge pull request #7757 from dcbaker/submit/curses-dependency
Extend the Curses dependency to use config tools and hand rolled search
-rw-r--r--azure-pipelines.yml4
-rw-r--r--docs/markdown/Dependencies.md12
-rw-r--r--docs/markdown/snippets/curses-dependency-improvements.md4
-rw-r--r--mesonbuild/dependencies/dev.py2
-rw-r--r--mesonbuild/dependencies/misc.py95
-rw-r--r--test cases/frameworks/31 curses/meson.build6
-rw-r--r--test cases/frameworks/31 curses/meson_options.txt6
-rw-r--r--test cases/frameworks/31 curses/test.json11
8 files changed, 133 insertions, 7 deletions
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index f0e238d..bd36aaa 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -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: |
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index efd8728..a8ada1d 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -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.
diff --git a/docs/markdown/snippets/curses-dependency-improvements.md b/docs/markdown/snippets/curses-dependency-improvements.md
new file mode 100644
index 0000000..237da4c
--- /dev/null
+++ b/docs/markdown/snippets/curses-dependency-improvements.md
@@ -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.
diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py
index 67d7e65..99c5c07 100644
--- a/mesonbuild/dependencies/dev.py
+++ b/mesonbuild/dependencies/dev.py
@@ -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
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 47694af..15055aa 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -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
diff --git a/test cases/frameworks/31 curses/meson.build b/test cases/frameworks/31 curses/meson.build
index 21483fb..796a0d8 100644
--- a/test cases/frameworks/31 curses/meson.build
+++ b/test cases/frameworks/31 curses/meson.build
@@ -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)
diff --git a/test cases/frameworks/31 curses/meson_options.txt b/test cases/frameworks/31 curses/meson_options.txt
new file mode 100644
index 0000000..e294e83
--- /dev/null
+++ b/test cases/frameworks/31 curses/meson_options.txt
@@ -0,0 +1,6 @@
+option(
+ 'method',
+ type : 'combo',
+ choices : ['pkg-config', 'config-tool', 'system'],
+ value : 'pkg-config',
+)
diff --git a/test cases/frameworks/31 curses/test.json b/test cases/frameworks/31 curses/test.json
new file mode 100644
index 0000000..3995695
--- /dev/null
+++ b/test cases/frameworks/31 curses/test.json
@@ -0,0 +1,11 @@
+{
+ "matrix": {
+ "options": {
+ "method": [
+ { "val": "pkg-config" },
+ { "val": "config-tool" },
+ { "val": "system" }
+ ]
+ }
+ }
+}