diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2019-05-21 21:57:05 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-21 21:57:05 +0300 |
commit | e9bd7d49bdc8c630cca3bf4cc02c437841b6aaf6 (patch) | |
tree | 3a7c2127d8ca71027248589d5d326c3bb23ace35 | |
parent | 60f34a1f51d455598143c1c55fd49a5eb1bb1fd6 (diff) | |
parent | 27b6c62ffdf51fed9a55ecfdd4ed47ac2ea79c1e (diff) | |
download | meson-e9bd7d49bdc8c630cca3bf4cc02c437841b6aaf6.zip meson-e9bd7d49bdc8c630cca3bf4cc02c437841b6aaf6.tar.gz meson-e9bd7d49bdc8c630cca3bf4cc02c437841b6aaf6.tar.bz2 |
Merge pull request #5372 from dcbaker/get_variable
Dependency.get_variable method
-rw-r--r-- | docs/markdown/Dependencies.md | 23 | ||||
-rw-r--r-- | docs/markdown/Reference-manual.md | 8 | ||||
-rw-r--r-- | docs/markdown/snippets/dependency_get_variable_method.md | 17 | ||||
-rw-r--r-- | mesonbuild/dependencies/base.py | 61 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 18 | ||||
-rw-r--r-- | test cases/common/219 dependency get_variable method/meson.build | 52 |
6 files changed, 178 insertions, 1 deletions
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index 50dbcf5..0cdd353 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -64,6 +64,29 @@ pkg-config files. Meson has autodetection support for some of these, and they are described [later in this page](#dependencies-with-custom-lookup-functionality). +# Arbitrary variables from dependencies that can be found multiple ways + +*Note* new in 0.51.0 + +When you need to get an arbitrary variables from a dependency that can be +found multiple ways and you don't want to constrain the type you can use +the generic `get_variable` method. This currently supports cmake, pkg-config, +and config-tool based variables. + +```meson +foo_dep = dependency('foo') +var = foo.get_variable(cmake : 'CMAKE_VAR', pkgconfig : 'pkg-config-var', configtool : 'get-var', default_value : 'default') +``` + +It accepts the keywords 'cmake', 'pkgconfig', 'pkgconfig_define', +'configtool', and 'default_value'. 'pkgconfig_define' works just like the +'define_variable' argument to `get_pkgconfig_variable`. When this method is +invoked the keyword corresponding to the underlying type of the dependency +will be used to look for a variable. If that variable cannot be found or if +the caller does not provide an argument for the type of dependency, one of +the following will happen: If 'default_value' was provided that value will be +returned, if 'default_value' was not provided then an error will be raised. + # Declaring your own You can declare your own dependency objects that can be used diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 2fc3d6a..477790b 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -2188,6 +2188,14 @@ an external dependency with the following methods: - includes: any include_directories - sources: any compiled or static sources the dependency has + - `get_variable(cmake : str, pkgconfig : str, configtool : str, + default_value : str, pkgconfig_define : [str, str]) *(Added in 0.51.0)* A + generic variable getter method, which repalces the get_*type*_variable + methods. This allows one to get the variable from a dependency without + knowing specifically how that dependency was found. If default_value is set and + the value cannot be gotten from the object then default_value is returned, + if it is not set then an error is raised. + ### `disabler` object A disabler object is an object that behaves in much the same way as diff --git a/docs/markdown/snippets/dependency_get_variable_method.md b/docs/markdown/snippets/dependency_get_variable_method.md new file mode 100644 index 0000000..aaeac9c --- /dev/null +++ b/docs/markdown/snippets/dependency_get_variable_method.md @@ -0,0 +1,17 @@ +## Dependency objects now have a get_variable method + +This is a generic replacement for type specific variable getters such as +`ConfigToolDependency.get_configtool_variable` and +`PkgConfigDependency.get_pkgconfig_variable`, and is the only way to query +such variables from cmake dependencies. + +This method allows you to get variables without knowing the kind of +dependency you have. + +```meson +dep = dependency('could_be_cmake_or_pkgconfig') +# cmake returns 'YES', pkg-config returns 'ON' +if ['YES', 'ON'].contains(dep.get_variable(pkg-config : 'var-name', cmake : 'COP_VAR_NAME', default_value : 'NO')) + error('Cannot build your project when dep is built with var-name support') +endif +``` diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 7836099..fd2a219 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -193,6 +193,13 @@ class Dependency: kwargs['method'] = method self.ext_deps.append(dep_type(env, kwargs)) + def get_variable(self, *, cmake: typing.Optional[str] = None, pkgconfig: typing.Optional[str] = None, + configtool: typing.Optional[str] = None, default_value: typing.Optional[str] = None, + pkgconfig_define: typing.Optional[typing.List[str]] = None) -> typing.Union[str, typing.List[str]]: + if default_value is not None: + return default_value + raise DependencyException('No default provided for dependency {!r}, which is not pkg-config, cmake, or config-tool based.'.format(self)) + class InternalDependency(Dependency): def __init__(self, version, incdirs, compile_args, link_args, libraries, whole_libraries, sources, ext_deps): @@ -518,6 +525,26 @@ class ConfigToolDependency(ExternalDependency): def log_tried(self): return self.type_name + def get_variable(self, *, cmake: typing.Optional[str] = None, pkgconfig: typing.Optional[str] = None, + configtool: typing.Optional[str] = None, default_value: typing.Optional[str] = None, + pkgconfig_define: typing.Optional[typing.List[str]] = None) -> typing.Union[str, typing.List[str]]: + if configtool: + # In the not required case '' (empty string) will be returned if the + # variable is not found. Since '' is a valid value to return we + # set required to True here to force and error, and use the + # finally clause to ensure it's restored. + restore = self.required + self.required = True + try: + return self.get_configtool_variable(configtool) + except DependencyException: + pass + finally: + self.required = restore + if default_value is not None: + return default_value + raise DependencyException('Could not get config-tool variable and no default provided for {!r}'.format(self)) + class PkgConfigDependency(ExternalDependency): # The class's copy of the pkg-config path. Avoids having to search for it @@ -928,6 +955,23 @@ class PkgConfigDependency(ExternalDependency): def log_tried(self): return self.type_name + def get_variable(self, *, cmake: typing.Optional[str] = None, pkgconfig: typing.Optional[str] = None, + configtool: typing.Optional[str] = None, default_value: typing.Optional[str] = None, + pkgconfig_define: typing.Optional[typing.List[str]] = None) -> typing.Union[str, typing.List[str]]: + if pkgconfig: + kwargs = {} + if default_value is not None: + kwargs['default'] = default_value + if pkgconfig_define is not None: + kwargs['define_variable'] = pkgconfig_define + try: + return self.get_pkgconfig_variable(pkgconfig, kwargs) + except DependencyException: + pass + if default_value is not None: + return default_value + raise DependencyException('Could not get pkg-config variable and no default provided for {!r}'.format(self)) + class CMakeTraceLine: def __init__(self, file, line, func, args): self.file = file @@ -1784,6 +1828,23 @@ set(CMAKE_SIZEOF_VOID_P "{}") return 'modules: ' + ', '.join(modules) return '' + def get_variable(self, *, cmake: typing.Optional[str] = None, pkgconfig: typing.Optional[str] = None, + configtool: typing.Optional[str] = None, default_value: typing.Optional[str] = None, + pkgconfig_define: typing.Optional[typing.List[str]] = None) -> typing.Union[str, typing.List[str]]: + if cmake: + try: + v = self.vars[cmake] + except KeyError: + pass + else: + if len(v) == 1: + return v[0] + elif v: + return v + if default_value is not None: + return default_value + raise DependencyException('Could not get cmake variable and no default provided for {!r}'.format(self)) + class DubDependency(ExternalDependency): class_dubbin = None diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index cb3aa8a..30be5ae 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -384,6 +384,7 @@ class DependencyHolder(InterpreterObject, ObjectHolder): 'name': self.name_method, 'get_pkgconfig_variable': self.pkgconfig_method, 'get_configtool_variable': self.configtool_method, + 'get_variable': self.variable_method, 'partial_dependency': self.partial_dependency_method, }) @@ -440,13 +441,21 @@ class DependencyHolder(InterpreterObject, ObjectHolder): pdep = self.held_object.get_partial_dependency(**kwargs) return DependencyHolder(pdep, self.subproject) + @FeatureNew('dep.get_variable', '0.51.0') + @noPosargs + @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'default', 'pkgconfig_define'}) + def variable_method(self, args, kwargs): + return self.held_object.get_variable(**kwargs) + + class InternalDependencyHolder(InterpreterObject, ObjectHolder): def __init__(self, dep, pv): InterpreterObject.__init__(self) ObjectHolder.__init__(self, dep, pv) self.methods.update({'found': self.found_method, - 'version': self.version_method, + 'get_variable': self.variable_method, 'partial_dependency': self.partial_dependency_method, + 'version': self.version_method, }) @noPosargs @@ -466,6 +475,13 @@ class InternalDependencyHolder(InterpreterObject, ObjectHolder): pdep = self.held_object.get_partial_dependency(**kwargs) return DependencyHolder(pdep, self.subproject) + @FeatureNew('dep.get_variable', '0.51.0') + @noPosargs + @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'default_variable', 'pkgconfig_define'}) + def variable_method(self, args, kwargs): + return self.held_object.get_variable(**kwargs) + + class ExternalProgramHolder(InterpreterObject, ObjectHolder): def __init__(self, ep): InterpreterObject.__init__(self) diff --git a/test cases/common/219 dependency get_variable method/meson.build b/test cases/common/219 dependency get_variable method/meson.build new file mode 100644 index 0000000..92b8704 --- /dev/null +++ b/test cases/common/219 dependency get_variable method/meson.build @@ -0,0 +1,52 @@ +project( + 'dependency get_variable', + ['c', 'cpp'], +) + +# Just some string that nothing should return +default = 'asufoiqwjtl;adjfbpiuqwoehtl;ajdfl;ghal;sdjg' + +dep = dependency('zlib', method: 'pkg-config', required : false) +if not dep.found() + warning('Skipping pkg-config tests as zlib is not avialable or is not pkg-config') +else + # Test for regular pkg-config + # We don't know what the value will be, but we know it should be the same + dep = dependency('zlib', method : 'pkg-config') + assert(dep.get_pkgconfig_variable('prefix') == dep.get_variable(pkgconfig : 'prefix'), + 'Got different values from get_pkgconfig_variable and get_variable(pkgconfig: )') + assert(dep.get_variable(pkgconfig : default, default_value : default) == default, + 'pkg-config didnt get default when we should have.') + assert(dep.get_variable(pkgconfig : 'prefix', default_value : default) != default, + 'pkg-config got default when we shouldnt have.') +endif + +dep_ct = dependency('llvm', method : 'config-tool', required : false) +if not dep_ct.found() + warning('Skipping config-tool tests as llvm is not available or llvm-config was not found.') +else + assert(dep_ct.get_configtool_variable('has-rtti') == dep_ct.get_variable(configtool : 'has-rtti'), + 'Got different values from get_configtool_variable and get_variable(configtool: )') + assert(dep_ct.get_variable(configtool : default, default_value : default) == default, + 'config-tool didnt get default when we should have.') + assert(dep_ct.get_variable(configtool : 'has-rtti', default_value : default) != default, + 'config-tool got default when we shouldnt have.') +endif + +dep_cm = dependency('llvm', method : 'cmake', required : false) +if not dep_cm.found() + warning('Skipping cmake tests as llvm is not available via the cmake finder.') +else + if dep_ct.found() + assert((dep_cm.get_variable(cmake : 'LLVM_ENABLE_RTTI') == 'ON') == (dep_ct.get_variable(configtool : 'has-rtti') == 'YES'), + 'RTTI information for cmake and config tools disagree') + endif + assert(dep_cm.get_variable(cmake : default, default_value : default) == default, + 'cmake didnt get default when we should have.') + assert(dep_cm.get_variable(cmake : 'LLVM_ENABLE_RTTI', default_value : default) != default, + 'cmake config-tool got default when we shouldnt have.') +endif + +idep = declare_dependency() +assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', default_value : default) == default, + 'Got something other than default from an internal dependency') |