diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2020-09-30 09:33:13 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-30 09:33:13 -0700 |
commit | ce2d927a7963caea26e858bead3123adc274606c (patch) | |
tree | 4759063f5127e8b80999705fa930ce1be7493b3e | |
parent | 137c3124e23f0f589c8855aafcd7897aa6d8c544 (diff) | |
parent | a3106776a681201b166d019a3cf27cfe07f30a87 (diff) | |
download | meson-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.yml | 4 | ||||
-rw-r--r-- | docs/markdown/Dependencies.md | 12 | ||||
-rw-r--r-- | docs/markdown/snippets/curses-dependency-improvements.md | 4 | ||||
-rw-r--r-- | mesonbuild/dependencies/dev.py | 2 | ||||
-rw-r--r-- | mesonbuild/dependencies/misc.py | 95 | ||||
-rw-r--r-- | test cases/frameworks/31 curses/meson.build | 6 | ||||
-rw-r--r-- | test cases/frameworks/31 curses/meson_options.txt | 6 | ||||
-rw-r--r-- | test cases/frameworks/31 curses/test.json | 11 |
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" } + ] + } + } +} |